<?php
/***************************************
 *   dbform.inc.php
 *   Engineering Society Registry
 *   (C) 2000 Phil Steinke and Kevin Everets
 *   Licensed under the GNU General Public License
 *
 *   This file contains the array and functions to build
 *   the form for someone's registry info.
 *
 *   The db fields that populate the forms and tables are found in
 *   fielddef.inc.php.
 *
 *   Specifically, it has the following functions:
 *        show_dbinfo($handle)
 *            - displays full details for user specified by $handle
 *        
 *        build_dbform($questset = 'all')
 *             - builds the form allowing a user to input or change their
 *              information.  $questset can be all fields or a required
 *              ('req') subset.  The subset of fields must be in a global
 *              array called $need.
 *
 *        add_prompt()
 *            - used internally by build_dbform() to add the actual html
 *              prompts for each db field
 *
 *        check_info()
 *            - checks through info submitted from a build_dbform().  Checks
 *              if any required fields are missing and builds the $need array.
 *              Also formats data where necessary for insertion into the
 *              database.
 *
 *        handle_prompt()
 *            - displays a handle-entry (no password) prompt
 *
 *        password_prompt()
 *            - displays a password changing prompt
 *        
 *
 *    ChangeLog:
 *    2000-08-01 flynn:     Made more Lynx Happy (changed setup of tables)
 *                        Made closer to XHTML1.0 Strict by removing "align"
 *                         attributes from "table" tags.
 *    2000-08-04 lintec:    Completed XHTML 1.0 Strict checking.
 *                        Created check_info() function.
 *    2000-11-28 lintec:    Added some functionality to the expanding of
 *                web url's such that they have http://
 *                prepended if it is not there.
 *    2006-05-04 mangler:     Make php happy by adding reference to where field def actually lives
 *    
 ***************************************/

include(dirname(__FILE__).'/fielddef.inc.php');

