Location: PHPKode > projects > BoltWire > barn/scripts/commands.php
<?php if (!defined('BOLTWIRE')) exit();

########################################
##  BOLTWIRE FORM COMMANDS            ##
##  Copyright 2010 Dan Vis            ##
##  See license.txt for details       ##
########################################

## BELOW ARE THE VARIOUS BOLT FORMS PROCESSING COMMANDS AVAILABLE IN ALPHATBETICAL ORDER
## AUTHKEY, BACKUP, COPY, CREATE, DELETE, EDIT, ENABLE, IF, INFO, JOIN, LIST, LOG, LOGIN, 
## LOGOUT, MAIL, MSG, PASSDATA, REGISTER, RENAME, REQUIRED, RESET, RESTORE, SAVEDATA, 
## SOURCE, STAMP, TARGET, TIME, UNSTAMP, UPLOAD, VALIDATE, WARN

function BOLTXauthkey($value, $field) {
## AN IMPORTANT SECURITY FEATURE WHICH ALLOWS SPECIFIED FORMS TO WRITE TO PAGES USERS DO NOT HAVE WRITE AUTHORIZATIONS
	if ($value == '') return;
	if (BOLTfilter($value, 'letters') == false) return;
	global $BOLTmemberships;
	$BOLTmemberships = $BOLTmemberships . ",key_$value";
	return $value;
	}

function BOLTXbackup($value, $field) {
## THIS COMMAND IS USED TO TAKE A CSV LIST OF PAGES NAMES AND CREATE A BACKUP FILE. MANY PLUGINS HAVE ASSOCIATED BACKUP FILES WHICH ARE EXTRACTED TO YOUR SITE ON INSTALLATION. THIS FUNCTION IS HOW THOSE FILES ARE CREATED. IT IS NOT DESIGNED FOR FULL SITE BACKUPS
	global $BOLTarray, $pagesDir, $configDir;
	$BOLTbackupsDir = BOLTconfig('BOLTbackupsDir', 'backups');
	BOLTfixdir($BOLTbackupsDir);
	if ($value != '') {
		$list = BOLTfilter($value, 'csv');
		$p = explode(',', $list);
		foreach ($p as $pp) $pages[] = BOLTpageshortcuts($pp);
		}
	else {
		if (isset($BOLTarray['backuppattern'])) $pat = $BOLTarray['backuppattern'];
		elseif(isset($BOLTarray['backupgroup'])) $pat = '/^' . BOLTfilter($BOLTarray['backupgroup'], 'page') . '\.(.*?)/';
		else $pat = NULL;
		$pages = BOLTlistpages($pat);
		}
	foreach ($pages as $p) {
		if (BOLTexists($p)) {
			$pp = BOLTloadpage($p, '', 'data', true);
			$outpages[] = "$p: " . urlencode($pp);
			}
		}
	$tempArray = $BOLTarray;
	// this section allows you to backup pages from other directories as well, like graphics or config pages
	foreach ($tempArray as $f => $v) {
		if (substr($f, 0, 10) == 'backupdir_') {
			$dir = substr($f, 10);
			$list = BOLTcsv(BOLTfilter($v, 'csv'));
			$pages = explode(',', $list);
			foreach ($pages as $p) {
				$pp = BOLTloadpage($p, $dir, 'data', true);
				if (file_exists("$dir/$p")) $outpages[] = "$dir::$p: " . urlencode($pp);
				}
			}
		}
	$content = implode("\n", $outpages);
	if (isset($BOLTarray['backupname'])) {
		$name = str_replace('.backup', '', $BOLTarray['backupname']);
		$name = BOLTfilter($name, 'letters') . '.backup';
		}
	if ($name == '') $name = strftime("%Y_%m_%d_%H%M") . ".backup";
	$page = fopen("$BOLTbackupsDir/$name", "wb");
    fwrite($page, $content);
    fclose($page); 
	BOLTmsg('backup_success');
	return $value;
	}

function BOLTXcounter($value, $field) {
## SIMPLE COMMAND USED TO TAP INTO THE COUNTER FUNCTION (BOLTFcounter). CAN BE USED FOR SIMPLE MATH MANIPULATIONS
	return BOLTcomm2func("$value  output=true", $field);
	}

function BOLTXcopy($value, $field) {
## CREATES DUPLICATES OF EXISTING PAGES, EVEN COPIES DATA, ETC. FORMAT OF $value LOOKS LIKE oldpage|newpage
	BOLTXrename($value, $field, 'copy');
	return $value;
	}

function BOLTXcreate($value, $field) {
## WRITES CONTENT ($value) TO A PAGE THAT DOES NOT EXIST
	global $BOLTid, $target;
	if (!BOLTauth($target, $BOLTid, 'write')) BOLTabort('create_fail_auth');
	if (BOLTexists($target)) BOLTabort('create_fail_exists', "~$target");
	if ($BOLTarray['editlines'] !== 'false') $value = str_replace('\n', "\n", $value);
	BOLTsavepage($target, $value);
	BOLTmsg('create_success', "~$target");
	return $value;
    }

