$msg END; } // Return a string which is a correct link back to ourselves, with the // operation set to $func. function gen_link($func, $content) { $me = $_SERVER['SCRIPT_NAME']; return "$content"; } // Open a form which we will process. Creates the form tag with the // correct action, and generates a hidden field for the function. function gen_form($func) { $me = $_SERVER['SCRIPT_NAME']; return "
\n" . "\n"; } // Generate a form asking the amount and selecting an account. These are used // for adds, transfers, and purchases. First arg is the oper value for the // action URL, the rest fill in text: The label for the amount, text for each // radio button, text for the submit button. function amt_acct_form($act, $amtlab, $rad1, $rad2, $sub) { echo gen_form($act), <<
$rad1
$rad2
ENDTAB; } // Update accounts. Used by the functions which change balances to check // and update. Args are the amount of transaction from the web page (must // be checked). $delta_a and $delta_b are factors. Each account is // incremented by the delta. function update_account($acct, $amt, $delta_a, $delta_b) { // Check the number. if(!numeric($amt)) return "Please Enter a Valid Number"; // Convert deltas to absolute. $delta_a = $delta_a * $amt; $delta_b = $delta_b * $amt; // Attempt to read the account entry. $dbm = opendb(); if(!$dbm) return "Database Update Failed"; $dat = pg_exec($dbm,"SELECT jelly, dust " . "FROM accounts WHERE acctname = '$acct'"); list($a, $b) = pg_fetch_row($dat, 0); // Check for sufficient funds. if($a + $delta_a < 0) { pg_close($dbm); return "Insufficient funds in ".act_A; } if($b + $delta_b < 0) { pg_close($dbm); return "Insufficient funds in ".act_B; } // Update $a += $delta_a; $b += $delta_b; pg_exec($dbm, "UPDATE accounts SET jelly = $a, dust = $b " . "WHERE acctname = '$acct'"); pg_close($dbm); return ''; } // Generate the start menu (the menu for logged out sessions). The title // can be sent, or defaults. function gen_start_menu($msg = 'Welcome to Frogbreath', $error = FALSE) { frogstart($msg, $error); echo gen_link('login', 'Log in'), " to Frogbreath
"; echo gen_link('create', 'Create'), " a Frogbreath account
"; global $oper; $oper = 'menu'; } // Generate the action menu (the menu for logged in sessions). Title will // default. function gen_do_menu($acct, $name, $msg = FALSE, $error = FALSE) { // Default message. Can't be the default 'cause it needs a variable. if(!$msg) $msg = "$name at Frogbreath"; frogstart($msg, $error); // Generate the links. echo gen_link('buy', 'Buy stuff'), " you can't see from Frogbreath
"; echo gen_link('add', 'Give'), " fake money to Frogbreath
"; echo gen_link('xfer', 'Transfer'), " fake money between accounts.
"; echo gen_link('query', 'Query'), " fake balances.
"; echo gen_link('logout', 'Log out'), " from Frogbreath
"; global $oper; $oper = 'menu'; } // Log out the user. Changes the session state. function do_logout($name) { // Change state and generate the login menu. $_SESSION['state'] = 'out'; gen_start_menu("$name has left Frogbreath"); } // Function for serious errors that we can't figure out. function gen_err($msg) { // Just in case. $_SESSION['state'] = 'out'; whap("Internal Error: $msg", "An internal error has occurred: $msg." . "This may indicate a problem with our server or your " . "network connection. You may want to try again later. " . "We regret any inconvenience this may cause.

" . "Thank you for visiting Frogbreath."); } // Output a table of the subaccount balances for the currently logged-on // account. Displays the header which defaults. If there is problem, // returns an error message. Otherwise, returns ''. function display_bal($acct, $msg = '', $error = FALSE) { $Act_A = Act_A; $Act_B = Act_B; // Attempt to read the balances. $dbm = opendb(); if(!$dbm) return 'Database open failed.'; $dat = pg_exec($dbm,"SELECT jelly, dust, humanname " . "FROM accounts WHERE acctname = '$acct'"); list($n, $m, $name) = pg_fetch_row($dat, 0); pg_close($dbm); // Display. if(!$msg) $msg = "Balances for $name"; frogstart($msg, $error); echo <<
$Act_A:$n
$Act_B:$m

DONE; return ''; } // Generate the balance query page. function gen_query($acct, $name) { $str = display_bal($acct); if($str != '') gen_do_menu($acct, $name, $str, TRUE); } // Produce the add additional funds menu. function gen_add($acct, $name, $head, $error = FALSE) { // Generate the current balance table if(($m = display_bal($acct,$head)) != '') { gen_do_menu($acct, $name, $m, TRUE); return; } echo "

