diff --git a/html/BTC.png b/html/BTC.png
new file mode 100644
index 00000000..dcc56561
Binary files /dev/null and b/html/BTC.png differ
diff --git a/pool/base.php b/pool/base.php
index 8bfa50ab..860de7c6 100644
--- a/pool/base.php
+++ b/pool/base.php
@@ -65,9 +65,38 @@ function emailStr($str)
  return preg_replace(array($all,$beg,$fin), '', $str);
 }
 #
+function safepass($pass)
+{
+ if (strlen($pass) < 6)
+	return false;
+
+ # Invalid characters
+ $p2 = preg_replace('/[\011]/', '', $pass);
+ if ($p2 != $pass)
+	return false;
+
+ # At least one lowercase
+ $p2 = preg_replace('/[a-z]/', '', $pass);
+ if ($p2 == $pass)
+	return false;
+
+ # At least one uppercase
+ $p2 = preg_replace('/[A-Z]/', '', $pass);
+ if ($p2 == $pass)
+	return false;
+
+ # At least one digit
+ $p2 = preg_replace('/[0-9]/', '', $pass);
+ if ($p2 == $pass)
+	return false;
+
+ return true;
+}
+#
 function loginStr($str)
 {
- $all = '/[^!-~]/'; // no spaces
+ // Anything but . _ / Tab
+ $all = '/[\._\/\011]/';
  return preg_replace($all, '', $str);
 }
 #
@@ -137,34 +166,34 @@ function safetext($txt, $len = 1024)
 #
 function dbd($data, $user)
 {
- return "
Web site is currently down";
+ return "
Web site is currently down";
 }
 #
 function dbdown()
 {
- gopage(NULL, 'dbd', NULL, '', false, true, false);
+ gopage(NULL, 'dbd', 'dbd', NULL, '', '', true, false, false);
 }
 #
 function f404($data)
 {
- return "
404";
+ return "
404";
 }
 #
 function do404()
 {
- gopage(NULL, 'f404', NULL, '', false, true, false);
+ gopage(NULL, 'f404', 'f404', NULL, '', '', true, false, false);
 }
 #
 function showPage($page, $menu, $name, $user)
 {
 # If you are doing development, use without '@'
 # Then switch to '@' when finished
-# @include_once("page_$page.php");
- include_once("page_$page.php");
+# include_once("page_$page.php");
+ @include_once("page_$page.php");
 
  $fun = 'show_' . $page;
  if (function_exists($fun))
-	$fun($menu, $name, $user);
+	$fun($page, $menu, $name, $user);
  else
 	do404();
 }
@@ -179,8 +208,9 @@ function offline()
  if (file_exists('./maintenance.txt'))
  {
 	$ip = $_SERVER['REMOTE_ADDR'];
-	if ($ip != '192.168.7.74')
-		gopage(NULL, file_get_contents('./maintenance.txt'), NULL, '', false, false, false, false);
+	if ($ip != '192.168.1.666')
+		gopage(NULL, file_get_contents('./maintenance.txt'),
+			'offline', NULL, '', '', false, false, false);
  }
 }
 #
@@ -192,10 +222,11 @@ include_once('db.php');
 #
 function validUserPass($user, $pass)
 {
- $rep = checkpass($user, $pass);
- $ans = repDecode($rep);
+ $rep = checkPass($user, $pass);
+ if ($rep != null)
+	 $ans = repDecode($rep);
  usleep(100000); // Max 10x per second
- if ($ans['STATUS'] == 'ok')
+ if ($rep != null && $ans['STATUS'] == 'ok')
  {
 	$key = 'ckp'.rand(1000000,9999999);
 	$_SESSION['ckpkey'] = $key;
diff --git a/pool/db.php b/pool/db.php
index 09f3897f..14688111 100644
--- a/pool/db.php
+++ b/pool/db.php
@@ -59,7 +59,7 @@ function repDecode($rep)
 	if (isset($major[3]))
 		$ans['ERROR'] = $major[3];
 	else
-		$ans['ERROR'] = 'unknown';
+		$ans['ERROR'] = 'system error';
  }
 
  return $ans;
@@ -116,17 +116,56 @@ function homeInfo($user)
  return $ans;
 }
 #
-function checkpass($user, $pass)
+function checkPass($user, $pass)
 {
  $passhash = myhash($pass);
  $flds = array('username' => $user, 'passwordhash' => $passhash);
  $msg = msgEncode('chkpass', 'log', $flds);
- $rep = sendsockreply('checkpass', $msg);
+ $rep = sendsockreply('checkPass', $msg);
  if (!$rep)
 	dbdown();
  return $rep;
 }
 #
+function setPass($user, $oldpass, $newpass)
+{
+ $oldhash = myhash($oldpass);
+ $newhash = myhash($newpass);
+ $flds = array('username' => $user, 'oldhash' => $oldhash, 'newhash' => $newhash);
+ $msg = msgEncode('newpass', 'log', $flds);
+ $rep = sendsockreply('setPass', $msg);
+ if (!$rep)
+	dbdown();
+ return repDecode($rep);
+}
+#
+function userReg($user, $email, $pass)
+{
+ $passhash = myhash($pass);
+ $flds = array('username' => $user, 'emailaddress' => $email, 'passwordhash' => $passhash);
+ $msg = msgEncode('adduser', 'reg', $flds);
+ $rep = sendsockreply('userReg', $msg);
+ if (!$rep)
+	dbdown();
+ return repDecode($rep);
+}
+#
+function userSettings($user, $email = null, $addr = null, $pass = null)
+{
+ $flds = array('username' => $user);
+ if ($email != null)
+	$flds['email'] = $email;
+ if ($addr != null)
+	$flds['address'] = $addr;
+ if ($pass != null)
+	$flds['passwordhash'] = myhash($pass);
+ $msg = msgEncode('usersettings', 'userset', $flds);
+ $rep = sendsockreply('userSettings', $msg);
+ if (!$rep)
+	dbdown();
+ return repDecode($rep);
+}
+#
 function getAllUsers()
 {
  $flds = array();
@@ -134,7 +173,7 @@ function getAllUsers()
  $rep = sendsockreply('getAllUsers', $msg);
  if (!$rep)
 	dbdown();
- return $rep;
+ return repDecode($rep);
 }
 #
 function getWorkers($user)
@@ -146,7 +185,7 @@ function getWorkers($user)
  $rep = sendsockreply('getWorkers', $msg);
  if (!$rep)
 	dbdown();
- return $rep;
+ return repDecode($rep);
 }
 #
 function getPayments($user)
@@ -158,7 +197,7 @@ function getPayments($user)
  $rep = sendsockreply('getPayments', $msg);
  if (!$rep)
 	dbdown();
- return $rep;
+ return repDecode($rep);
 }
 #
 function getBlocks($user)
@@ -170,7 +209,7 @@ function getBlocks($user)
  $rep = sendsockreply('getBlocks', $msg);
  if (!$rep)
 	dbdown();
- return $rep;
+ return repDecode($rep);
 }
 #
 ?>
diff --git a/pool/page.php b/pool/page.php
index 1939977d..14ee4c88 100644
--- a/pool/page.php
+++ b/pool/page.php
@@ -52,6 +52,14 @@ function makeLink($page, $rest = '')
  return $href;
 }
 #
+function makeForm($page)
+{
+ $form = '