function BOLTXdelete($value, $field) {
## DELETES ONE OR MORE PAGES (CSV LIST)
	global $pagesDir, $pageLink, $BOLTid, $systemPath, $scriptURL, $BOLTindexPages;
	$BOLThtmlDir = BOLTconfig('BOLThtmlDir', 'html');
	$BOLTzonesDir = BOLTconfig('BOLTzonesDir', 'zones');
	if ($value == '') return;
	$value = trim((str_replace("\n", ',', $value)), ',');
	if (strpos($value, ",")) $p =  explode(",", $value);
	else $p[] = $value;
	foreach ($p as $i => $pp) {
		if (substr($pp, -1) == "*") {
			$g = substr($pp, 0, -1);
			$gg = BOLTlistpages("/^$g/");
			unset($p[$i]);
			foreach($gg as $ggg) $p[] = $ggg;
			}
		}
	$p = array_unique($p);
	foreach($p as $page) {
		$c = $c + 1;
		$page = BOLTpageshortcuts($page);
		$fpage = BOLTfolders($page);
		if (!BOLTauth($page, $BOLTid, 'write')) BOLTabort("delete_fail_auth_$c", "~$page");
		if (!BOLTexists($page)) BOLTmsg("delete_fail_exist_$c", "~$page");
		else {
			if (file_exists("$systemPath/$page") && $page != 'code.skin') {
				if (BOLTloadpage($page) != ' ') BOLTsavepage($page, ' '); 
				else unlink("$pagesDir/$fpage");
				}
			else unlink("$pagesDir/$fpage");
			if (file_exists("$BOLThtmlDir/$page.html")) unlink("$BOLThtmlDir/$page.html");
			if (file_exists("$BOLTzonesDir/$page"))	unlink("$BOLTzonesDir/$page");
			$BOLTindexPages[] = $page;
			BOLTmsg("delete_success_$c", "~$page");
			}
		}
	clearstatcache();
	return $value;
	}

function BOLTXedit($value, $field) {
## USED TO REWRITE PAGE CONTENT ($value) OF AN EXISTING PAGE. DOES NOT AFFECT DATA
	global $BOLTid, $target, $BOLTarray;
	if (!BOLTauth($target, $BOLTid, 'write')) BOLTabort('edit_fail_auth', "~$target");
	if ($value == '') $value = ' ';
	if ($BOLTarray['editlines'] !== 'false') $value = str_replace('\n', "\n", $value);
	BOLTsavepage($target, $value);
	BOLTmsg('edit_success');
	return $page;
	}

function BOLTXenable($value, $field) {
## THIS COMMAND TAKES A PLUGIN NAME AND ACTIVATES IT SITEWIDE ON SITE.CONFIG. TO LIMIT PLUGIN TO CERTAIN PAGES ONLY, YOU WILL NEED TO MANUALLY EDIT SITE.CONFIG OR USE A CONFIG FILE
	if ($value != 'true' && $value != 'false') return;
	$plugin = 'enable' . ucfirst(substr($field, 7));
	$config = BOLTloadpage('site.config');
	if ($value == 'true') {
		if (strpos(strtolower($config), strtolower($plugin)) !== false) preg_replace("/$plugin(: .*)?/mi", "$plugin", $config);
		else $config = "$config$plugin\n";
		BOLTmsg('plugin_enabled', '~' . substr($plugin, 6));
		}
	else {
		$config = preg_replace("/$plugin(: .*)?/mi", '', $config);
		BOLTmsg('plugin_disabled', '~' . substr($plugin, 6));
		}
	BOLTsavepage('site.config', $config);
	}

function BOLTXfilter($value, $field) {
## COMMAND TO ALLOW REPLACEMENTS OF $value ACCORDING TO RULES SET UP IN $BOLTmyFilter. COMES WITH A BUILT IN TITLE FILTER TO CONVERT PAGE TITLES TO ACCEPTABLE PAGE NAMES.
	global $BOLTmyFilter;
	$filter = substr($field, 7);
	if (strpos($filter, '_') !== false) $filter = substr($filter, 0, strpos($filter, '_'));
	if (is_array($BOLTmyFilter[$filter])) {
		foreach ($BOLTmyFilter[$filter] as $in => $out) {
			if (substr($in, 0, 1) == '/') $value = preg_replace($in, $out, $value);
			else $value = str_replace($in, $out, $value);
			}
		}
	return $value;
	}

function BOLTXfind($value, $field) {
## COMMAND FOR SCANNING ACTUAL PAGES FOR CONTENT. MANY POSSIBLE PARAMETERS. LIMIT PAGES BY PAGES, PATTERN, GROUP, INCLUDE, EXCLUDE, TYPE, FOLDER, DIR. SEARCH STRING,MARKUP,REGEX. ORGANIZE BY SORT,IF. OUTPUT IS TEMPLATE OR FMT
	global $query, $outarray, $pageLink;
	$BOLTfieldKey = BOLTconfig('BOLTfieldKey');
	$args = BOLTargs($value, 'x_find');
	$query = BOLTFfind($args);
	$query = BOLTdomarkup($query);
	while (preg_match('/\~\~([0-9]+)\~\~/', $query) == 1) $query = BOLTescape($query, false);
	$query = BOLTescape(BOLTdomarkup($query), false);
	session_start();
	$_SESSION[$BOLTfieldKey]['QUERY'] = $query;
	$_SESSION[$BOLTfieldKey]['LASTQUERY'][$pageLink] = $query;
	session_write_close();
	return implode(",", $outarray);
	}

