<?PHP
/*
* phpMyPurchasing
* Jason Gerfen [hide@address.com]
*
* class.groups.php - Handle group managment and import
*/
class groups
{
function process($token,$get,$post,$server)
{
global $errors, $handles, $defined;
$user_details = $handles['encrypt']->DecodeAuthTokenHeavy( $token );
$user = $user_details[0]; $formData['addAppAdmin'] = $username;
$group = $user_details[3];
$post = array_merge($post,$this->GenAllErrors($post));
$post['importGroups'] = $this->createImportForm($post);
if(count($post['ldap_groups'])>0) {
$post['lerror'] = '<div class="error">' . $this->import($post,$user) . '</div>';
}
if(!empty($post['cmd'])) {
if((!empty($post['txtGroupName']))&&(!empty($post['txtGroupManager']))&&(!empty($post['txtGroupPhone']))) {
if(($handles['val']->ValidateParagraph($post['txtGroupManager'])!==-1)||($handles['val']->ValidatePhone($post['txtGroupPhone'])!==-1)||($handles['val']->ValidateParagraph($post['txtGroupDescription'])!==-1)) {
if($post['cmd']==="addGroup") {
$flag = 'add';
$sql['main'] = $this->add($token,$order,$post,$user);
}
if($post['cmd']==="editGroup") {
$flag = 'edit';
$sql['main'] = $this->edit($post,$user);
}
if($post['cmd']==="delGroup") {
$flag = 'del';
$sql['main'] = $this->delete($post);
$sql['resource'] = $this->dresource($post);
$sql['gresource'] = $this->dgresource($post);
$sql['uresource'] = $this->duresource($post);
$sql['udelete'] = $this->udelete($post);
$sql['uresourced'] = $this->udelete($post);
$users = $this->getGroupUsers($post['txtGroupName']);
if(count($users)>0) {
foreach($users as $key => $value) {
$sql[$key] = $this->duresource($value['username']);
$sql[$value['username']] = $this->dresourcebyname($value['username']);
}
}
}
if($post['cmd']!=="delGroup") {
$sql['resource'] = $this->resource($user,$post);
$sql['gresource'] = $this->gresource($group,$post);
$sql['uresource'] = $this->uresource($user,$post);
}
$result = $this->execute($sql);
if($result==='-1'){
$x = $defined['error']; $class = "error";
$message = "A database error occured when saving changes to '$post[txtGroupName]'";
} else {
$x = $defined['good']; $class = "good";
$message = "Changes to '$post[txtGroupName]' were successful. $result changes were made.";
}
$post['error'] = '<div class="'.$class.'">' . $handles['err']->GenerateErrorImg( $x, "help/help.html", NULL, '800', '800' ) . ' ' . $message . '</div>';
} else {
$erlink = $handles['err']->GenerateErrorImg( $defined['error'], "help/help.html", "", '800', '800' );
$list = "<ul>";
if($handles['val']->ValidateParagraph($post['txtGroupName'])===-1){ $list .= "<li>Group name is invalid. Allowed: [ -?!#$&+0-9=?A-Z^_.,]</li>"; $post['txtGroupNameErr'] = $erlink; }
if($handles['val']->ValidateParagraph($post['txtGroupManager'])===-1){ $list .= "<li>Group manager is invalid. Allowed: [ -?!#$&+0-9=?A-Z^_.,]</li>"; $post['txtGroupManagerErr'] = $erlink; }
if($handles['val']->ValidatePhone($post['txtGroupPhone'])===-1){ $list .= "<li>Group phone is invalid. Allowed: [xxx-xxx-xxxx]</li>"; $post['txtGroupPhoneErr'] = $erlink; }
if($handles['val']->ValidateParagraph($post['txtGroupDescription'])===-1){ $list .= "<li>Group description is invalid. Allowed: [ -?!#$&+0-9=?A-Z^_.,]</li>"; $post['txtGroupDescriptionErr'] = $erlink; }
$list .= "</ul>";
$post['error'] = '<div class="error">' . $list . '</div>';
}
} else {
$erlink = $handles['err']->GenerateErrorImg( $defined['error'], "help/help.html", "", '800', '800' );
$list = "<ul>";
if(empty($post['txtGroupName'])){ $list .= "<li>Group name is missing</li>"; $post['txtGroupNameErr'] = $erlink; }
if(empty($post['txtGroupManger'])){ $list .= "<li>Group manager is missing</li>"; $post['txtGroupManagerErr'] = $erlink; }
if(empty($post['txtGroupPhone'])){ $list .= "<li>Group phone is missing</li>"; $post['txtGroupPhoneErr'] = $erlink; }
$list .= "</ul>";
$post['error'] = '<div class="error">' . $list . '</div>';
}
} else {
$post = array_merge($post, $this->GenAllValues());
}
if(function_exists("json_encode")) {
$jsonGroups = json_encode( array_map( $handles['val']->ValidateXSS, $this->getGroupInfo($token) ) );
} else {
$jsonGroups = $handles['misc']->arr2json( array_map( $handles['val']->ValidateXSS, $this->getGroupInfo($token) ) );
}
$post['jsonGroups'] = 'var groups = ' . $jsonGroups . ';';
return $post;
}
function genAllValues()
{
$post['txtGroupName'] = '';
$post['txtGroupManager'] = '';
$post['txtGroupPhone'] = '';
$post['txtGroupDescription'] = '';
return $post;
}
function genAllErrors($post)
{
$post['error'] = '';
$post['lerror'] = '';
$post['txtGroupNameErr'] = '*';
$post['txtGroupManagerErr'] = '*';
$post['txtGroupPhoneErr'] = '*';
$post['txtGroupDescriptionErr'] = '';
return $post;
}
function getGroupInfo($token)
{
global $defined;
global $handles;
$details = $handles['encrypt']->DecodeAuthTokenHeavy($token);
$dbconn = $handles['db']->dbConnect( $defined['dbhost'], $defined['username'], $defined['password'], $defined['dbname'] );
$sql = "SELECT * FROM `groups`";
if(($value = $handles['db']->dbQuery($handles['val']->ValidateSQL($sql, $dbconn), $dbconn))!==-1) {
if($handles['db']->dbNumRows($value)>0) {
$data = $handles['db']->dbArrayResultsAssoc($value);
}
}
$handles['misc']->CleanUpVars($details, NULL);
$handles['db']->dbFixTable("groups", $dbconn);
$handles['db']->dbFreeData($dbconn);
$handles['db']->dbCloseConn($dbconn);
return $data;
}
function getGroupUsers($group)
{
global $defined;
global $handles;
$dbconn = $handles['db']->dbConnect( $defined['dbhost'], $defined['username'], $defined['password'], $defined['dbname'] );
$sql = "SELECT * FROM `users` WHERE `group` = \"" . $group . "\"";
if(($value = $handles['db']->dbQuery($handles['val']->ValidateSQL($sql, $dbconn), $dbconn))!==-1) {
if($handles['db']->dbNumRows($value)>0) {
$data = $handles['db']->dbArrayResultsAssoc($value);
}
}
$handles['misc']->CleanUpVars($details, NULL);
$handles['db']->dbFixTable("groups", $dbconn);
$handles['db']->dbFreeData($dbconn);
$handles['db']->dbCloseConn($dbconn);
return $data;
}
function add($token,$order,$post,$user)
{
return "INSERT INTO `groups` (`txtGroupName`,`txtGroupManager`,`txtGroupPhone`,`txtGroupDescription`,`owner`) VALUES (\"" . $post['txtGroupName'] . "\",\"" . $post['txtGroupManger'] . "\",\"" . $post['txtGroupPhone'] . "\",\"" . $post['txtGroupDescription'] . "\",\"" . $user . "\") ON DUPLICATE KEY UPDATE `txtGroupName` = \"" . $post['txtGroupName'] . "\",`txtGroupManager` = \"" . $post['txtGroupManager'] . "\",`txtGroupPhone` = \"" . $post['txtGroupPhone'] . "\",`txtGroupDescription` = \"" . $post['txtGroupDescription'] . "\"";
}
function edit($post,$user)
{
return "UPDATE `groups` SET `txtGroupName` = \"" . $post['txtGroupName'] . "\",`txtGroupManager` = \"" . $post['txtGroupManager'] . "\",`txtGroupPhone` = \"" . $post['txtGroupPhone'] . "\",`txtGroupDescription` = \"" . $post['txtGroupDescription'] . "\" WHERE `txtGroupName` = \"" . $post['txtGroupName'] . "\" LIMIT 1";
}
function delete($post)
{
return "DELETE FROM `groups` WHERE `txtGroupName` = \"" . $post['txtGroupName'] . "\" LIMIT 1";
}
function udelete($post)
{
return "DELETE FROM `users` WHERE `txtObjectGroup` = \"" . $post['txtGroupName'] . "\"";
}
function uresourced($post)
{
return "DELETE FROM `uresources` WHERE `txtObjectUser` = \"" . $post['txtUserName'] . "\" LIMIT 1";
}
function resource($user,$post)
{
return "INSERT INTO `resources` (`txtObjectID`,`txtObjectUser`,`txtObjectRead`,`txtObjectWrite`) VALUES (\"" . md5($post['txtGroupName']) . "\", \"" . $post['txtGroupName'] . "\", \"" . $user . "\") ON DUPLICATE KEY UPDATE `txtObjectID` = \"" . md5($post['txtGroupName']) . "\",`txtObjectName` = \"" . $post['txtGroupName'] . "\"";
}
function gresource($group,$post)
{
return "INSERT INTO `gresources` (`txtObjectID`,`txtObjectUser`,`txtObjectRead`,`txtObjectWrite`) VALUES (\"" . md5($post['txtGroupName']) . "\", \"" . $group . "\", \"1\", \"1\") ON DUPLICATE KEY UPDATE `txtObjectID` = \"" . md5($post['txtGroupName']) . "\",`txtObjectGroup` = \"" . $group . "\",`txtObjectRead` = \"1\", `txtObjectWrite` = \"1\"";
}
function uresource($user,$post)
{
return "INSERT INTO `uresources` (`txtObjectID`,`txtObjectUser`,`txtObjectRead`,`txtObjectWrite`) VALUES (\"" . md5($post['txtGroupName']) . "\", \"" . $user . "\", \"1\", \"1\") ON DUPLICATE KEY UPDATE `txtObjectID` = \"" . md5($post['txtGroupName']) . "\",`txtObjectUser` = \"" . $user . "\",`txtObjectRead` = \"1\", `txtObjectWrite` = \"1\"";
}
function dresource($post)
{
return "DELETE FROM `resources` WHERE `txtObjectID` = \"" . md5($post['txtGroupName']) . "\" LIMIT 1";
}
function dgresource($post)
{
return "DELETE FROM `gresources` WHERE `txtObjectGroup` = \"" . $post['txtGroupName'] . "\"";
}
function duresource($user)
{
return "DELETE FROM `uresources` WHERE `txtObjectName` = \"" . md5($user) . "\"";
}
function dresourcebyname($user)
{
return "DELETE FROM `resources` WHERE `txtObjectName` = \"" . $user . "\"";
}
function execute($sql)
{
global $defined, $handles;
if(count($sql)>0) {
$dbconn = $handles['db']->dbConnect( $defined['dbhost'], $defined['username'], $defined['password'], $defined['dbname'] );
foreach($sql as $key => $value) {
if(($res = $handles['db']->dbQuery($handles['val']->ValidateSQL($value, $dbconn), $dbconn))!==-1) {
if(($a=$handles['db']->dbNumRowsAffected($dbconn))>0) {
$a++;
$return = $a;
}
} else {
$return = '-1';
}
}
$handles['db']->dbFixTable("groups", $dbconn);
$handles['db']->dbFixTable("resources", $dbconn);
$handles['db']->dbFixTable("gresources", $dbconn);
$handles['db']->dbFixTable("uresources", $dbconn);
$handles['db']->dbFreeData($dbconn);
$handles['db']->dbCloseConn($dbconn);
}
return $return;
}
function createImportForm($post)
{
global $defined, $handles;
if( ( !empty( $defined['ldapuser'] ) ) && ( !empty( $defined['ldappass'] ) ) && ( !empty( $defined['ldapdomain'] ) ) && ( !empty( $defined['ldapserv'] ) ) && ( !empty( $defined['ldapport'] ) ) && ( !empty( $defined['binddn'] ) ) && ( !empty( $defined['basedn'] ) ) ) {
if( ( $ldapConn = $handles['ldap']->connect( $defined['ldapserv'], $defined['ldapport'] ) ) === -1 ) {
$importLDAPGrps = $handles['err']->GenerateErrorLink( "help/help.php", "#ldap_connect", $defined['error'], $errors['ldap_connect_err'], '800', '800' );
} else {
if( ( $ldapBind = $handles['ldap']->bind( $ldapConn, $defined['ldapuser'] . "@" . $defined['ldapdomain'], $defined['ldappass'] ) ) === 0 ) {
$ldap_data = $handles['ldap']->queryGroups( $ldapConn, $defined['basedn'] );
$ldap_data = $handles['ldap']->getEntries( $ldapConn, $ldap_data );
$ldap_data = $handles['ldap']->filterGroupsResults( $ldap_data );
if( count( $ldap_data ) > 0 ) {
$importLDAPGrps = $this->CreateSelectBoxGroups( $ldap_data );
} else {
$importLDAPGrps = $handles['err']->GenerateErrorLink( "help/help.php", "#ldap_connect", $defined['error'], $errors['ldap_connect_err'], '800', '800' );
}
} else {
$importLDAPGrps = $handles['err']->GenerateErrorLink( "help/help.php", "#ldap_connect", $defined['error'], $errors['ldap_connect_err'], '800', '800' );
}
}
} else {
$importLDAPGrps = $handles['err']->GenerateErrorLink( "help/help.php", "#ldap_options", $defined['error'], $errors['ldap_options_err'] . " I am not configured to utilize OpenLDAP/Active Directory functionality. Please configure an optional authentication source under the configuration menu.", '600', '600' );
}
return $importLDAPGrps;
}
function import($post,$user)
{
global $defined, $handles;
if( !empty( $post['ldap_groups'] ) ) {
if( count( $post['ldap_groups'] ) > 0 ) {
$dbconn = $handles['db']->dbConnect( $defined['dbhost'], $defined['username'], $defined['password'], $defined['dbname'] );
foreach( $post['ldap_groups'] as $key => $value ) {
if( ( !empty( $defined['ldapuser'] ) ) && ( !empty( $defined['ldappass'] ) ) && ( !empty( $defined['ldapdomain'] ) ) && ( !empty( $defined['ldapserv'] ) ) && ( !empty( $defined['ldapport'] ) ) && ( !empty( $defined['binddn'] ) ) && ( !empty( $defined['basedn'] ) ) ) {
if( ( $ldapConn = $handles['ldap']->connect( $defined['ldapserv'], $defined['ldapport'] ) ) === -1 ) {
$ldap_users = $handles['err']->GenerateErrorLink( "help/help.php", "#ldap_connect", $defined['error'], $errors['ldap_connect_err'] . $list, '600', '600' );
} else {
if( ( $ldapBind = $handles['ldap']->bind( $ldapConn, $defined['ldapuser'] . "@" . $defined['ldapdomain'], $defined['ldappass'] ) ) === 0 ) {
$ldap_data = $handles['ldap']->queryObject( $ldapConn, $defined['basedn'], $value );
$ldap_data = $handles['ldap']->getEntries( $ldapConn, $ldap_data );
$ldap_data = $handles['ldap']->filterGroupsResults( $ldap_data );
if( count( $ldap_data ) > 0 ) {
$list = "<ol>";
foreach( $ldap_data as $obj => $tmp ) {
if( !empty( $tmp['username'] ) ) {
if( ( count( $tmp['members']) > 0 ) && ( count( $post['add_ldap_users'] ) > 0 ) ) {
$usr_count = 0;
$count = 0;
$perm_count = 0;
foreach( $tmp['members'] as $usr => $val ) {
$ldap_usr = $handles['ldap']->queryUserByDN( $ldapConn, $val );
$data = $handles['ldap']->getEntries( $ldapConn, $ldap_usr );
$data = $handles['ldap']->filterUserResults( $data );
if( ($data[$val]['username'] !== "admin" ) || ($data[$val]['username'] !== "Administrator")) {
$sql_usr = "INSERT INTO `users` ( `txtUserName`, `txtUserLevel`, `txtUserGroup`, `create_date`, `create_time`, `reset`, `owner` ) VALUES ( \"" . $data[$val]['username'] . "\", \"user\", \"" . $tmp['username'] . "\", \"" . $data[$val]['create_date'] . "\", \"" . $data[$val]['create_time'] . "\", \"FALSE\", \"" . $user . "\" ) ON DUPLICATE KEY UPDATE `txtUserName` = \"" . $data[$val]['username'] . "\", `txtUserLevel` = \"user\", `txtUserGroup` = \"" . $tmp['username'] . "\", `create_date` = \"" . $data[$val]['create_date'] . "\", `create_time` = \"" . $data[$val]['create_time'] . "\", `reset` = \"FALSE\", `owner` = \"" . $user . "\"";
}
if( ( $sql_res = $handles['db']->dbQuery( $handles['val']->ValidateSQL( $sql_usr, $dbconn ), $dbconn ) ) === -1 ) {
$err_chk = 1;
$list .= "<li>Error importing corresponding group member '" . $data[$val]['username'] . "'</li>";
} else {
$err_chk = 0;
$usr_count = $usr_count + $handles['db']->dbNumRowsAffected( $dbconn );
$res_usr['resource'] = "INSERT INTO `resources` (`txtObjectID`,`txtObjectName`,`txtObjectOwner`) VALUES (\"" . md5($data[$val]['username']) . "\", \"" . $data[$val]['username'] . "\", \"" . $user . "\") ON DUPLICATE KEY UPDATE `txtObjectID` = \"" . md5($data[$val]['username']) . "\",`txtObjectName` = \"" . $data[$val]['username'] . "\"";
$res_usr['gresource'] = "INSERT INTO `gresources` (`txtObjectID`,`txtObjectGroup`,`txtObjectRead`,`txtObjectWrite`) VALUES (\"" . md5($data[$val]['username']) . "\", \"" . $tmp['username'] . "\", \"1\", \"1\") ON DUPLICATE KEY UPDATE `txtObjectID` = \"" . md5($data[$val]['username']) . "\",`txtObjectGroup` = \"" . $tmp['username'] . "\",`txtObjectRead` = \"1\", `txtObjectWrite` = \"1\"";
$res_usr['uresource'] = "INSERT INTO `uresources` (`txtObjectID`,`txtObjectUser`,`txtObjectRead`,`txtObjectWrite`) VALUES (\"" . md5($data[$val]['username']) . "\", \"" . $user . "\", \"1\", \"1\") ON DUPLICATE KEY UPDATE `txtObjectID` = \"" . md5($data[$val]['username']) . "\",`txtObjectUser` = \"" . $user . "\",`txtObjectRead` = \"1\", `txtObjectWrite` = \"1\"";
foreach($res_usr as $k => $v){
if( ( $sql_res = $handles['db']->dbQuery( $handles['val']->ValidateSQL( $v, $dbconn ), $dbconn ) ) === -1 ) {
$err_chk = 1;
$list .= "<li>Error while setting permission objects for '" . $data[$val]['username'] . "'</li>";
} else {
$err_chk = 0;
$perm_count = $perm_count + $handles['db']->dbNumRowsAffected( $dbconn );
}
}
}
}
}
if( $tmp['username'] !== "admin" ) {
$sql = "INSERT INTO `groups` ( `txtGroupName`, `txtGroupDescription`, `owner` ) VALUES ( \"" . $tmp['username'] . "\", \"" . $tmp['description'] . "\", \"" . $username . "\" ) ON DUPLICATE KEY UPDATE `txtGroupName` = \"" . $tmp['username'] . "\", `txtGroupDescription` = \"" . $tmp['description'] . "\", `owner` = \"" . $username . "\"";
}
if( ( $sql_res = $handles['db']->dbQuery( $handles['val']->ValidateSQL( $sql, $dbconn ), $dbconn ) ) === -1 ) {
$err_chk = 1;
$list .= "<li>Error importing " . $data['username'] . "</li>";
} else {
$err_chk = 0;
$count = $count + $handles['db']->dbNumRowsAffected( $dbconn );
$res_grp['resource'] = "INSERT INTO `resources` (`txtObjectID`,`txtObjectName`,`txtObjectOwner`) VALUES (\"" . md5($tmp['username']) . "\", \"" . $tmp['username'] . "\", \"" . $user . "\") ON DUPLICATE KEY UPDATE `txtObjectID` = \"" . md5($tmp['username']) . "\",`txtObjectName` = \"" . $tmp['username'] . "\"";
$res_grp['gresource'] = "INSERT INTO `gresources` (`txtObjectID`,`txtObjectGroup`,`txtObjectRead`,`txtObjectWrite`) VALUES (\"" . md5($tmp['username']) . "\", \"" . $tmp['username'] . "\", \"1\", \"1\") ON DUPLICATE KEY UPDATE `txtObjectID` = \"" . md5($tmp['username']) . "\",`txtObjectGroup` = \"" . $tmp['username'] . "\",`txtObjectRead` = \"1\", `txtObjectWrite` = \"1\"";
$res_grp['uresource'] = "INSERT INTO `uresources` (`txtObjectID`,`txtObjectUser`,`txtObjectRead`,`txtObjectWrite`) VALUES (\"" . md5($tmp['username']) . "\", \"" . $user . "\", \"1\", \"1\") ON DUPLICATE KEY UPDATE `txtObjectID` = \"" . md5($tmp['username']) . "\",`txtObjectUser` = \"" . $user['username'] . "\",`txtObjectRead` = \"1\", `txtObjectWrite` = \"1\"";
foreach($res_grp as $k => $v){
if( ( $sql_res = $handles['db']->dbQuery( $handles['val']->ValidateSQL( $v, $dbconn ), $dbconn ) ) === -1 ) {
$err_chk = 1;
$list .= "<li>Error setting permission objects for '" . $tmp['username'] . "'</li>";
} else {
$err_chk = 0;
$perm_count = $perm_count + $handles['db']->dbNumRowsAffected( $dbconn );
}
}
}
}
}
$list .= "</ol>";
if( $err_chk === 1 ) {
$message = $handles['err']->GenerateErrorLink( "help/help.php", "#ldap_groups", $defined['error'], "There was an error during importing of Active Directory/OpenLDAP groups" . $list, '600', '600' );
} else {
$message = $handles['err']->GenerateErrorLink( "help/help.php", "#ldap_groups", $defined['good'], "The importing of " . $count . " groups and " . $usr_count . " users was completed. Also set " . $perm_count . " of default permissions" . $list, '600', '600' );
}
} else {
$message = $handles['err']->GenerateErrorLink( "help/help.php", "#ldap_connect", $defined['error'], $errors['ldap_connect_err'], '600', '600' );
}
} else {
$message = $handles['err']->GenerateErrorLink( "help/help.php", "#ldap_connect", $defined['error'], $errors['ldap_connect_err'], '600', '600' );
}
}
} else {
$message = $handles['err']->GenerateErrorLink( "help/help.php", "#ldap_options", $defined['error'], $errors['ldap_options_err'], '600', '600' );
}
}
}
}
$handles['db']->dbFixTable("groups", $dbconn);
$handles['db']->dbFixTable("users", $dbconn);
$handles['db']->dbFixTable("resources", $dbconn);
$handles['db']->dbFixTable("gresources", $dbconn);
$handles['db']->dbFixTable("uresources", $dbconn);
$handles['db']->dbFreeData($dbconn);
$handles['db']->dbCloseConn($dbconn);
return $message;
}
function CreateSelectBoxGroups( $groups )
{
if( count( $groups ) > 0 ) {
asort($groups);
$html .= "<table>";
$html .= "<tr><td colspan=2><SELECT name=\"ldap_groups[]\" size=\"15\" style=\"width: 600px;\" multiple>";
foreach( $groups as $key => $value ) {
$html .= "<option value=\"" . $value['username'] . "\">" . $value['username'] . "</option>";
}
$html .= "</SELECT></td></tr>";
$html .= "<tr><td width=150><b>Add group members?</b></td><td><input type=\"checkbox\" name=\"add_ldap_users\" value=\"1\"></td></tr>";
}
return $html;
}
function GenDropMenuWSelectedGroups( $array, $selected, $name )
{
global $handles;
if( count( $array[0] ) !== 0 ) {
$list .= "<select id=\"" . $name . "\" name=\"". $name . "\" style=\"width: 100%\">";
if( !empty( $selected ) ) {
$list .= "<option value=\"" . $selected . "\">" . $selected . "</option>";
}
$list .= "<option>---------------</option>";
foreach( $array as $key => $value ) {
$value['txtGroupName'] = $handles['misc']->TrimString( $value['txtGroupName'], 60 );
$list .= "<option value=\"" . $value['txtGroupName'] . "\">" . $value['txtGroupName'] . "</option>";
}
$list .= "</select>";
}
return $list;
}
}
?>