<?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;
	$nextpage = $pagename;
	$datapage = "Data-" . $pagename;
	$datamembers = "Data-Member";  // default group for user accounts.
	$pagecreated = "false";
	$r1 = array('%',"\n", '<');
	$r2 = array('%25','%0a','%3c');
	$m = "";  // holds system messages.


	foreach ($_POST as $field => $value) {
		switch ($field)	{

			case "TestPage" :
				if ($value != "") $_POST[$field] = FixPage($_POST[$field]);
				break;
				
			case "NextPage" :
				if ($value != "") $nextpage = FixPage($_POST[$field]);
		    	$nextpage = FmtPageName($nextpage, $pagename);
				break;

			case "DataPage" :
				if ($value != "") $datapage = "Data-" . FixPage($_POST[$field]);
				$datapage=FmtPageName($datapage, $pagename);
				break;

			case "Required" :
				$required = true;
				$r = explode(",", $value);  // $r = required fields
				foreach ($r as $f => $v) {
					switch ($v) {
						case "NewMember" :
							if ($_POST[$v] == "") Warning("No member name entered. Please try again.");
							if (PageExists("$datamembers.$_POST[$v]")) Warning("Member name already taken.  Please try again.");
							if ($_POST[$v] != PageVar(MakePageName($pagename, $_POST[$v]), '$Name')) Warning("Invalid member name. Please try again.");
							break;
						case "Member" :
							if (! PageExists("$datamembers.$_POST[$v]")) Warning("Member name does not exist. Please try again.");
							break;
						case "Email" :
							if (!ereg("^.+@.+\..+$", $_POST[$v])) Warning("Invalid email address entered.");
							$_POST[Email] = str_replace("@", " (at) ", $_POST[Email]);
							break;
						default :
							if ($_POST[$v] == "") Warning("Field \"$v\" required. Please try again.");
							break;
						}
					}
				break;

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

			case "Date":
				$_POST[$field] = strftime("%B %d, %Y", time());
				break;
						
			case "DataNotes" :
				$d = explode(",", $value);
				foreach ($d as $f => $v) {
					$nextpage .= "?$v=$_POST[$v]";
					}
				break;

			case "DataCopy" :
				$d = explode(",", $value);
				foreach ($d as $f => $v) {
					$c = explode("|", $v);
					if ($c[2] == "") $_POST[$c[1]] = $_POST[$c[0]];
					else $_POST[$c[1]] = str_replace($c[2], $_POST[$c[0]], $_POST[$c[1]]);
					}
				break;

			case "SaveData" :
				$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";
					}
				$time = time();
				$dc[0] ="version=$Version ordered=1 urlencoded=1
author=$_POST[Author]
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
time=$time
title=$_POST[DataTitle]";
				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";
					}
				$time = time();
				$dc[0] ="version=$Version ordered=1 urlencoded=1
author=$_POST[Author]
text=(:Title $_POST[DataTitle]:)";
				if ($prepend == "<") $dc[2] = "[[#Data]] %0a%0a" . $data . "%0a" .  substr($dc[2], 16);
				else $dc[2] .= $data;
				$pc = "$dc[0](:comment data:) %0a%0a$dc[1](:comment data:) %0a%0a$dc[2]%0a(:comment data:) %0a%0a
time=$time
title=$_POST[DataTitle]";
				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 .= "$v = $_POST[$v] 

";
						}
					}
				if ($data == "") Warning("No contents in message.  Email not sent.");
				$EmailTo = str_replace(" (at) ", "@", $_POST[EmailTo]);
				$EmailFrom = str_replace(" (at) ", "@", $_POST[EmailFrom]);
				mail($EmailTo, $_POST[Subject], $data, "From: $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 "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();
}


# Function to fix pages
function FixPage($v) {
	global $pagename;
	$e = 1000;  // default start value for enumerator
	if (substr($v, 0, 1) == "~") { 
		$page = explode(".", $v);
		$v = substr($page[0], 1) . "." . $_POST[$page[1]];
		}
	if (substr($v, 0, 2) == "*.") {  
		$page = explode(".", $pagename);
		$v = $page[0] . substr($v,1);
		}
	if (substr($v, -2, 2) == ".*") {  
		$page = explode(".", $pagename);
		$v = substr($v, 0, strlen($v)-1) . $page[1];
		}
	if (substr($v, -1, 1) == "#") {
		$g = substr("Data-$v", 0, strlen($value)-2);
		foreach(ListPages("/^$g\\.\\d/") as $n) {
			$n = substr($n,strlen($g)+1);
			$e = max($e,$n+1);
			}
		$v = substr($g, 5) . "." . $e;
		}
	if (substr($v, -1, 1) == "=") {
		$g = substr("Data-$v", 0, strlen($value)-2);
		foreach(ListPages("/^$g\\.\\d/") as $n) {
			$n = substr($n,strlen($g)+1);
			$e = max($e,$n);
			}
		$v = substr($g, 5) . "." . $e;
		}
	if (substr($v, -2, 2) == ".@") {
		$g = substr("$v", 0, strlen($value)-2);
		$v = $g . "." . $GLOBALS['AuthId'];
		}
	return $v;
}



# 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>');



# To make a separate data-read recipe, move this section out.
# <?php if (!defined('PmWiki')) exit();

/*
* @Description: This recipe works closely with FAST Data to retrieve data:
* 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
*/



# 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;
	$passcode = "";  // set this to require passcode to read data
	if (($passcode == "") and ($l == "")) $l = " " . $pagename;
	if (($passcode != "") and (substr($l, strlen($l)-strlen($passcode)-1)) != "|$passcode") return "data access denied";
	if ($passcode != "") $l = substr($l, 0, strlen($l)-strlen($passcode)-1);
	$r1 = array('%',"\n");
	$r2 = array('%25','%0a');
    $datapage = FixPage(substr($l, 1));
	$datapage = "Data-" . $datapage;
	if (substr($datapage, -2, 2) == ".*") {
		$name = explode(".", $pagename);
		$datapage = substr($datapage,0,strlen($datapage)-1) . $name[1];
		}
	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";
}