function BOLTXif($value, $field) {
## THIS COMMAND ALLOWS YOU TO TAP INTO THE ENTIRE BOLTWIRE CONDITIONAL SYSTEM IN A FORM. FORMAT LOOKS LIKE [session if "equal a b ? field1=value1 , field2=value2 : field3=value3] WHICH MEANS IF A & B ARE EQUAL, FORM FIELDS 1 & 2 ARE ASSIGNED NEW VALUES. IF NOT FIELD 3 IS REASSIGNED
	global $BOLTarray;
	$BOLTcond = substr($value, 0, strpos($value, " ? "));
	$value = substr($value, strpos($value, " ? ") + 3);
	$BOLTacts[0] = '';
	if (strpos($value, ' : ') === false) $BOLTacts[1] = explode(' , ', $value);
	else {
		$BOLTacts[1] = explode(' , ', substr($value, 0, strpos($value, ' : ')));  //true
		$BOLTacts[0] = explode(' , ', substr($value, strpos($value, ' : ') + 3)); //false
		}
	$c = '0';
	if (BOLTMtrue1($BOLTcond, 'true') == 'true') $c = '1';
	if (!is_array($BOLTacts[$c])) $BOLTacts[$c] = array($BOLTacts[$c]);
	foreach ($BOLTacts[$c] as $act) {
		list($f,$v) = explode('=',$act,2);
		$BOLTarray[$f] = $v;
		}
	if ($c == '0') return 'true';
	return 'false';
	}

function BOLTXindex($value, $field) {
## SIMPLE COMMAND USED TO TAP INTO THE INDEXING FUNCTION (BOLTFindex). CAN BE USED IN A FORM TO INSTANTLY UPDATE PAGES WHEN THEY ARE MODIFIED
	$out = BOLTcomm2func($value, $field);
	return "The following pages have been indexed: $out";
	}

function BOLTXinfo($value, $field) {
## A COMMAND TO TAP INTO BOLTWIRE'S INFO VAR CAPABILITIES. VALUE IS THE PARAMETER STRING. SEE BOLTFinfo FOR MORE INFO ON POSSIBLE OPTIONS
	return BOLTcomm2func($value, $field);
	}

function BOLTXjoin($value, $field) {
## THIS COMMAND ADDS MEMBERS IN FORM FIELD "members" AND ADDS TO GROUP $value.  USE +MEMBER1,-MEMBER2 TO ADD AND DROP MEMBERS FROM THE LIST. I SHOULD CHANGE THIS TO USE FIELD NAMES LIKE JOIN_CHESSCLUB AND LET VALUE BE CSV LIST
	global $BOLTarray, $BOLTid;
	if ($value == '') return;
	$page = BOLTpageshortcuts("@.$value");
	if (!BOLTauth($page, $BOLTid, 'write')) BOLTabort('join_fail_auth');
	$members = $BOLTarray['members'];
	if ($members == '') return $value;
	$oldgroup = BOLTloadpage($page);
	$oldgroup = str_replace("\n", ",", $oldgroup);
	if ((substr($members, 0, 1) == "+") || (substr($members, 0, 1) == "-")) $out = BOLTcsv($members, $oldgroup);
	else $out = BOLTcsv($members, '');
	$newgroup = str_replace(",", "\n", $out);
	BOLTsavepage($page, $newgroup);
	BOLTmsg('join_success');
	return $value;
	}

function BOLTXlist($value, $field) {
## A POWERFUL COMMAND FOR TAKING A CSV LIST, CLEANING IT UP. IF +/- USED BEFORE LIST ITEMS MERGES WITH EXISTING LIST. NEXT, TAPS INTO THE LIST FUNCTION TO GENERATE TEMPLATED OR FORMATTED OUTPUT. 
	if ($value == '') return;
	global $BOLTarray, $target;
	$data = substr($field, 5);
	if (strpos($value, '=') === false) {
		if ((substr($value, 0, 1) == "+") || (substr($value, 0, 1) == "-")) {
			$current = BOLTvars("$target:$data");
			$value = BOLTcsv($value, $current);
			}
		$value = '\'' . str_replace('\'', '&#39;', $value) . '\' fmt=csv';
		}
	if (strpos($value, 'fmt=') === false && strpos($value, 'template=') === false) $value = "$value fmt=csv";
	$value = BOLTcomm2func($value, $field);
	$data = substr($field, 5);
	if ($data != '') $BOLTarray[$data] = BOLTcsv($value);
	return $value;
	}

