<?php if (!defined('PmWiki')) exit();

/*
* @Description: This recipe extends forms capability on PmWiki, including:
* flexible data storage, retrieval, logging, deletion, and email processing.
* Also allows for an alternate way to register and authenticate members.
* And includes an enumerator, required fields, pulldown menus, textarea's, etc.
* For info, see docs at http://www.pmwiki.org/wiki/Cookbook/FASTData.  Enjoy!
* @author: Dan Vis aka Caveman <editor àt fast döt st>  
* @license http://www.gnu.org/licenses/gpl.html GNU General Public License
*/



# Action for activating this recipe
$HandleActions['data'] = 'Data';

# Function called by action = data
function Data() {
	global $WorkDir, $WikiDir, $pagename, $Version, $MessagesFmt;
	$nextpage = $pagename;
	$datapage = "Data-$pagename";  // default value for data page.
	$datamembers = "Data-Member";  // default group for user accounts.
	$pagecreated = "false";
	$count = "1000";  // start value for enumerator function.
	$r1 = array('%',"\n", '<');
	$r2 = array('%25','%0a','%3c');
	$m = "";  // holds system messages.

	foreach ($_POST as $field => $value) {
		switch ($field)	{
		
			case "NextPage" :
		    	$nextpage=FmtPageName($value, $pagename);
				break;

			case "DataPage" :
				if (substr($value, -2, 2) == ".#") {
					$g = substr($value, 0, strlen($value)-2);  // $g = group
					foreach(ListPages("/^$g\\.\\d/") as $n) {
						$n = substr($n,strlen($g)+1);
						$count = max($count,$n+1);
						}
					$value = $g . "." . $count;
					}
				$datapage=FmtPageName($value, $pagename);
				break;		   

			case "Required" :
				$required = true;
				$r = explode(",", $value);  // $r = required fields
				foreach ($r as $f => $v) {
					switch ($v) {
						case "Email" :
							if (!ereg("^.+@.+\..+$", $_POST[$v])) Warning("Invalid email address entered.");
							break;
						default :
							if ($_POST[$v] == "") Warning("Field \"$v\" required. Please try again.");
							break;
						}
					}
				break;

			case "Count" :
				$_POST[$field] = $_POST[$field] + 1;
				break;
						
			case "FormLink" :
				$_POST[$field] = "[[$pagename]]";
				break;

			case "SaveData" :
				if (substr($datapage, 0, 4) != "Data") {
					Warning("Invalid Data page.");
		   	   		break;
			    	}
				$data = '';
				$d = explode(",", $value);
				foreach ($d as $f => $v) {
					$vv = str_replace($r1, $r2, "$_POST[$v]");
					$data .= "$v=\"$vv\" %0a%0a"; 
					}
				if ((PageExists("$datapage")) or ($pagecreated == "true")) {
					$dr = fopen("$WorkDir/$datapage", "rb");
					$pc = fread($dr, filesize("$WorkDir/$datapage"));
					fclose($dr);
					$dc = explode("(:comment data:) %0a%0a", $pc);
					}
				else {
					$dc[1] = "";
					$dc[2] = "[[#Data]] %0a%0a";					
					$pagecreated = "true";
					}
				$dc[0] ="version=$Version ordered=1 urlencoded=1
title=$_POST[DataTitle]
text=(:Title $_POST[DataTitle]:)";
				$dc[1] = $data;
				$pc = "$dc[0](:comment data:) %0a%0a$dc[1](:comment data:) %0a%0a$dc[2](:comment data:) %0a%0a";
				if ($ds = fopen("$WorkDir/$datapage", "wb")){
					fwrite($ds,"$pc");
					fclose($ds); 
					PageIndexUpdate("$datapage");
					$m .= "Data has been successfully saved.  ";
					}
				break;

			case "LogData" :
				if (substr($datapage, 0, 4) != "Data") {
					Warning("Invalid Data page.");
		   	   		break;
			    	}
				$data = '';
				$prepend = substr($value, 0, 1);
				if ($prepend == "<") $value = substr($value, 1);
				$d = explode(",", $value);
				foreach ($d as $f => $v) {
					$vv = str_replace($r1, $r2, "$_POST[$v]");
					$data .= "$vv %0a"; 
					}
				if ((PageExists("$datapage")) or ($pagecreated == "true")) {
					$dr = fopen("$WorkDir/$datapage", "rb");
					$pc = fread($dr, filesize("$WorkDir/$datapage"));
					fclose($dr);
					$dc = explode("(:comment data:) %0a%0a", $pc);
					}
				else {
					$dc[1] = "";
					$dc[2] = "[[#Data]] %0a%0a";					
					$pagecreated = "true";
					}
				$dc[0] ="version=$Version ordered=1 urlencoded=1
title=$_POST[DataTitle]
text=(:Title $_POST[DataTitle]:)";
				if ($prepend == "<") $dc[2] = "[[#Data]] %0a%0a" . $data . substr($dc[2], 16);
				else $dc[2] .= $data;
				$pc = "$dc[0](:comment data:) %0a%0a$dc[1](:comment data:) %0a%0a$dc[2](:comment data:) %0a%0a";
				if ($ds = fopen("$WorkDir/$datapage", "wb")){
					fwrite($ds,"$pc");
					fclose($ds); 
					PageIndexUpdate("$datapage");
					$m .= "Data log successfully updated.  ";					
					}
				break;

			case "EmailData" :
				$data = '';
				if ($_POST[EmailTo] == "") Warning("No email \"to\" value entered.  Email not sent.");
				if ($_POST[EmailFrom] == "") Warning("No email \"from\" value entered.  Email not sent.");
				if ($_POST[Subject] == "") Warning("No email subject entered.  Email not sent.");
				$d = explode(",", $value);
				foreach ($d as $f => $v) {
					if (substr($v,0,1) == '-' ) {
						$v = substr($v,1);
						$data .= "$_POST[$v] 

"; 
						}
					else {
						$data .= "$_POST[$v]

";
						}
					}
				if ($data == "") Warning("No contents in message.  Email not sent.");
				mail($_POST[EmailTo], $_POST[Subject], $data, "From: $_POST[EmailFrom]");
				$m .= "Mail successfully sent to \"$_POST[EmailTo]\".  ";
				break;

			case "Delete" :
				if (substr($datapage, 0, 4) != "Data") {
					Warning("Invalid Data page.");
		   	   		break;
			    	}
				if ($_POST[Delete] == "Page") {
					if (PageExists("$datapage")) {
						$WikiDir->delete($datapage);
						$m .= "Data page has been successfully deleted.  ";
						break;
						}
					else Warning("Data not found.  Page not deleted.");
					}
				if ($_POST[Delete] == "Data") {
					if (PageExists("$datapage")) {
						$dr = fopen("$WorkDir/$datapage", "rb");
						$pc = fread($dr, filesize("$WorkDir/$datapage"));
						fclose($dr);
						$dc = explode("(:comment data:) %0a%0a", $pc);
						$dc[1] = "";
						$pc = "$dc[0](:comment data:) %0a%0a$dc[1](:comment data:) %0a%0a$dc[2](:comment data:) %0a%0a";
						$ds = fopen("$WorkDir/$datapage", "wb");
						fwrite($ds,"$pc");
						fclose($ds); 
						PageIndexUpdate("$datapage");
						$m .= "Data fields have been successfully deleted.  ";
						break;
						}
					else Warning("Data not found.  Data values not deleted.");
					}
				if ($_POST[Delete] == "Log") {
					if (PageExists("$datapage")) {
						$dr = fopen("$WorkDir/$datapage", "rb");
						$pc = fread($dr, filesize("$WorkDir/$datapage"));
						fclose($dr);
						$dc = explode("(:comment data:) %0a%0a", $pc);
						$dc[2] = "[[#Data]] %0a%0a";
						$pc = "$dc[0](:comment data:) %0a%0a$dc[1](:comment data:) %0a%0a$dc[2](:comment data:) %0a%0a";
						$ds = fopen("$WorkDir/$datapage", "wb");
						fwrite($ds,"$pc");
						fclose($ds); 
						PageIndexUpdate("$datapage");
						$m .= "Data log has been successfully deleted.  ";
						break;
						}
					else Warning("Data not found.  Log not deleted.");
					}
				break;
			
			case "Check" :  
				if ($value=="") Warning("No member name entered. Please try again.");
				if($value!=PageVar(MakePageName($pagename, $value), '$Name')) Warning("Invalid member name. Please try again.");
				if (PageExists("$datamembers.$value")) Warning("Member name already taken.  Please try again.");
				$nextpage=FmtPageName("$nextpage?myname=$value", $pagename);
				break;

			case "Login" :
				if (($value == "auto") and (! PageExists("$datamembers.$_POST[Member]"))) {
					AuthUserId($pagename, $_POST['Member']);
					$m .= "You have been successfully logged in.  ";					
					break;
					}
				if ($dr = fopen("$WorkDir/$datamembers.$_POST[Member]", "rb")){
					$pc = fread($dr, filesize("$WorkDir/$datamembers.$_POST[Member]"));
					fclose($dr);
					$dc = explode("(:comment data:) %0a%0a", $pc);
					$db = explode(" %0a%0a", $dc[1]);
					$dv = explode ("=", $db[1]);
					$pass1 = substr(urlencode(stripslashes($dv[1])),3,-3);
					$pass2 = $_POST['Password'];
					if ($pass1 == $pass2) {			   
						AuthUserId($pagename, $_POST['Member']);
						$m .= "You have been successfully logged in.  ";
						break;
						}
					Warning("Incorrect member name or password.");
					}
				break;
			}
		}
	$MessagesFmt[] = "<h5 class='wikimessage'>$[$m]</h5>";
	if ($nextpage == $pagename) {
		HandleBrowse($pagename);
		}
  	else Redirect(FmtPageName($nextpage, $pagename));
}