// Show the full set of allowed info for $handle
function show_dbinfo ($handle) {
    global 
$form_field$regdb$webuser;
    
$dbdata $regdb->getRow("select * from people where handle='$handle'"
                             
DB_FETCHMODE_ASSOC);
    
$publish $regdb->getRow("select * from publish where handle='$handle'",
                              
DB_FETCHMODE_ASSOC);
    
// spit out a little header, then the tables with info ?>
<pre>
Information for user <?php echo $dbdata['handle'?>.
Last login:               <?php echo $dbdata['laston'?> 
Information last updated: <?php echo $dbdata['lastupdate'?>
</pre>
<?php // done little header

    
$table_top '<table class="addform" cellspacing="0" border="1">' "\n";

    
// show personal and contact info side by each (using stylesheets)
//    echo "<table width=\"100%\">\n";
//    echo "<tr valign=\"top\"><td>
    
echo "<div class=\"details\">\n";
    echo 
"<div class=\"personalInfo\">\n";
    echo 
"<h3>Personal Information:</h3>\n";
    
// spit out the personal info part
    
echo $table_top;
    
$rowclass "inputD";
    for (
reset($form_field); !preg_match("/^address/"key($form_field)); 
                  
next($form_field)) {
        
// set variables for our current info
        
$info current($form_field);
        
$field key($form_field);
        
// determine if they're allowed to see this field
        
$dispOk = (($webuser->is_admin() == $dbdata['class'])
                  || (
$webuser->is_admin() == 'master')
                  || !(isset(
$publish[$field]) && $publish[$field] == 'f'));
        
// don't show hidden fields or those with no data
        
if ($info[2] != 'hidden' && $dispOk && $dbdata[$field]) {
            
// toggle rowclass between light and dark
            
switch ($rowclass) {
            case 
"inputL":
                
$rowclass "inputD";
                break;
            default:
                
$rowclass "inputL";
            }
            echo 
"<tr class=\"$rowclass\">";
            echo 
"<td>" $info[0] . ": </td>";
            if (isset(
$publish[$field]) && $publish[$field] == "f") {
                echo 
"<td class=\"noPublish\">";
            } else {
                echo 
"<td>";
            }
            
// prepend the 'sci' for their year
            
if (preg_match("/^class/"$field)) {
                echo 
"Sci'";
            }
            echo 
$dbdata[$field] . "</td></tr>\n";
        }
    }
    echo 
"</table>\n";
    echo 
"</div>\n";
    echo 
"<div class=\"contactInfo\">\n";
    echo 
"<h3>Contact Information:</h3>\n";
    
// now for the contact info part
    
echo $table_top;
    
// special case for address: just format it in one big block instead of
    // showing each field
    
if (($webuser->is_admin() == $dbdata['class'])
        || (
$webuser->is_admin() == 'master')
        || (
$publish['address'] == 't')) {
        
$rowclass "inputL";
        echo 
"<tr class=\"$rowclass\">";
        echo 
"<td>Address:</td>";
        if (
$publish['address'] == 't') {
            echo 
"<td>";
        } else {
            echo 
"<td class=\"noPublish\">";
        }
        echo 
$dbdata['address_street1'] . "<br />\n";
        echo 
$dbdata['address_street2'] ? $dbdata['address_street2'] . "<br />\n" "";
        echo 
$dbdata['address_city'];
        echo 
$dbdata['address_prov'] ?  ", " $dbdata['address_prov'] . "<br />\n" "<br />\n";
        echo 
$dbdata['address_postcode'] . "<br />\n";
        echo 
$dbdata['address_country'] . "</td></tr>\n";
    }
    
// flip past the address fields in the array
    
while (key($form_field) != 'address_loc') {
        
next($form_field);
    }
    
// display the rest of the contact fields
    
while (list($field$info) = each($form_field)) {
        
$dispOk = (($webuser->is_admin() == $dbdata['class'])
                  || (
$webuser->is_admin() == 'master')
                  || !(isset(
$publish[$field]) && $publish[$field] == 'f'));
        if (
$info[2] != 'hidden' && $dispOk && $dbdata[$field]) {
            
// toggle rowclass between light and dark
            
switch ($rowclass) {
            case 
"inputL":
                
$rowclass "inputD";
                break;
            default:
                
$rowclass "inputL";
            }
            echo 
"<tr class=\"$rowclass\">";
            echo 
"<td>" $info[0] . ": </td>";
            if (isset(
$publish[$field]) && $publish[$field] == "f") {
                echo 
"<td class=\"noPublish\">";
            } else {
                echo 
"<td>";
            }
            
// if the contact info is online, make it a hyperlink
            
if (preg_match("/^email_(?!preference)/"$field)) {
                echo 
"<a href=\"mailto:$dbdata[$field]\">$dbdata[$field]</a>";
            } elseif (
preg_match("/^web/"$field)) {
                if (!
preg_match("/^\w+:\/\//"$dbdata[$field]))
                    
$dbdata[$field] = "http://$dbdata[$field]";
                echo 
"<a href=\"$dbdata[$field]\">$dbdata[$field]</a>";
            } else {
                echo 
$dbdata[$field] ? $dbdata[$field] : "&nbsp;";
            }
            echo 
"</td></tr>\n";
        }
    }
//    echo "</table></td></tr>\n"; --- close off stylesheet division
    
echo "</table>\n";
    echo 
"</div>\n";
    echo 
"</div>\n";
}


// Builds the form to collect or edit a user's info.  Each field's data is
// stored in a global variable with the same name as the field (e.g.
// the data for the first_name field is in $first_name).
function build_dbform($questset "all") {
    
// questset can be 'all' or 'req'.  
    // 'req' only displays a subset of fields contained in the 
    // global $need[] array.  $need[] must be set up before calling this
    // function
    
global $PHP_SELF$form_field$need$reqimg$addrfields,
           
$addrpub$using_ns4$publish;
    
// Display the top of the form ?>
<form action="<?php echo basename($PHP_SELF?>" method="post" class="addform">
<div class="formhid">
    <input type="hidden" name="addStep" value="createAcct" />
</div>
<table class="addform" cellspacing="0" border="1">
<tr class="inputD">
    <th>Field</th>
    <th>Required</th>
    <th>Data</th>
    <th>Publish</th>
</tr>
<?php     // display the input fields
    
if ($questset == 'req') {
        
// build fix-required form
        
foreach($form_field as $field => $info) {
            if (
$need["$field"]) {
                if (
$info[2]) {
                    
add_prompt($info[0], $field$info[1], $info[2]);
                } elseif (
$info[3]) {
                    
add_prompt($info[0], $field$info[1], $info[2], $info[3]);
                } else {
                    
add_prompt($info[0], $field$info[1]);
                }
            } else {
                global $
$field;
                print 
"<tr class=\"formhid\">\n";
                print 
"\t<td class=\"formhid\">";
                
// Carry over the data for this field.
                
print "<input type=\"hidden\" name=\"$field\" value=\"${$field}\" />";
                
// Catch the address block for publish.
                
if ($field == 'address_street1')
                    
$field 'address';
                
// Carry over the users publish settings.
                
if (in_array($field$publish)) {
                    print 
"<input type=\"hidden\" name=\"publish[]\" value=\"$field\" />";
                }
                print 
"</td>\n";
                echo 
"</tr>\n";
            }
        }
        
// done building fix-it form
    
} elseif ($questset == 'all') {
        
$addrfields 8;
        
// go through array and add_prompt()
        
foreach($form_field as $field => $info) {
            if (
$info[2]) {
                
add_prompt($info[0], $field$info[1], $info[2]);
            } elseif (
$info[3]) {
                
add_prompt($info[0], $field$info[1], $info[2], $info[3]);
            } else {
                
add_prompt($info[0], $field$info[1]);
            }
        }
        
// end of formatting table
    
}
    
// finish off the form ?>
</table>
<p>
    Please ensure that the information above is correct, and that all
    required fields have been filled.
</p>
<p>
    <input type="image" src="images/buttons/submit.png" alt="Submit"
           name="submit" value="submit" 
           <?php if ($using_ns4) print 'border="0" '?>/>
    <!-- <input type="submit" value="Submit Info" />
    &nbsp;
    <input type="reset" value="Clear Changes" /> -->
</p>
</form>
<?php    // done displaying form
}


// actually displays the form prompt for each field, using the information
// in the $form_field array
function add_prompt($prompt$name$req=false$type="text"$link="") {
// a brief explanation of the parameters: (prompt and name are required)
// string $prompt - text to be shown beside entry field (without colon)
// string $name   - name of field in the DB
//   bool $req    - true if field is required
// string $type   - type of data 
//                     (one of text, textbox, select, class, phone, date)
// string $link   - link destination for help on this item
    
global $regdb$reqimg$addrfields$addrpub, $$name$handle,
    
$always_publish$publish;
    if (empty(
$publish)) {
        
$publish $regdb->getRow("select * from publish where handle='$handle'"DB_GETMODE_ASSOC);
    }
    if (empty(
$reqimg)) $reqimg "<tt>-></tt>";

// carry any hidden data and stop the function
    
if ($type == "hidden") { 
        
// add hidden input item ?>
        <tr class="formhid">
            <td class="formhid"><input type="hidden" name="<?php echo $name ?>" value="<?php echo $$name ?>" /></td>
        </tr>
<?php    // done displaying hidden item
        
return;
    }

// toggle rowclass between light and dark
    
global $rowclass;
    switch (
$rowclass) {
    case 
"inputL":
        
$rowclass "inputD";
        break;
    default:
        
$rowclass "inputL";
    }

// display prompt and required image
    
echo "<tr class=\"$rowclass\">\n";
    if (
$link) {
        echo 
"\t<td><a href=\"$link\">$prompt</a>:</td>\n";
    } else {
        echo 
"\t<td>$prompt:</td>\n";
    }
    
$LorD substr($rowclass, -1);
    echo 
"\t<td class=\"reqimg$LorD\">";
    if (
$req) {
        if (
ereg("checkmark.?\.png"$reqimg)) {
            
$reqimg "<img src=\"images/checkmark$LorD.png\" alt=\"->\" />";
        }
        echo 
$reqimg;
    } else {
        echo 
"&nbsp;";
    }
    echo 
"</td>\n";
    echo 
"\t<td>";

// show input field for given type.  If a global variable for the field
// exists, it will be the default value displayed.
    // grab the length of this field from the database (ooh.. fancy)
    // figured out how to do this from phppgadmin
    
$maxwidth 30;
    
$sql_field_len "
        SELECT 
            a.attlen,
            a.atttypmod
        FROM 
            pg_attribute a, 
            pg_class c
        WHERE
            c.relname = 'people'
            and a.attrelid = c.oid
            and a.attname = '$name'"
;
    
$len $regdb->getRow($sql_field_len);
    if (
$len[0] > 0) {
        
$len $len[0];
    } else {
        
$len $len[1] - 4;
    }
    if (
$len $maxwidth) {
        
$displen $maxwidth;
    }
    switch (
$type) {
    case 
"class":
        echo 
"<tt>Sci'</tt>";
    case 
"text":
        echo 
"<input type=\"text\" maxlength=\"$len\" size=\"";
        echo 
$displen ?  $displen $len;
        echo 
"\" name=\"$name\" value=\"${$name}\" />\n";
        break;
    case 
"textbox":
        echo 
"<textarea name=\"$name\" rows=\"5\" ";
        echo 
"cols=\"$maxwidth\">${$name}</textarea>";
        break;
    case 
"select":
        echo 
"<select name=\"$name\">\n";
// getAssoc gave massive problems.  do the work myself.
//        $options = $regdb->getAssoc("select index, $name from options");
//        for ($i = 1; !empty($options[$i]); $i++) {
//            echo "\t\t<option>$options[$i]</option>\n";
//        }
        
$result $regdb->query("select $name from options");
        while (
$row $result->fetchRow()) {
            if (
preg_match("/\S/"$row[0])) {
                echo 
"\t\t<option";
                if ($
$name == $row[0]) echo " selected=\"selected\"";
                echo 
">$row[0]</option>\n";
            }
        }
        
$result->free();
        unset(
$result);
        echo 
"\t</select>";
        break;
    case 
"phone":
        if (
$name == "phone_home") {
            echo 
"<table class=\"phoneEntry\">\n";
            echo 
"<tr>\n\t<td>Please format as if dialing long-distance.</td>\n";
            echo 
"</tr>\n";
            echo 
"<tr>\n\t<td>";
        }
        echo 
"<input type=\"text\" size=\"";
        echo 
$displen ?  $displen $len;
        echo 
"\" maxlength=\"$len\" name=\"$name\" value=\"${$name}\" />";
        if (
$name == "phone_home") {
            echo 
"</td>\n</tr>\n";
            echo 
"<tr>\n\t<td>e.g. <tt>1-613-533-6008</tt></td>\n</tr>\n";
            echo 
"</table>\n";
        }
        break;
    case 
"date":
        
// had major problems trying to do this directly, so use temporary
        // variable 'bla'
        
$bla explode("-", $$name);
        $
$name = array(
            
'year'  => $bla[0],
            
'month' => $bla[1],
            
'day'   => $bla[2]
        );
        unset(
$bla);
        
$birthTime mktime (000, ${$name}['month'], ${$name}['day'], ${$name}['year']);
        
// easiest done in html mode ?>
<table class="dateEntry">
<tr><td>
<input type="text" name="<?php echo $name ?>[day]" maxlength="2" size="2" value="<?php echo ${$name}['day'?>" />
<select name="<?php echo $name ?>[month]">
<?php    // spit out the month options
        
for ($i 1$i <= 12$i++) {
            
$curTime mktime(000$i11990);
            echo 
"\t<option value=\"";
            echo 
date("m"$curTime) . '"';
            if (
date("F"$birthTime) == date("F"$curTime)) {
                echo 
' selected="selected"';
            }
            echo 
'>' date("F"$curTime);
            echo 
"</option>\n";
        } 
        
// back to html mode to finish it off ?>
</select>, 
<input type="text" name="<?php echo $name ?>[year]" maxlength="4" size="4" value="<?php echo ${$name}['year'?>" />
</td></tr>
<tr>
    <td>e.g. <tt>18 November, 1977</tt></td>
</tr>
</table>
<?php // end of date entry
    
// end of switch
    
echo "</td>\n";

// display publish column
    
if (preg_match("/^addr/"$name)) {
        if (!
$addrpub) {
            
// rowspan was $addrfields before we put hidden fields in table
            // rows
            
echo "\t<td class=\"addrPublish\" rowspan=\"8\">"
            echo 
"<input type=\"checkbox\" name=\"publish[]\" value=\"address\"";
            if (isset(
$publish['address']) && $publish['address'] == "f") {
                echo 
" />";
            } else {
                echo 
" checked=\"checked\" />";
            }
            echo 
"</td>\n";
            
$addrpub true;
        }
    } elseif (
in_array($name$always_publish)) {
        echo 
"\t<td class=\"toggle\">";
        echo 
"&nbsp;";
        echo 
"</td>\n";
    } else {
        echo 
"\t<td class=\"toggle\">";
        echo 
"<input type=\"checkbox\" name=\"publish[]\" value=\"$name\"";
        if (isset(
$publish[$name]) && $publish[$name] == "f") {
            echo 
" />";
        } else {
            echo 
" checked=\"checked\" />";
        }
        echo 
"</td>\n";
    }

    echo 
"</tr>\n";
    
// end of add_prompt()



function check_info() {
    global 
$lastupdate$laston$form_field$need$fieldList$values;
    
$lastupdate 'now';
    
$laston 'now';
    foreach(
$form_field as $field => $info) {
        global $
$field;
        if (
$info[2] == "date" && is_array($$field)) {
            
// note how the array ambiguity with the variable variable
            // must be resolved.  The PHP manual covers this.
            
if (strlen(${$field}['day']) == 1) {
                ${
$field}['day'] = "0" . ${$field}['day'];
            }
            $
$field = ${$field}['year'] . "-" . ${$field}['month'] . "-" . ${$field}['day'];
        }
        
// Ensure there's no leading or trailing whitespace on the
        // data.
        
$$field trim($$field);
        if (
$info[1]) {
            if (empty($
$field) || preg_match("/^-/", $$field)) {
                
$need["$field"] = true;
            }
        }
        
$fieldList .= "$field, ";
        
$values .= "'${$field}', ";
    }
// end of check_info()



// simple prompt for a user's handle
function handle_prompt() { 
    global 
$PHP_SELF$using_ns4;
    
// display handle prompt ?>
    <form action="<?php echo basename($PHP_SELF?>" method="post">
    <div class="formhid">
        <input type="hidden" name="addStep" value="checkHandle" />
    </div>
    <table>
    <tr><td>Handle: </td>
        <td><input type="text" size="22" maxlength="20" name="handle" /></td>
    </tr>
    <tr><td colspan="2">
    <input type="image" src="images/buttons/continue.png" 
           value="continue" alt="continue" name="continue"
           <?php if ($using_ns4) print 'border="0" '?>/></td>
    </tr>
    </table>
    </form> 
<?php // end of handle prompt
}


// simple pair of prompts for a password change
function password_prompt() { 
    global 
$PHP_SELF$handle$using_ns4;
    
// display password prompt, and carry the handle ?>
    <form action="<?php echo basename($PHP_SELF?>" method="post">
    <div class="formhid">
        <input type="hidden" name="addStep" value="checkPassword" />
        <input type="hidden" name="handle"  value="<?php echo $handle ?>" />
    </div>
    <table>
    <tr><td>Password: </td>
        <td><input type="password" size="22" maxlength="20" name="password[1]" /></td>
    </tr>
    <tr><td>Verify: </td>
        <td><input type="password" size="22" maxlength="20" name="password[2]" /></td>
    </tr>
    <tr><td colspan="2">
    <input type="image" src="images/buttons/continue.png" 
           value="continue" alt="continue" name="continue" 
           <?php if ($using_ns4) print 'border="0" '?>/></td>
    </tr>
    </table>
    </form> 
<?php // end of password prompt
}

function 
password_check ($password) {
    
// Does some simple checks to ensure a good password.    
    
$pwfail false;
    
similar_text($handle$password$sim);
    if (
strlen($password) < 6) {
        
$pwfail true;
        
$reason "too short.  It must be at least 6 characters.";
    } elseif ((
$sim 60) || ($password == strrev($handle))) {
        
$pwfail true;
        
$reason "too similar to your handle";
    } elseif (!
preg_match("/[^a-zA-Z]/"$password)) {
        
$pwfail true;
        
$reason "all letters.  It must contain at least one";
        
$reason .= " non-letter character.";
    }
    return array(
$pwfail$reason);
}

//eof ?>