function BOLTXlog($value, $field) {
## THIS IS THE COMMAND THAT ALLOWS YOU TO TAP INTO THE LOG FUNCTION. VERY POWERFUL OPTIONS. SEE BOLTFlog AND BOLTlog FOR MORE INFORMATION
	if (strpos($value, '=') === false) $value = 'content=\'' . str_replace('\'', '&#39;', $value) . '\'';
	return BOLTcomm2func($value, $field);
	}

function BOLTXlogin($value, $field) {
## HERE'S THE COMMAND THAT TAKES A MEMBER AND PASSWORD FORM VALUE AND AUTHENTICATES AGAINST THE USER PROFILE DATA. CAN HANDLE ENCRYPTED OR UNENCRYPTED VALUES, AND AUTOMATIC LOGINS. AFTER AUTHENTICATED ALL GROUP MEMBERSHIPS ARE DETERMINED AND PROPER PERMISSIONS ASSIGNED
	global $pageLink, $BOLTarray, $BOLTid, $BOLTmember, $BOLTfieldKey;
	$BOLTloginPages = BOLTconfig('BOLTloginPages', 'login');
	if ($BOLTid != '') BOLTabort('login_problem');
	if (strpos($BOLTarray['member'], '@')) {
		$page = BOLTFsearch(Array('data'=>"email=$BOLTarray[member]", 'group'=>$BOLTloginPages, 'count'=>1, 'join'=>'', 'fmt'=>'{+p}'), 'COMMAND', false);
		$member = substr($page, strlen($BOLTloginPages) + 1);
		}
	else {
		$member = BOLTfilter(BOLTutf2url($BOLTarray['member']), 'csv');
		$page = BOLTpageshortcuts("$BOLTloginPages.$member");
		}
	$id = substr($page, strlen($BOLTloginPages) + 1);
	if (isset($BOLTarray['name'])) $member = BOLTfilter($BOLTarray['name'], 'csv');
	else {
		$name = BOLTvars("$page:member", false);
		if ($name != '') $member = $name;
	 	}
	$BOLTarray['member'] = $member;
	$pass1 = BOLTvars("$page:password", false);
	$pass2 = $BOLTarray['password'];
	if ((($pass1 == $pass2 || $pass1 == BOLTcrypt($pass2)) && ($pass1 != ''))){
//	if ($pass1 == BOLTcrypt($pass2) && $pass1 != '') {
		session_start();
		$_SESSION[$BOLTfieldKey]['ID']['id'] = $id;
		$_SESSION[$BOLTfieldKey]['ID']['member'] = $member;
		session_write_close();
		$BOLTid = $id;
		$BOLTmember  = $member;
		$memberships = BOLTFmemberships(Array('msg_func_memberships'=>'false'));
		BOLTmsg('login_success', "~$member");
//		setcookie('cache', $memberships, time() + 86000);
		}
	else BOLTabort('login_fail');
	return $value;
	}

function BOLTXlogout($value, $field) {
## DELETES LOGIN SESSION INFORMATION FROM USER
	session_start();
	$_SESSION = array();
	if (isset($_COOKIE[session_name()])) setcookie(session_name(), '', time() - 100000, '/');
	session_destroy();
	BOLTmsg('logout_success');
//	setcookie('cache', '', time() - 100000);
	return $value;
	}

function BOLTXmail($value, $field) {
## HERE IS THE COMMAND THAT TAPS INTO THE MAIL FUNCTION, FOR SENDING EMAIL. SEE BOLTFmail FOR MORE DETAILS
	BOLTmsg('email', BOLTescape(BOLTcomm2func($value, $field), false));
	}

function BOLTXmsg($value, $field) {
## YOU CAN USE THIS COMMAND TO TAP INTO BOLTWIRE'S MESSAGING SYSTEM, EITHER CLEARING MESSAGES, MODIFYING SYSTEM MESSAGES, OR GENERATING YOUR OWN MESSAGES. VERY FLEXIBLE
	if ($field == 'msg') BOLTmsg('clear', $value);
	else BOLTmsg(substr($field, 4), $value);
	return $value;
	}

function BOLTXpassdata($value, $field) {
## THIS COMMANDS TAKES A STRING OF FIELD NAMES AND APPENDS THEM ALL TO THE NEXTPAGE URL AS GET VAR'S, ALONG WITH THEIR SPECIFIED VALUES (URL ENCODED, OF COURSE)
	$value = BOLTfilter($value, 'csv');
	if ($value == '') return $value;
	global $BOLTarray;
	$f = explode(",", $value);
	foreach ($f as $ff) {
		if ((isset($BOLTarray[$ff])) && ($BOLTarray[$ff] != '')) $passdata .= "&amp;$ff=" . urlencode($BOLTarray[$ff]);
		}
	return $passdata;
	}