"; // Generate the transfer information form. amt_acct_form('doadd', 'Funds to Add', "Add to ".act_A, "Add to ".act_B, 'ADD'); } // Process additional funds response. function do_add($acct, $name) { $amt = $_REQUEST['amt']; $which = $_REQUEST['which']; // Compute the delta factors for update_account based on the // account selection from the form. $da = $db = 0; if($which == 'a') $da = 1; else $db = 1; // Attempt to update the account, then go to the index, or back to // account add form in case of error. if(($msg = update_account($acct, $amt, $da, $db)) != '') gen_add($acct, $name, $msg); else gen_do_menu($acct, $name, "Added $amt to " . ${"act_$which"} . " for $name"); } // Generate transfer menu. function gen_xfer($acct, $name, $head, $error = FALSE) { // Display current balances. if(($m = display_bal($acct, $head, $error)) != '') { gen_do_menu($acct, $name, $m); return; } echo "

"; // Generate transfer form. amt_acct_form('doxfer', 'Funds to Transfer', "Transfer from " . act_A . " to " . act_B, "Transfer from " . act_B . " to " . act_A, 'TRANSFER'); } // Process funds transfer. function do_xfer($acct, $name) { $amt = $_REQUEST['amt']; // Based on radio button results, choose deltas for update_account, // and a success message, in case we have some. if($_REQUEST['which'] == 'a') { $da = -1; $db = 1; $succ = "Transferred $amt from " . act_A . " to " . act_B . " for $name"; } else { $da = 1; $db = -1; $succ = "Transferred $amt from " . act_B . " to " . act_A . " for $name"; } // Update the account, menu or back to form in case of error. if(($msg = update_account($acct, $amt, $da, $db)) != '') gen_xfer($acct, $name, $msg, TRUE); else gen_do_menu($acct, $name, $succ); } // Generate the purchase menu. function gen_buy($acct, $name, $head, $error = FALSE) { // Display current balances. if(($m = display_bal($acct, $head, $error)) != '') { gen_do_menu($acct, $name, $m); return; } echo "

"; // The "market" prices set at random. (The market is rather volatile) if($error) { $pri_pop = $_SESSION['pri_pop']; $pri_fame = $_SESSION['pri_fame']; $pri_sawdust = $_SESSION['pri_sawdust']; } else { list($u, $s) = explode(' ', microtime()); srand((100000*$u) ^ $s); $_SESSION['pri_pop'] = $pri_pop = rand(1, 20); $_SESSION['pri_fame'] = $pri_fame = rand(15, 30); $_SESSION['pri_sawdust'] = $pri_sawdust = rand(6, 15); } // Generate purchase form. $Act_A = Act_A; $Act_B = Act_B; echo gen_form('dobuy'), << Popularity @ $pri_pop
Fame @ $pri_fame
Sawdust @ $pri_sawdust

From which account will you pay?
$Act_A
$Act_B
ENDTAB; } // Process purchase. function do_buy($acct, $name) { // Prices from session. $pri_pop = $_SESSION['pri_pop']; $pri_fame = $_SESSION['pri_fame']; $pri_sawdust = $_SESSION['pri_sawdust']; // Purchase selections from form. $sel_pop = $_REQUEST['sel_pop']; $sel_fame = $_REQUEST['sel_fame']; $sel_sawdust = $_REQUEST['sel_sawdust']; // Check that input counts are numeric. if(!numeric($sel_pop) || !numeric($sel_fame) || !numeric($sel_sawdust)) { gen_buy($acct, $name, "Please give positive numeric quantities.", TRUE); return; } // Compute price. $price = $sel_pop*$pri_pop; $price += $sel_fame*$pri_fame; $price += $sel_sawdust*$pri_sawdust; // Set account to debit. $da = $db = 0; if($_REQUEST['which'] == 'a') $da = -1; else $db = -1; // Update account, show menu or return to form on an error. if(($msg = update_account($acct, $price, $da, $db)) != '') gen_buy($acct, $name, $msg, TRUE); else gen_do_menu($acct, $name, "$name spent $price from " . ${"act_$which"}); } // Generate the create account page. function gen_create() { frogstart('Create A Frogbreath Account'); // Generate the form. echo gen_form('docreate'); ?>
Your Name:
Account Name:
Password:
Account Name:
Password:
  ", gen_link('menu', 'Menu

'); ?>