# Function to return error messages
function Warning($m) {
	global $pagename, $MessagesFmt;
	$MessagesFmt[] = "<h5 class='wikimessage'>$[$m]</h5>";
	HandleBrowse($pagename);
	die();
}



# Directive to retrieve data from another page
Markup('fastdata', '<{$var}', '/\(:data(.*?):\)/ei', "ReadData('$1')");

# Function called by directive to retrieve form data
function ReadData($l) {
	global $WorkDir, $FmtPV, $pagename;
	$r1 = array('%',"\n");
	$r2 = array('%25','%0a');
    $datapage = substr($l, 1);
	if (substr($datapage, -2, 2) == ".*") {
		$name = explode(".", $pagename);
		$datapage = substr($datapage,0,strlen($datapage)-1) . $name[1];
		}
	if (substr($datapage, 0, 4) != "Data") {
		return "invalid data parameter";
		}
	if (PageExists("$datapage")) {
		$dr = fopen("$WorkDir/$datapage", "rb");
		$pc = fread($dr, filesize("$WorkDir/$datapage"));
		fclose($dr);
		$dc = explode("(:comment data:) %0a%0a", $pc);
		$db = explode(" %0a%0a", $dc[1]);
		$i = 0;
		while ($i < count($db)-1) {
			$dv = explode ("=", $db[$i]);
			$value = stripslashes("$dv[1]");
			$value = str_replace($r2, $r1, $value);
			$FmtPV["$$dv[0]"] = $value;
			$i = $i + 1;
			}
		return;
		}
	return "data not found";
}


# Markups for pulldown menu's and textarea's
Markup('select', 'inline', '/\(:select (.*?):\\)/', '<select name=$1>');
Markup('option', 'inline',
     '/\\(:option (.*?):\\)/e',
     "Keep(PSS(\"<option value='$1'>\"))");
Markup('selectend', 'inline', '/\(:selectend:\\)/', '</select>');
Markup('textarea', 'inline', '/\(:textarea (.*?):\\)/', '<textarea name=$1>');
Markup('textareaend', 'inline', '/\(:textareaend:\\)/', '</textarea>');