function BOLTXregister($value, $field) {
## JUST A SHORTCUT FUNCTION FOR USER REGISTRATION. DOES SEVERAL BASIC CHECKS OF USER INPUT. IF ALL LOOKS OK, CREATES USER PROFILE AND LOGS THEM IN. TAKES A CSV LIST OF FIELDS AND SAVES THEM AS DATA VALUES TO USER PROFILE (OR SPECIFIED IN REGISTERPAGE). DOES NOT SEEM TO ASSIGN GROUP MEMBERSHIPS.
	global $BOLTarray, $BOLTid, $target;
	$BOLTloginPages = BOLTconfig('BOLTloginPages', 'login');
	if (!isset($BOLTarray['member'])) BOLTabort('register_no_member');
	if ($BOLTarray['member'] == "") BOLTabort('register_member_blank');
	$logingroup = $BOLTloginPages;
	$page = BOLTpageshortcuts("$logingroup.$BOLTarray[member]");
	if (! BOLTfilter($page, 'page')) BOLTabort('register_invalid_name');
	if (BOLTexists($page)) BOLTabort('register_member_exists');
	if (isset($BOLTarray['email']) && $BOLTarray['checkemail'] !== 'false') {
		if (preg_match('/^.+\@.+\..+$/', $BOLTarray['email']) == 0) BOLTabort('register_email_fails');
		$checkemail = BOLTFsearch(Array("email(=)$BOLTarray[email]", 'group'=>$BOLTloginPages), 'COMMAND', false);
		if ($checkemail != '') BOLTabort('register_email_exists');
		}
	if (! BOLTauth($page, $BOLTid, 'write')) BOLTabort('register_fail_auth');
	if (! isset($BOLTarray['password'])) BOLTabort('register_no_pass');
	if ($BOLTarray['password'] == '') BOLTabort('register_pass_blank');
	$tempPass = $BOLTarray['password'];
	if ($BOLTarray['loginfmt'] != 'plaintext') $BOLTarray['password'] = BOLTcrypt($BOLTarray['password']);
//	$BOLTarray['password'] = BOLTcrypt($BOLTarray['password']);
	if (isset($BOLTarray['registerpage'])) $page = BOLTpageshortcuts($BOLTarray['registerpage']);
	$tempLink = $target;
	$target = $page;
	BOLTXsavedata(str_replace('password', '', $value), 'savedata');
	BOLTsavedata(Array('password'=>$BOLTarray['password']), $target, false); 
	$target = $tempLink;
	$BOLTarray['password'] = $tempPass;
	if (BOLTexists($target)) BOLTmsg('register_success');
	else BOLTabort('register_fail');
	return $value;
	}

function BOLTXrename($value, $field, $rename='rename') {
## GIVES NEW NAME TO EXISTING PAGE, RETAINING ALL CONTENT AND DATA, ETC. FORMAT OF $value LOOKS LIKE oldpage|newpage
	global $BOLTindexPages, $pageLink, $pagesDir, $BOLTid, $systemPath;
	if (BOLTfilter(BOLTutf2url($value), 'csv') == '') BOLTabort("$rename_invalid_page");
	$p = explode("|", $value);
	$tempLink = $pageLink;
	$out = BOLTpageshortcuts($p[1]);
	if (!BOLTauth($out, $BOLTid, 'write')) {
		BOLTabort("$rename_fail_auth", "~$out");
		continue;
		}
	$BOLTindexPages[] = $out;
	$in = BOLTpageshortcuts($p[0]);
	if ($rename != 'copy') $BOLTindexPages[] = $in;
	$in = BOLTfolders($in);
	$pageLink = $in;
	$out = BOLTfolders($out);
	$pathin = $pagesDir;
	if (!BOLTexists($in)) BOLTmsg("$rename_fail_nofile", "~$in");
	elseif (file_exists("$pagesDir/$out")) BOLTmsg("$rename_fail_exists", "~$in~$out");
	else {
		if ((file_exists("$systemPath/$in")) && (! file_exists("$pathin/$in"))) $success = copy("$systemPath/$in", "$pagesDir/$out"); 
		else {
			if ($rename == 'copy') $success = copy("$pathin/$in", "$pagesDir/$out");
			else $success = rename("$pathin/$in", "$pagesDir/$out");
			}
		if(!$success) BOLTmsg("$rename_fail", "~$in");
		if($success) BOLTmsg("$rename_success", "~$in");
		}
	$pageLink = $tempLink;
	return $value;
	}

function BOLTXrequired($value, $field) {
## SIMPLE FORM VALIDATION. TAKES A CSV LIST OF FIELD NAMES AND ENSURES ALL FIELDS HAVE CONTENT
	$value = BOLTfilter($value, 'csv');
	if ($value == '') return;
	global $BOLTarray;
	$f = explode(",", $value);
	foreach ($f as $ff) {
		if ($BOLTarray[$ff] == '') $out = $out . "$ff, ";
		}
	if ($out != '') {
		$out = substr($out, 0, -2);
		BOLTabort('required', "~$out");
		}
	return $value;
	}

function BOLTXreset($value, $field) {
## SIMPLE COMMAND WHICH ALLOWS YOU TO RESET A FORM FIELD WITH A NEW VALUE. USEFUL FOR EXAMPLE, WHEN YOU NEED TO RETRIEVE DATA BASED ON USER INPUT
	if (strlen($field) <= 6) return $value;
	global $BOLTarray;
	$BOLTarray[substr($field, 6)] = $value;
	return $value;
	}

