1<?php
2if(!defined('DOKU_INC')) die();
3if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
4require_once(DOKU_PLUGIN.'syntax.php');
5
6class syntax_plugin_conform extends DokuWiki_Syntax_Plugin
7{
8    function getInfo()
9    {
10        return array(
11            'author' => 'William Fletcher',
12            'email'  => 'uiriamu.furecchaa@gmail.com',
13            'date'   => '2008-09-08',
14            'name'   => 'conform',
15            'desc'   => 'Creates HTML forms properly',
16            'url'    => 'http://thirdforces.internationalconspiracy.org/~ultraviolet/software/conform/',
17        );
18    }
19
20    function getType()
21    {
22        return 'substition';
23    }
24
25    function getPType()
26    {
27        return 'block';
28    }
29
30    function getSort()
31    {
32        return 999;
33    }
34
35    function connectTo($mode)
36    {
37        $this->Lexer->addEntryPattern('<CONFORM.*?>(?=.*?</CONFORM>)',$mode,'plugin_conform');
38    }
39
40    function postConnect()
41    {
42	$this->Lexer->addExitPattern('</CONFORM>', 'plugin_conform');
43    }
44
45    function handle($match, $state, $pos, &$handler)
46    {
47	switch ($state)
48	{
49	    case DOKU_LEXER_UNMATCHED:
50		if ( !$conform =& plugin_load('helper', 'conform') ) return false;
51		return $conform->conformExtract($match);
52		break;
53	}
54	return false;
55    }
56
57    function conformError(&$renderer, $message)
58    {
59	$renderer->doc .= '<span style="color:#FF0000;">'.$message.'</span><br>';
60    }
61
62    function conformCreateEmailInput($arg)
63    {
64	switch($arg[0])
65	{
66	    case 'Checkbox':
67		if ( isset($_POST["$arg[1]"]) )
68		{
69		    return "Yes";
70		}
71		else
72		{
73		    return "No";
74		}
75	    default:
76		return htmlspecialchars($_POST["$arg[1]"]);
77	}
78    }
79
80    function conformCreateInput($arg)
81    {
82	switch($arg[0])
83	{
84	    case 'Textbox':
85		$textbox  = "<input class=\"edit\" type=\"text\" name=\"$arg[1]\" style=\"width:".$arg[3]."px;\"";
86		$textbox .= " value=\"".htmlspecialchars($_POST["$arg[1]"])."\"";
87		$textbox .= ">";
88		return $textbox;
89	    case 'Textarea':
90		$textarea  = "<textarea class=\"edit\" name=\"$arg[1]\" rows=\"$arg[3]\" style=\"width:".$arg[4]."px;\">";
91		$textarea .= htmlspecialchars($_POST["$arg[1]"]);
92		$textarea .= "</textarea>";
93		return $textarea;
94		break;
95	    case 'Checkbox':
96		$checked = "";
97		if ( isset($_POST["id"]) )
98		{
99		    if ( $_POST["$arg[1]"] == "on" ) $checked = "checked";
100		}
101		else
102		{
103		    if ( $arg[3] == 1 ) $checked = "checked";
104		}
105		$checkbox  = "<input type=\"checkbox\" name=\"$arg[1]\" $checked>";
106		return $checkbox;
107		break;
108	    case 'Radio':
109		$radiocount = 0;
110		if ( ! isset($_POST["$arg[1]"]) ) $checked = " checked='checked'";
111		foreach ( $arg[3] as $value )
112		{
113		    if ( $value == $_POST["$arg[1]"] ) $checked = " checked='checked'";
114		    $radio .= "<input type=\"radio\" name=\"$arg[1]\" value=\"$value\"$checked>$value<br>";
115		    $checked = "";
116		}
117		return $radio;
118		break;
119	    case 'Select':
120		$select   = "<select name=\"$arg[1]\">";
121		$selected = "";
122		foreach ( $arg[3] as $value )
123		{
124		    if ( $value == $_POST["$arg[1]"] ) $selected = "selected";
125		    $select  .= "<option $selected>$value</option>";
126		    $selected = "";
127		}
128		$select .= "</select>";
129		return $select;
130	    default:
131		return "ERROR! ERROR! ERROR! Attempting to create an unsupported input maybe?";
132	}
133    }
134
135    function conformConstraintArgCheck($constraintname, $postname, $constraints, &$renderer)
136    {
137	foreach ( $constraints as $constraint )
138	{
139	    if ( $constraintname == $constraint[1] )
140	    {
141		if ( ! isset($_POST["$postname"]) )
142		{
143		    $this->conformError($renderer, "Constraint $postname checked against a value that wasn't posted!");
144		    return false;
145		}
146		$post = $_POST["$postname"];
147		$check = explode("=", $constraint[3], 2);
148		if ( ( $check[0] == 'maxLength' && strlen($post) > $check[1] ) ||
149                     ( $check[0] == 'minLength' && strlen($post) < $check[1] ) )
150		{
151		    $this->conformError($renderer, "$constraint[2]");
152		    return false;
153		}
154	    }
155	}
156	return true;
157    }
158
159    function conformConstraintCheck($constraints, $tables, &$renderer)
160    {
161	foreach ( $tables as $table )
162	{
163	    $args = &$table['args'];
164	    if ( count($args) == 0 ) continue;
165	    switch($table['mode'])
166	    {
167		case 0:
168		    foreach ( $args as $arg )
169		    {
170		    	switch($arg[0])
171		    	{
172			    case 'Submit':
173			    case 'Line':
174			    case 'Static':
175			    case 'Radio':
176			    case 'Checkbox':
177			    case 'Select':
178				break;
179			    default:
180				if ( $this->conformConstraintArgCheck($arg[1], "$arg[1]", $constraints, $renderer) == false )
181				{
182				    $this->conformConstrained = $arg[1];
183				    return false;
184				}
185			}
186		    }
187		    break;
188		case 1:
189		    if ( $table['complete'] == 0 ) break;
190		    $rows = $table['rows'];
191		    for ( $row = 1; $row <= $rows; $row++ )
192		    {
193			foreach ( $args as $arg )
194			{
195			    switch($arg[0])
196			    {
197				case 'Submit':
198				case 'Line':
199				case 'Static':
200				case 'Radio':
201				case 'Checkbox':
202				case 'Select':
203				    break;
204				default:
205				    if ( $this->conformConstraintArgCheck($arg[1], "$arg[1]_$row", $constraints, $renderer) == false )
206				    {
207					$this->conformConstrained = $arg[1];
208					return false;
209				    }
210			    }
211			}
212		    }
213		    break;
214	    }
215	}
216	return true;
217    }
218
219    function conformCreateDescription($text, $postname)
220    {
221	if ( isset($_POST["id"]) && $postname == $this->conformConstrained )
222	{
223	    return '<span style="color:#FF0000;">'.$text.'</span><br>';
224	}
225	return $text;
226    }
227
228    function render($format, &$renderer, $data)
229    {
230	global $ID;
231	if( $format == 'xhtml' )
232	{
233	    session_start();
234	    $formaction = DOKU_URL . "doku.php";
235	    $renderer->info['cache'] = false;
236	    if ( $data == false ) return false;
237	    if ( ! is_array($data) ) return false;
238	    if ( ! in_array($ID,  $data['idallow']) )
239	    {
240		$this->conformError($renderer, "Conform not allowed on this page! Please ask the admin to rectify this!");
241		return true;
242	    }
243	    if ( count($data['errors']) > 0 )
244	    {
245		foreach ( $data['errors'] as $error )
246		{
247		    $this->conformError($renderer, $error);
248		}
249	    }
250	    $tables = &$data['tables'];
251	    $email = false;
252	    if ( isset($_POST["id"]) )
253	    {
254		if ( $this->conformConstraintCheck($data['constraints'], $tables, $renderer) == true )
255		{
256		    $email = true;
257		}
258	    }
259	    if ( $email == false )
260	    {
261		$form .= "<form action=\"$formaction\" method=\"post\" accept-charset=\"utf-8\" enctype=\"multipart/form-data\">\n";
262		$_SESSION["conform_emailed"] = false;
263	    }
264	    $form .= "<table class=\"conform\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\n";
265	    $maxcolumns = $data['maxcolumns'];
266	    if ( $maxcolumns < 2 )
267	    {
268		$columns    = 2;
269		$maxcolumns = 2;
270	    }
271	    else
272	    {
273		$columns = $maxcolumns;
274	    }
275	    foreach ( $tables as $table )
276	    {
277		$args = &$table['args'];
278		if ( count($args) == 0 ) continue;
279		switch($table['mode'])
280		{
281		    case 0:
282			foreach ( $args as $arg )
283			{
284			    switch($arg[0])
285			    {
286				case 'Submit':
287				    $submit = $arg;
288				    break;
289				case 'Line':
290				    $form .= "<tr><td colspan=\"$columns\"><br></td></tr>\n";
291				    break;
292				case 'Static':
293				    $form .= "<tr><td colspan=\"$columns\">$arg[1]</td></tr>\n";
294				    break;
295				default:
296                                    if ( $email == false )
297                                    {
298					$input = $this->conformCreateInput($arg);
299                                    }
300                                    else
301                                    {
302					$input = $this->conformCreateEmailInput($arg);
303                                    }
304				    $form .= "<tr><td colspan=\"".($columns - 1 ).
305					              "\">".$this->conformCreateDescription($arg[2], $arg[1])."</td><td>$input<br></td></tr>\n";
306			    }
307			}
308			break;
309		    case 1:
310			if ( $table['complete'] == 0 ) break;
311			$rows       = $table['rows'];
312			$argcolumns = $table['columns'];
313			for ( $row = 0; $row <= $rows; $row++ )
314			{
315			    $form .= "<tr>\n";
316			    $argcount = 0;
317			    foreach ( $args as $arg )
318			    {
319				switch($arg[0])
320				{
321				    case 'Submit':
322					$submit = $arg;
323					break;
324				    case 'Line':
325					break;
326				    case 'Static':
327					break;
328				    default:
329					$colspan = "";
330					if ( $argcount == $argcolumns ) $colspan = " colspan=\"".($maxcolumns - $argcolumns)."\"";
331					if ( $row > 0 )
332					{
333					    $arg[1] .= "_$row";
334					    if ( $email == false )
335					    {
336						$input = $this->conformCreateInput($arg);
337					    }
338					    else
339					    {
340						$input = $this->conformCreateEmailInput($arg);
341					    }
342					    $form .= "<td$colspan>$input<br></td>\n";
343					}
344					else
345					{
346					    $form .= "<td$colspan>".$this->conformCreateDescription($arg[2], $arg[1])."</td>\n";
347					}
348				}
349				$argcount++;
350			    }
351			    $form .= "</tr>\n";
352			}
353			break;
354		}
355	    }
356	    if ( count($data['errors']) == 0 && $email == false )
357	    {
358		$form .= "<tr><td colspan=\"$maxcolumns\"><input class=\"button\" type=\"submit\" name=\"submit\" value=\"$submit[1]\"";
359		$form .= "style=\"width:".$submit[2]."px;\"></td></tr>\n";
360		$form .= "<input type=\"hidden\" name=\"id\" value=\"$ID\" />\n";
361		$form .= "</form>";
362	    }
363	    $form .= "</table>\n";
364	    if ( $email == true )
365	    {
366		$theboundary = md5(uniqid(""));
367		$header = "From: ".$this->getConf('conformFrom');
368		$header .= "\r\nMIME-Version: 1.0";
369		$header .= "\nContent-Type: text/html";
370		$header .= "\r\nX-Priority: 3";
371		$header .= "\r\nX-MSMail-Priority: Normal";
372		$header .= "\r\n";
373		if ( $_SESSION["conform_emailed"] == false )
374		{
375		    $emailform  = "<html><body>";
376		    $emailform .= "<style>";
377		    $emailform .= "body { padding: 0; border-spacing: 0; border-collapse: collapse; }";
378		    $emailform .= "table.conform { border: 1px solid #000000; padding: 0px; margin: 5px; border-spacing: 0; }";
379		    $emailform .= "table.conform td { border: 1px solid #000000; padding 0px; margin: 5px; border-spacing: 0; }";
380		    $emailform .= "</style>";
381		    $emailform .= $form;
382		    $emailform .= "</body></html>";
383		    mail($data['to'], $data['subject'], $emailform, $header);
384		}
385		$_SESSION["conform_emailed"] = true;
386	    }
387	    $renderer->doc .= $form;
388	    return true;
389	}
390	return false;
391    }
392}
393?>
394