Index: trunk/lib/App.inc.php
===================================================================
--- trunk/lib/App.inc.php	(revision 29)
+++ trunk/lib/App.inc.php	(revision 32)
@@ -81,5 +81,5 @@
         
         // For classes that require db tables, do we check that a table exists and create if missing?
-        'db_create_tables' => null,
+        'db_create_tables' => true,
 
         // The level of error reporting. Don't set this to 0 to suppress messages, instead use display_errors to control display.
@@ -366,6 +366,8 @@
             $this =& App::getInstance();
         }
-
-        if (!$this->running) {
+        
+        $message = trim($message);
+
+        if (!$this->running || '' == $message) {
             return false;
         }
@@ -543,5 +545,5 @@
     /**
      * Sets which query arguments will be carried persistently between requests.
-     * Values in the _carry_queries array will be copied to URLs (via oHREF()) and 
+     * Values in the _carry_queries array will be copied to URLs (via App::url()) and 
      * to hidden input values (via printHiddenSession()).
      *
@@ -566,14 +568,14 @@
     /**
      * Outputs a fully qualified URL with a query of all the used (ie: not empty)
-     * keys and values, including optional queries. This allows simple printing of
-     * links without needing to know which queries to add to it. If cookies are not
+     * keys and values, including optional queries. This allows mindless retention 
+     * of query arguments across page requests. If cookies are not
      * used, the session id will be propogated in the URL.
      *
-     * @param  string $url                 The initial url
-     * @param  mixed  $carry_args          Additional url arguments to carry in the query,
-     *                                     or FALSE to prevent carrying queries. Can be any of the following formats:
-     *                                     -array('key1', key2', key3')  <-- to save these keys if in the form data.
-     *                                     -array('key1'=>'value', key2'='value')  <-- to set keys to default values if not present in form data.
-     *                                     -false  <-- To not carry any queries. If URL already has queries those will be retained.
+     * @param  string $url              The initial url
+     * @param  mixed  $carry_args       Additional url arguments to carry in the query,
+     *                                  or FALSE to prevent carrying queries. Can be any of the following formats:
+     *                                      array('key1', key2', key3')  <-- to save these keys if in the form data.
+     *                                      array('key1'=>'value', key2'='value')  <-- to set keys to default values if not present in form data.
+     *                                      false  <-- To not carry any queries. If URL already has queries those will be retained.
      *
      * @param  mixed  $always_include_sid  Always add the session id, even if using_trans_sid = true. This is required when
@@ -583,5 +585,5 @@
      * @return string url with attached queries and, if not using cookies, the session id
      */
-    function oHREF($url='', $carry_args=null, $always_include_sid=false)
+    function url($url, $carry_args=null, $always_include_sid=false)
     {
         if (!isset($this) || !is_a($this, 'App')) {
@@ -617,5 +619,6 @@
         
         // Get the first delimiter that is needed in the url.
-        $delim = preg_match('/\?/', $url) ? ini_get('arg_separator.output') : '?';
+        $delim = strpos($url, '?') !== false ? ini_get('arg_separator.output') : '?';
+
         
         $q = '';
@@ -667,4 +670,27 @@
         }
     }
+
+    /**
+     * Returns a HTML-friendly URL processed with App::url and & replaced with &amp;
+     *
+     * @access  public
+     * @param   string  $url    Input URL to parse.
+     * @return  string          URL with App::url() and htmlentities() applied.
+     * @author  Quinn Comendant <quinn@strangecode.com>
+     * @since   09 Dec 2005 17:58:45
+     */
+    function oHREF($url, $carry_args=null, $always_include_sid=false)
+    {
+        if (!isset($this) || !is_a($this, 'App')) {
+            $this =& App::getInstance();
+        }
+        
+        $url = $this->url($url, $carry_args, $always_include_sid);
+        
+        // Replace any & not followed by an html or unicode entity with it's &amp; equivalent.
+        $url = preg_replace('/&(?![\w\d#]{1,10};)/', '&amp;', $url);
+        
+        return $url;
+    }
     
     /**
@@ -674,10 +700,10 @@
      * @param  mixed  $carry_args        Additional url arguments to carry in the query,
      *                                   or FALSE to prevent carrying queries. Can be any of the following formats:
-     *                                   -array('key1', key2', key3')  <-- to save these keys if in the form data.
-     *                                   -array('key1'=>'value', key2'='value')  <-- to set keys to default values if not present in form data.
-     *                                   -false  <-- To not carry any queries. If URL already has queries those will be retained.
+     *                                      array('key1', key2', key3')  <-- to save these keys if in the form data.
+     *                                      array('key1'=>'value', key2'='value')  <-- to set keys to default values if not present in form data.
+     *                                      false  <-- To not carry any queries. If URL already has queries those will be retained.
      */
     function printHiddenSession($carry_args=null)
-    {    
+    {
         if (!isset($this) || !is_a($this, 'App')) {
             $this =& App::getInstance();
@@ -762,5 +788,5 @@
         }
 
-        $url = $this->oHREF($url, $carry_args, $always_include_sid);
+        $url = $this->url($url, $carry_args, $always_include_sid);
         
         header(sprintf('Location: %s', $url));
Index: trunk/lib/Auth_SQL.inc.php
===================================================================
--- trunk/lib/Auth_SQL.inc.php	(revision 29)
+++ trunk/lib/Auth_SQL.inc.php	(revision 32)
@@ -22,4 +22,7 @@
     // Default param values.
     var $_default_params = array(
+    
+        // Message displayed by requireLogin().
+        'login_required_message' => 'Please login',
         
         // Automatically create table and verify columns. Better set to false after site launch.
@@ -537,5 +540,5 @@
      * Redirect user to login page if they are not logged in.
      *
-     * @param string $msg     The text description of a message to raise.
+     * @param string $message The text description of a message to raise.
      * @param int    $type    The type of message: MSG_NOTICE,
      *                        MSG_SUCCESS, MSG_WARNING, or MSG_ERR.
@@ -544,10 +547,10 @@
      * @access public
      */
-    function requireLogin($msg='', $type=MSG_NOTICE, $file=null, $line=null)
+    function requireLogin($message='', $type=MSG_NOTICE, $file=null, $line=null)
     {
         if (!$this->isLoggedIn()) {
-            if ('' != $msg) {
-                App::raiseMsg($msg, $type, $file, $line);
-            }
+            // Display message for requiring login.
+            App::raiseMsg($message, $type, $file, $line);
+
             // Login scripts must have the same 'login' tag for boomerangURL verification/manipulation.
             App::setBoomerangURL(absoluteMe(), 'login');
@@ -820,5 +823,5 @@
      * @param  constant $security_zone   string of comma delimited priviliges for the zone
      */
-    function requireAccessClearance($security_zone, $msg='')
+    function requireAccessClearance($security_zone, $message='')
     {
         return true;
@@ -828,6 +831,6 @@
          * user has no privilege, DIE with a message. */
         if (!in_array($this->getVal('priv'), $zone_members) || !$this->getVal('priv')) {
-            $msg = empty($msg) ? _("You have insufficient privileges to view that page.") : $msg;
-            App::raiseMsg($msg, MSG_NOTICE, __FILE__, __LINE__);
+            $message = empty($message) ? _("You have insufficient privileges to view that page.") : $message;
+            App::raiseMsg($message, MSG_NOTICE, __FILE__, __LINE__);
             App::dieBoomerangURL();
         }
Index: trunk/lib/Captcha.inc.php
===================================================================
--- trunk/lib/Captcha.inc.php	(revision 29)
+++ trunk/lib/Captcha.inc.php	(revision 32)
@@ -142,6 +142,6 @@
         ?>
         <label for="sc-captcha"><?php echo _("Reverse Turing Test") ?></label>
-        <p class="help">Please enter the number here to prove you are a human. This is a measure to prevent spam robots from submitting this form.</p>
-        <pre style="font-size: 1px;"><?php echo $ascii ?></pre>
+        <p class="help"><?php echo _("Please type the following number to prove you are a human. This is a measure to prevent spam robots from submitting this form.") ?></p>
+        <pre style="font-size: 0.5em;"><?php echo $ascii ?></pre>
         <input name="sc-captcha" id="sc-captcha" type="text" />
         <input name="sc-captcha-hash" type="hidden" value="<?php echo $hash ?>" />
Index: trunk/lib/TemplateGlue.inc.php
===================================================================
--- trunk/lib/TemplateGlue.inc.php	(revision 29)
+++ trunk/lib/TemplateGlue.inc.php	(revision 32)
@@ -105,7 +105,27 @@
         }
     }
-    foreach ($values as $item) {
-        $selected = ($item == $preselected) ? ' selected' : '';
-        ?><option value="<?php echo $item; ?>"<?php echo $selected; ?>><?php echo oTxt($item); ?></option>
+    foreach ($values as $v) {
+        $selected = ($v == $preselected) ? ' selected' : '';
+        ?><option value="<?php echo $v; ?>"<?php echo $selected; ?>><?php echo oTxt($v); ?></option>
+        <?php
+    }
+}
+
+/**
+ * Prints radio buttons from a set/enum column.
+ *
+ * @param  string $db_table   database table to lookup
+ * @param  string $db_col     database column to lookup
+ */
+function printEnumRadios($name, $db_table, $db_col, $preselected, $blank=false)
+{
+    $values = getSetEnumFieldValues($db_table, $db_col);
+    if ($values === false) {
+        return false;
+    }
+
+    foreach ($values as $v) {
+        $selected = ($v == $preselected) ? ' selected' : '';
+        ?><input type="radio" name="<?php echo $name ?>" id="<?php echo $v; ?>" value="<?php echo $v; ?>"<?php echo $selected; ?> /><label for="<?php echo $v; ?>"><?php echo oTxt($v); ?></label>
         <?php
     }
@@ -150,5 +170,5 @@
     $row_cnt = 0;
     $col_cnt = 0;
-    foreach ($values as $item) {
+    foreach ($values as $v) {
         if ($col_cnt == $columns) {
             // Begin a new row.
@@ -166,5 +186,5 @@
         
         // Look for preselected value.
-        if (in_array($item, $preselected)) {
+        if (in_array($v, $preselected)) {
             $checked = ' checked="checked"';
         } else {
@@ -173,10 +193,10 @@
         if ('allone' == $flag) {
             // Print a cell with multidimentioal array checkboxes.
-            $html_name = 'dbcol[' . $db_col . '][' . $item . ']';
+            $html_name = 'dbcol[' . $db_col . '][' . $v . ']';
         } else {
             // Print a cell with basic named checkboxes.
-            $html_name = $db_col . '[' . $item . ']';
-        }
-        ?><td><input type="checkbox" name="<?php echo $html_name ?>" id="<?php echo $html_name ?>"<?php echo $checked; ?> /><label for="<?php echo $html_name ?>"><?php echo oTxt($item); ?></label></td>
+            $html_name = $db_col . '[' . $v . ']';
+        }
+        ?><td><input type="checkbox" name="<?php echo $html_name ?>" id="<?php echo $html_name ?>"<?php echo $checked; ?> /><label for="<?php echo $html_name ?>"><?php echo oTxt($v); ?></label></td>
         <?php
     }
@@ -228,5 +248,5 @@
     $row_cnt = 0;
     $col_cnt = 0;
-    foreach ($values as $item) {
+    foreach ($values as $v) {
         if ($col_cnt == $columns) {
             // Begin a new row.
@@ -244,5 +264,5 @@
         
         // Look for preselected value.
-        if (in_array($item, $preselected)) {
+        if (in_array($v, $preselected)) {
             $checked = ' checked="checked"';
         } else {
@@ -250,5 +270,5 @@
         }
         // Print a cell with basic named checkboxes.
-        ?><td><input type="radio" name="<?php echo $db_col; ?>" id="<?php echo $db_col; ?>" value="<?php echo $item ?>"<?php echo $checked; ?> /><label for="<?php echo $db_col ?>"><?php echo oTxt($item); ?></label></td>
+        ?><td><input type="radio" name="<?php echo $db_col; ?>" id="<?php echo $db_col; ?>" value="<?php echo $v ?>"<?php echo $checked; ?> /><label for="<?php echo $db_col ?>"><?php echo oTxt($v); ?></label></td>
         <?php
     }
Index: trunk/lib/Utilities.inc.php
===================================================================
--- trunk/lib/Utilities.inc.php	(revision 29)
+++ trunk/lib/Utilities.inc.php	(revision 32)
@@ -97,6 +97,6 @@
 
     // & becomes &amp;. Exclude any occurance where the & is followed by a alphanum or unicode caracter.
-    $search['ampersand']        = '/&((?![\w\d#]{1,10};))/';
-    $replace['ampersand']       = '&amp;\\1';
+    $search['ampersand']        = '/&(?![\w\d#]{1,10};)/';
+    $replace['ampersand']       = '&amp;';
 
     return preg_replace($search, $replace, htmlentities($txt, ENT_QUOTES, App::getParam('character_set')));