function BOLTXrestore($value, $field) {
## THE OPPOSITE OF THE BACKUP COMMAND -- EXTRACTS A BACKUP FILE AND INSTALLS IN SITE IF WRITE PERMISSION. USED IN COMBINATION WITH THE ENABLE COMMAND TO BOTH INSTALL AND ACTIVATE COMPLEX PLUGINS
	$value = BOLTfilter($value, 'page');
	if ($value == '') return;
	if (substr($value, -7) != '.backup') $value = "$value.backup";
	global $BOLTarray, $pagesDir, $pluginPath;
	if ($BOLTarray['restoredir'] == 'plugins') $dir = $pluginPath;
	else {
		$dir = BOLTconfig('BOLTbackupsDir');
		BOLTfixdir($dir);
		}
	$pages = BOLTloadpage($value, $dir, 'data');
	if ($pages == '') {
		BOLTmsg('restore_fail');
		$BOLTarray['restorepages'] = '';
		return;
		}
	if (strpos($pages, "\n~data~\n") !== false) {
		$data = substr($pages, strpos($pages, "\n~data~\n") + 8);
		$pages = substr($pages, 0, strpos($pages, "\n~data~\n"));
		$BOLTarray['restoredata'] = $data;
		}
	$p = explode ("\n", $pages);
	foreach ($p as $pp) {
		if (strpos($pp, "::") !== false) {
			$dir =  substr($pp, 0, strpos($pp, "::"));
			$pp = substr($pp, strpos($pp, "::") + 2);
			if (! file_exists($dir)) mkdir($dir);
			$page = substr($pp, 0, strpos($pp, ":"));
			}
		else {
			$dir = $pagesDir;
			if (! file_exists($dir)) mkdir($dir);
			$page = BOLTfolders(substr($pp, 0, strpos($pp, ":")));
			}
		$pp = substr($pp, strpos($pp, ": ") + 2);
		$content = urldecode($pp);
		$handle = fopen("$dir/$page", "wb");
	    fwrite($handle, $content);
	    fclose($handle);
		if ($dir != $pagesDir) $out[] = "$dir: $page";
		else $out[] = $page;
		}
	$pages = implode(", ", $out);
	$BOLTarray['restorepages'] = implode("\n", $out);
	BOLTmsg('restore_success', "~$pages");
	return $pages;
	}

function BOLTXsavedata($value, $field='') {
## THIS COMMAND TAKES A CSV LIST OF FIELD NAMES, AND SAVES THEM TO THE CURRENT PAGE TARGET ALONG WITH THEIR VALUES AS DATA. IF VALUE IS NULL, THE DATA FIELD IS REMOVED. DATA FIELDS NOT LISTED ARE IGNORED (IE, THEY REMAIN ON THE PAGE)
	global $BOLTarray, $target, $pageLink, $BOLTid;
//	$value = BOLTfilter($value, 'csv');
	if ($value == '') return;
	$x = explode(',', $value);
	foreach ($x as $xx) {
		$xx = trim($xx);
		if ($xx == '') continue;
		if (substr($xx, 0, 1) == '-') $data[substr($xx, 1)] = '';
		else $data[$xx] = $BOLTarray[$xx];
		}
	BOLTsavedata($data, $target);
	BOLTmsg('data_success');
	return $value;
	}

function BOLTXsearch($value, $field='') {
## COMMAND FOR SEARCHING INDEX. MANY POSSIBLE PARAMETERS. LIMIT PAGES BY PAGES, PATTERN, GROUP, INCLUDE, EXCLUDE, TYPE, FOLDER, DIR. SEARCH TEXT,DATA,LINK. ORGANIZE BY SORT,IF. OUTPUT IS TEMPLATE OR FMT
	global $query, $outarray, $pageLink, $BOLTfieldKey;
	$query = BOLTcomm2func($value, $field);
	if (preg_match('/^\~\~([0-9]+)\~\~$/', $query) == 0) {  // fmt's
		$query = BOLTdomarkupTable($query);
		$query = BOLTvspace($query);
		$query = BOLTescape($query, false);
		}
	$query = BOLTescape($query, false);
	session_start();
	$_SESSION[$BOLTfieldKey]['QUERY'] = $query;
	$_SESSION[$BOLTfieldKey]['LASTQUERY'][$pageLink] = $query;
	session_write_close();
	return $query;
	}

function BOLTXsource($value, $field) {
## THIS COMMAND TAPS INTO THE SOURCE FUNCTION (BOLTFsource) AND CAN BE USED TO RETRIEVE VARIOUS KINDS OF INFORMATION AT THE TIME OF FORM PROCESSING. SEE ALSO BOLTXreset.
	return BOLTcomm2func("page=$value escape=false", $field);
	}

function BOLTXstamp($value, $field) {
## THIS COMMAND TAKES A PAGE NAME AND CREATES A TIMESTAMPED BACKUP OF THE PAGE IN THE STAMPS DIR. TO REVERT TO A STAMPED VERSION, USE THE BOLTXunstamp COMMAND
	global $BOLTid, $pagesDir, $pageLink, $BOLTarray, $systemPath, $Token;
	$dir = BOLTconfig('BOLTstampsDir', 'stamps');
	BOLTfixdir($dir);
	$value = BOLTfilter(BOLTpageshortcuts($value), 'page');
	if ($value == '') $value = $pageLink;
	if(!BOLTexists($value)) {
		BOLTmsg('stamp_no_file', "~$value");
		return $value;
		}
	$content = BOLTloadpage($value, '', 'data');
	$content = $content . 'diff: ' . BOLTFdiff(Array(), '', false, true) . "\n~\n";
	$stamp = $value . "." . time();
	$page = fopen("$dir/$stamp", "wb");
	fwrite($page, $content);
	fclose($page); 
	if(file_exists("$dir/$stamp")) BOLTmsg('stamp_success', "~$value");
	else BOLTmsg('stamp_fail', "~$value");
// clear out too old, or too many stamps
	$BOLTstampsDir = BOLTconfig('BOLTstampsDir', 'stamps');
	$BOLTstampsExpire = BOLTconfig('BOLTstampsExpire');
	$BOLTstampsMax = BOLTconfig('BOLTstampsMax');
	if ($BOLTstampsExpire != '' || $BOLTstampsMax != '') {
		$time = time() - ($BOLTstampsExpire * 86400);
		$p = array_reverse(BOLTlistpages(NULL, $dir));
		foreach ($p as $i => $page) {
			if ($BOLTstampsExpire > 0 && substr($page, -10) < $time) unlink("$BOLTstampsDir/$page");
			$base = substr($page, 0, -11);
			$count[$base] = $count[$base] + 1;
			if ($BOLTstampsMax > 0 && $count[$base] > $BOLTstampsMax) unlink("$BOLTstampsDir/$page");
			}
		}
	return $value;
	}

function BOLTXtarget($value, $field) {
## THIS SETS THE TARGET PAGE FOR MANY COMMANDS LIKE CREATE, EDIT, SAVEDATA, ETC. BY DEFAULT IT IS THE CURRENT PAGE. TO MODIFY SEVERAL PAGES, USE TARGET_1, TARGET_2, ETC. YOU CAN DEFINE A $BOLTfixPage VARIABLE TO STRIP OUT CERTAIN CHARACTERS WHEN "FIX" IS IN THE FIELD NAME. TO DO UTF ENCODING OF PAGES SET UTFpages: true IN SITE.CONFIG
	global $target;
	if (strlen($field) > 7) $value = BOLTXfilter($value, $field);
	$target = BOLTpageshortcuts($value);
	if (BOLTfilter($target, 'page') == '') BOLTabort('invalid_page_name');
	return $target;
	}

function BOLTXtime($value, $field) {
## TIME COMMAND ALLOWS YOU TO GENERATE ALL KINDS OF OUTPUTS. VALUE SHOULD LOOK LIKE time|fmt. BY DEFAULT TIME IS CURRENT TIMESTAMP, BUT CAN BE ANY RECOGNIZABLE STRING, LIKE TOMORROW, OR +3 HRS. THE FMT CAN BE ANYTHING RECOGNIZED BY THE PHP FUNCTION STRFTIME (SEE PHP DOCS FOR DETAILS)
	global $BOLTtime;
	if (strpos($value, "|") === false) {
		if (is_numeric($value) && strlen($value) == 10) $time[0] == $value;
		else $time[0] = strtotime($value);
		if ($time[0] == '') $time[0] = $BOLTtime;
		}
	else {
		$time = explode("|", $value);
		if ($time[0] == '') $time[0] = $BOLTtime;
		else $time[0] = trim($time[0]);	
		if (! is_numeric($time[0]) || strlen($time[0]) != 10) $time[0] = strtotime($time[0]);
		}
	if ($time[1] == '') $time[1] = BOLTconfig('BOLTtimeFmt');
	if ($time[1] == '') return $time[0];
	return strftime($time[1], $time[0]);
	}

function BOLTXtouch($value, $field) {
## THIS COMMAND RESETS LASTMODIFIED TIME OF TARGET PAGE TO CURRENT TIME OR VALUE TIMESTAMP. USEFUL IN FORCING CACHES TO REFRESH.
	global $target, $pagesDir, $systemPath;
	if ($value == '') $value = time();
	else $value = strtotime($value);
	if (file_exists("$pagesDir/$target")) $success = touch("$pagesDir/$target", $value);
	if ($success) BOLTmsg('touch_success', "~$page");
	else BOLTmsg('touch_fail', "~$page");
	return $value;
	}

function BOLTXunstamp($value, $field) {
## THIS COMMAND TAKES A STAMP PAGE NAME AND RESTORES IT TO YOUR SITE
	if ($value == '') return;
	global $BOLTid, $pagesDir, $BOLTarray;
	$BOLTstampsDir = BOLTconfig('BOLTstampsDir', 'stamps');
	BOLTfixdir($BOLTstampsDir);
	$out = BOLTpageshortcuts($value);
	$in = substr($out, 0, -11);
	if (!BOLTauth($in, $BOLTid, 'write')) BOLTabort("unstamp_fail_auth", "~$value");
	$content = BOLTloadpage($out, $BOLTstampsDir);
	BOLTsavepage($in, $content, '', true, true, false);
	BOLTmsg('unstamp_success', "~$in");
	$BOLTarray['nextpage'] = $in;
	return $value;
	}

function BOLTXupload($value, $field) {
## THIS IS THE COMMAND USED TO UPLOAD A FILE. SEVERAL OPTIONS. MORE DOCUMENTATION NEEDED
	global $pageLink, $BOLTarray;
	$BOLTuploadMode = BOLTconfig('BOLTuploadMode');
	$BOLTuploadTypes = BOLTconfig('BOLTuploadTypes');
	$BOLTuploadSize = BOLTconfig('BOLTuploadSize');
	$BOLTfilesDir = BOLTconfig('BOLTfilesDir', 'files');
	BOLTfixdir($BOLTfilesDir, false);
	if (BOLTauth($pageLink, $BOLTid, 'uploads') == false) BOLTabort("upload_fail_auth");
	if ($BOLTuploadMode == 'true') $auth = true;
	if ($auth != true) BOLTmsg('upload_mode');
	$fn = "filename" . substr($field, 6);
   	if (isset($BOLTarray[$fn])) $filename = BOLTfilter($BOLTarray[$fn], 'page');
	else $filename = $_FILES[$field]['name'];
	if (BOLTconfig('BOLTuploadCase', 'true') != 'true') $filename = strtolower($filename);
	$fp = "filepath" . substr($field, 6);
   	if (isset($BOLTarray[$fp])) {
		$filepath = $BOLTfilesDir . '/' . BOLTfilter($BOLTarray[$fp], '-_a-z0-9');
		BOLTfixdir($filepath, false);		
		}
	else $filepath = $BOLTfilesDir;
	if ($_FILES[$field]['error'] != UPLOAD_ERR_OK) BOLTabort('upload_error', "~$filename");
	if ($_FILES[$field]['size'] > $BOLTuploadSize) BOLTabort('upload_fail_size', "~$filename");
	if (strpos($filename, '.') === false) BOLTabort('upload_no_ext');
	$type = substr(strrchr($filename, '.'), 1);
	if (strpos(strtolower(" ,$BOLTuploadTypes,"), strtolower(",$type,")) === false) BOLTabort('upload_fail_type', "~$type");
	if ($auth == true) $success = move_uploaded_file($_FILES[$field]['tmp_name'], "$filepath/$filename");
	else $success = true;
	if ($success) {
		chmod("$filepath/$filename", 0644);
		BOLTmsg('upload_success', "~$filename");
		}
	else BOLTmsg('upload_fail', "~$filename");
	clearstatcache();
	return $value;
	}

function BOLTXvalidate($value, $field) {
## AN ADVANCED COMMAND FOR MORE SOPHISTICATED FORM VALIDATAION, USING A REGEX PATTERN. VALUE SHOULD LOOK LIKE [session validate_field "/pattern/ ? field1=value1 , field2=value2 : field3=value3"]. FIELD SPECIFIES WHICH FIELD VALUE IS CHECKED. PATTERN IS A REGEX. IF IT MATCHES FIELD 1&2 ARE RESET TO NEW VALUES, IF IT FAILS FIELD 3 IS RESET. CAN TRIGGER ANY FORM ACTION
	global $BOLTarray;
	$BOLTcond = substr($value, 0, strpos($value, " ? "));
	$value = substr($value, strpos($value, " ? ") + 3);
	$BOLTacts[0] = '';
	if (strpos($value, " : ") === false) $BOLTacts[1] = explode(" , ", substr($value, strpos($value, " ? ")));
	else {
		$BOLTacts[1] = explode(" , ", substr($value, 0, strpos($value, " : "))); //true
		$BOLTacts[0] = explode(" , ", substr($value, strpos($value, " : ") + 3)); //false
		}
	$valfield = substr($field, 8);
	if (substr($valfield, 0, 1) == '_') $valfield = substr($valfield, 1);
	$c = "0";
	if (preg_match($BOLTcond, $BOLTarray[$valfield]) == 1) $c = "1"; // true
	if (!is_array($BOLTacts[$c])) $BOLTacts[$c] = array($BOLTacts[$c]);
	foreach ($BOLTacts[$c] as $act) {
		list($f,$v) = explode('=',$act,2);
		$BOLTarray[$f] = $v;
		}
	if ($c == 1) return 'true';
	return 'false';
	}

function BOLTXwarn($value, $field) {
## SUBMITS A MESSAGE TO THE USER AND ABORTS FORM PROCESSING IMMEDIATELY, OFTEN USED WITH IF OR VALIDATE TO REQUIRE VARIOUS USER INPUT
	if ($value == '') return;
	$id = substr($field, 5);
	if ($id == '') $id = 'warn';
	BOLTabort($id, $value);
	}
Return current item: BoltWire