Advertisement
Guest User

Untitled

a guest
Nov 1st, 2017
133
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 36.21 KB | None | 0 0
  1. <?php
  2. /*****************************************************************************\
  3. *                                                                            *
  4. *   File name     edit_users.php                                             *
  5. *                                                                            *
  6. *   Description   Edit the user database                                     *
  7. *                                                                            *
  8. *   Notes         Automatically creates the database if it's not present.    *
  9. *                                                                            *
  10. *                 Designed to be easily extensible:                          *
  11. *                 Adding more fields for each user does not require          *
  12. *                 modifying the editor code. Only to add the fields in       *
  13. *                 the database creation code.                                *
  14. *                                                                            *
  15. *                 An admin rights model is used where the level (an          *
  16. *                 integer between 0 and $max_level) denotes rights:          *
  17. *                      0:  no rights                                         *
  18. *                      1:  an ordinary user                                  *
  19. *                      2+: admins, with increasing rights.   Designed to     *
  20. *                          allow more granularity of admin rights, for       *
  21. *                          example by having booking admins, user admins     *
  22. *                          snd system admins.  (System admins might be       *
  23. *                          necessary in the future if, for example, some     *
  24. *                          parameters curreently in the config file are      *
  25. *                          made editable from MRBS)                          *
  26. *                                                                            *
  27. *                 Only admins with at least user editing rights (level >=    *
  28. *                 $min_user_editing_level) can edit other users, and they    *
  29. *                 cannot edit users with a higher level than themselves      *
  30. *                                                                            *
  31. *                 To do:                                                     *
  32. *                     - Localisability                                       *
  33. *                                                                            *
  34. *   History                                                                  *
  35. *                 2003/12/29 JFL Created this file                           *
  36. *                                                                            *
  37. \*****************************************************************************/
  38.  
  39. // $Id: edit_users.php 1779 2011-01-30 10:06:06Z cimorrison $
  40.  
  41. require_once "defaultincludes.inc";
  42.  
  43. // Get non-standard form variables
  44. $Action = get_form_var('Action', 'string');
  45. $Id = get_form_var('Id', 'int');
  46. $password0 = get_form_var('password0', 'string');
  47. $password1 = get_form_var('password1', 'string');
  48. $invalid_email = get_form_var('invalid_email', 'int');
  49. $name_empty = get_form_var('name_empty', 'int');
  50. $name_not_unique = get_form_var('name_not_unique', 'int');
  51. $taken_name = get_form_var('taken_name', 'string');
  52. $pwd_not_match = get_form_var('pwd_not_match', 'string');
  53. $pwd_invalid = get_form_var('pwd_invalid', 'string');
  54.  
  55. // Validates that the password conforms to the password policy
  56. // (Ideally this function should also be matched by client-side
  57. // validation, but unfortunately JavaScript's native support for Unicode
  58. // pattern matching is very limited.   Would need to be implemented using
  59. // an add-in library).
  60. function validate_password($password)
  61. {
  62.   global $pwd_policy;
  63.          
  64.   if (isset($pwd_policy))
  65.   {
  66.     // Set up regular expressions.  Use p{Ll} instead of [a-z] etc.
  67.     // to make sure accented characters are included
  68.     $pattern = array('alpha'   => '/\p{L}/',
  69.                      'lower'   => '/\p{Ll}/',
  70.                      'upper'   => '/\p{Lu}/',
  71.                      'numeric' => '/\p{N}/',
  72.                      'special' => '/[^\p{L}|\p{N}]/');
  73.     // Check for conformance to each rule                
  74.     foreach($pwd_policy as $rule => $value)
  75.     {
  76.       switch($rule)
  77.       {
  78.         case 'length':
  79.           // assumes that the site has enabled multi-byte string function
  80.           // overloading if necessary in php.ini
  81.           if (strlen($password) < $pwd_policy[$rule])
  82.           {
  83.             return FALSE;
  84.           }
  85.           break;
  86.         default:
  87.           // turn on Unicode matching
  88.           $pattern[$rule] .= 'u';
  89.  
  90.           $n = preg_match_all($pattern[$rule], $password, $matches);
  91.           if (($n === FALSE) || ($n < $pwd_policy[$rule]))
  92.           {
  93.             return FALSE;
  94.           }
  95.           break;
  96.       }
  97.     }
  98.   }
  99.  
  100.   // Everything is OK
  101.   return TRUE;
  102. }
  103.  
  104.  
  105. // Get the type that should be used with get_form_var() for
  106. // a field which is a member of the array returned by get_field_info()
  107. function get_form_var_type($field)
  108. {
  109.   switch($field['nature'])
  110.   {
  111.     case 'character':
  112.       $type = 'string';
  113.       break;
  114.     case 'integer':
  115.       $type = 'int';
  116.       break;
  117.     // We can only really deal with the types above at the moment
  118.     default:
  119.       $type = 'string';
  120.       break;
  121.   }
  122.   return $type;
  123. }
  124.  
  125.  
  126. // Produce the HTML for a freeze_panes sub-table
  127. //
  128. //   $info       an array containing the data
  129. //   $columns    the columns in that data to display
  130. //   $class      the class name tio assign to the table
  131. //   $action     whether an action button is required
  132. function freeze_panes_table_html($info, $columns, $class, $action=FALSE)
  133. {
  134.   global $tbl_users, $PHP_SELF;
  135.   global $user, $level, $min_user_editing_level, $max_content_length;
  136.   global $fields, $auth;
  137.  
  138.   $html = '';
  139.   $html .= "<div class=\"$class\">\n";
  140.   $html .= "<table class=\"admin_table\">\n";
  141.   $html .= "<thead>\n";
  142.   $html .= "<tr>";
  143.   if ($action)
  144.   {
  145.     // First column which is an action button
  146.     $html .= "<th><div>" . get_vocab("action") . "</div></th>";
  147.   }
  148.  
  149.   // Column headers
  150.   foreach ($fields as $field)
  151.   {
  152.     $fieldname = $field['name'];
  153.     if (in_array($fieldname, $columns))
  154.     {
  155.       $html .= "<th><div>" . get_loc_field_name($tbl_users, $fieldname) . "</div></th>";
  156.     }
  157.   }
  158.  
  159.   $html .= "</tr>\n";
  160.   $html .= "</thead>\n";
  161.  
  162.   $html .= "<tbody>\n";
  163.   $row_class = "odd_row";
  164.   foreach ($info as $line)
  165.   {
  166.     // Check whether ordinary users are allowed to see other users' details.  If not,
  167.     // then skip past this row if it's not the current user or the user is not an admin
  168.     if ($auth['only_admin_can_see_other_users'] &&
  169.         ($level < $min_user_editing_level) &&
  170.         (strcasecmp($line['name'], $user) != 0))
  171.     {
  172.       continue;
  173.     }
  174.    
  175.     $row_class = ($row_class == "even_row") ? "odd_row" : "even_row";
  176.     $html .= "<tr class=\"$row_class\">\n";
  177.     if ($action)
  178.     {
  179.       // First column (the action button)
  180.       $html .= "<td class=\"action\"><div>\n";
  181.       // You can only edit a user if you have sufficient admin rights, or else if that user is yourself
  182.       if (($level >= $min_user_editing_level) || (strcasecmp($line['name'], $user) == 0))
  183.       {
  184.         $html .= "<form method=\"post\" action=\"" . htmlspecialchars(basename($PHP_SELF)) . "\">\n";
  185.         $html .= "<div>\n";
  186.         $html .= "<input type=\"hidden\" name=\"Action\" value=\"Edit\">\n";
  187.         $html .= "<input type=\"hidden\" name=\"Id\" value=\"" . $line['id'] . "\">\n";
  188.         $html .= "<input type=\"image\" class=\"button\" src=\"images/edit.png\"
  189.                   title=\"" . get_vocab("edit") . "\" alt=\"" . get_vocab("edit") . "\">\n";
  190.         $html .= "</div>\n";
  191.         $html .= "</form>\n";
  192.       }
  193.       else
  194.       {
  195.         $html .= "&nbsp;\n";
  196.       }
  197.       $html .= "</div></td>\n";
  198.     }
  199.    
  200.     // Column contents
  201.     foreach ($fields as $field)
  202.     {
  203.       $key = $field['name'];
  204.       if (in_array($key, $columns))
  205.       {
  206.         $col_value = $line[$key];
  207.         switch($key)
  208.         {
  209.           // special treatment for some fields
  210.           case 'level':
  211.             // the level field contains a code and we want to display a string
  212.             $html .= "<td><div>" . get_vocab("level_$col_value") . "</div></td>\n";
  213.             break;
  214.           case 'email':
  215.             // we don't want to truncate the email address
  216.             $html .= "<td><div>" . htmlspecialchars($col_value) . "</div></td>\n";
  217.             break;
  218.           default:
  219.             if (($field['nature'] == 'boolean') ||
  220.                 (($field['nature'] == 'integer') && isset($field['length']) && ($field['length'] <= 2)) )
  221.             {
  222.               // booleans: represent by a checkmark
  223.               $html .= "<td class=\"int\"><div>";
  224.               $html .= (!empty($col_value)) ? "<img src=\"images/check.png\" alt=\"check mark\" width=\"16\" height=\"16\">" : "&nbsp;";
  225.               $html .= "</div></td>\n";
  226.             }
  227.             elseif (($field['nature'] == 'integer') && isset($field['length']) && ($field['length'] > 2))
  228.             {
  229.               // integer values
  230.               $html .= "<td class=\"int\"><div>" . $col_value . "</div></td>\n";
  231.             }
  232.             else
  233.             {
  234.                // strings
  235.               $html .= "<td title=\"" . htmlspecialchars($col_value) . "\"><div>";
  236.               // Truncate before conversion, otherwise you could chop off in the middle of an entity
  237.               $html .= htmlspecialchars(substr($col_value, 0, $max_content_length));
  238.               $html .= (strlen($col_value) > $max_content_length) ? " ..." : "";
  239.               $html .= "</div></td>\n";
  240.             }
  241.             break;
  242.         }  // end switch
  243.       }
  244.     }  // end foreach
  245.    
  246.     $html .= "</tr>\n";
  247.    
  248.   }  // end while
  249.  
  250.   $html .= "</tbody>\n";
  251.   $html .= "</table>\n";
  252.   $html .= "</div>\n";
  253.  
  254.   return $html;
  255. }
  256.  
  257.  
  258. // Get the information about the fields in the users table
  259. $fields = sql_field_info($tbl_users);
  260.  
  261. $nusers = sql_query1("SELECT COUNT(*) FROM $tbl_users");
  262.  
  263. /*---------------------------------------------------------------------------*\
  264. |                         Authenticate the current user                         |
  265. \*---------------------------------------------------------------------------*/
  266.  
  267. $initial_user_creation = 0;
  268.  
  269. if ($nusers > 0)
  270. {
  271.   $user = getUserName();
  272.   $level = authGetUserLevel($user);
  273.   // Check the user is authorised for this page
  274.   checkAuthorised();
  275. }
  276. else
  277. // We've just created the table.   Assume the person doing this IS an administrator
  278. // and then send them through to the screen to add the first user (which we'll force
  279. // to be an admin)
  280. {
  281.   $initial_user_creation = 1;
  282.   if (!isset($Action))   // second time through it will be set to "Update"
  283.   {
  284.     $Action = "Add";
  285.     $Id = -1;
  286.   }
  287.   $level = $max_level;
  288.   $user = "";           // to avoid an undefined variable notice
  289. }
  290.  
  291. /*---------------------------------------------------------------------------*\
  292. |             Edit a given entry - 1st phase: Get the user input.             |
  293. \*---------------------------------------------------------------------------*/
  294.  
  295. if (isset($Action) && ( ($Action == "Edit") or ($Action == "Add") ))
  296. {
  297.  
  298.   if ($Id >= 0) /* -1 for new users, or >=0 for existing ones */
  299.   {
  300.     // If it's an existing user then get the data from the database
  301.     $result = sql_query("select * from $tbl_users where id=$Id");
  302.     $data = sql_row_keyed($result, 0);
  303.     sql_free($result);
  304.   }
  305.   if (($Id == -1) || (!$data))
  306.   {
  307.     // Otherwise try and get the data from the query string, and if it's
  308.     // not there set the default to be blank.  (The data will be in the
  309.     // query string if there was an error on validating the data after it
  310.     // had been submitted.   We want to preserve the user's original values
  311.     // so that they don't have to re-type them).
  312.     foreach ($fields as $field)
  313.     {
  314.       $type = get_form_var_type($field);
  315.       $value = get_form_var($field['name'], $type);
  316.       $data[$field['name']] = (isset($value)) ? $value : "";
  317.     }
  318.   }
  319.  
  320.   /* First make sure the user is authorized */
  321.   if (!$initial_user_creation && !auth_can_edit_user($user, $data['name']))
  322.   {
  323.     showAccessDenied(0, 0, 0, "", "");
  324.     exit();
  325.   }
  326.  
  327.   print_header(0, 0, 0, 0, "");
  328.  
  329.   if ($initial_user_creation == 1)
  330.   {
  331.     print "<h3>" . get_vocab("no_users_initial") . "</h3>\n";
  332.     print "<p>" . get_vocab("no_users_create_first_admin") . "</p>\n";
  333.   }
  334.  
  335.   print "<div id=\"form_container\">";
  336.   print "<form id=\"form_edit_users\" method=\"post\" action=\"" . htmlspecialchars(basename($PHP_SELF)). "\">\n";
  337.     ?>
  338.         <fieldset class="admin">
  339.         <legend><?php echo (($Action == "Edit") ? get_vocab("edit_user") : get_vocab("add_new_user"));?></legend>
  340.         <div id="edit_users_input_container">
  341.           <?php
  342.           // Find out how many admins are left in the table - it's disastrous if the last one is deleted,
  343.           // or admin rights are removed!
  344.           if ($Action == "Edit")
  345.           {
  346.             $n_admins = sql_query1("select count(*) from $tbl_users where level=$max_level");
  347.             $editing_last_admin = ($n_admins <= 1) && ($data['level'] == $max_level);
  348.           }
  349.           else
  350.           {
  351.             $editing_last_admin = FALSE;
  352.           }
  353.          
  354.           // Work out whether the level select input should be disabled (NB you can't make a <select> readonly)
  355.           // We don't want the user to be able to change the level if (a) it's the first user being created or
  356.           // (b) it's the last admin left or (c) they don't have admin rights
  357.           $disable_select = ($initial_user_creation || $editing_last_admin || ($level < $min_user_editing_level));
  358.          
  359.           foreach ($fields as $field)
  360.           {
  361.             $key = $field['name'];
  362.             $var_name = VAR_PREFIX . $key;
  363.             // First of all output the input for the field
  364.             // The ID field cannot change; The password field must not be shown.
  365.             switch($key)
  366.             {
  367.               case 'id':
  368.                 echo "<input type=\"hidden\" name=\"Id\" value=\"$Id\">\n";
  369.                 break;
  370.               case 'password':
  371.                 echo "<input type=\"hidden\" name=\"$var_name\" value=\"". htmlspecialchars($data[$key]) . "\">\n";
  372.                 break;
  373.               default:
  374.                 echo "<div>\n";
  375.                 $label_text = get_loc_field_name($tbl_users, $key);
  376.                 switch($key)
  377.                 {
  378.                   case 'level':
  379.                     echo "<label for=\"$var_name\">$label_text:</label>\n";
  380.                     echo "<select id=\"$var_name\" name=\"$var_name\"" . ($disable_select ? " disabled=\"disabled\"" : "") . ">\n";
  381.                     // Only display options up to and including one's own level (you can't upgrade yourself).
  382.                     // If you're not some kind of admin then the select will also be disabled.
  383.                     // (Note - disabling individual options doesn't work in older browsers, eg IE6)    
  384.                     for ($i=0; $i<=$level; $i++)
  385.                     {
  386.                       echo "<option value=\"$i\"";
  387.                       // Work out which option should be selected by default:
  388.                       //   if we're editing an existing entry, then it should be the current value;
  389.                       //   if we're adding the very first entry, then it should be an admin;
  390.                       //   if we're adding a subsequent entry, then it should be an ordinary user;
  391.                       if ( (($Action == "Edit")  && ($i == $data[$key])) ||
  392.                            (($Action == "Add") && $initial_user_creation && ($i == $max_level)) ||
  393.                            (($Action == "Add") && !$initial_user_creation && ($i == 1)) )
  394.                       {
  395.                         echo " selected=\"selected\"";
  396.                       }
  397.                       echo ">" . get_vocab("level_$i") . "</option>\n";
  398.                     }
  399.                     echo "</select>\n";
  400.                     // If the level select input was disabled, we still need to submit a value with
  401.                     // the form.   <select> can't be set to 'readonly' so instead we'll use a hidden input
  402.                     if ($disable_select)
  403.                     {
  404.                       if ($initial_user_creation)
  405.                       {
  406.                         $v = $max_level;
  407.                       }
  408.                       else
  409.                       {
  410.                         $v = $data[$key];
  411.                       }
  412.                       echo "<input type=\"hidden\" name=\"$var_name\" value=\"$v\">\n";
  413.                     }
  414.                     break;
  415.                   case 'name':
  416.                     // you cannot change a username (even your own) unless you have user editing rights
  417.                     echo "<label for=\"$var_name\">$label_text:</label>\n";
  418.                     echo "<input id=\"$var_name\" name=\"$var_name\" type=\"text\" " .
  419.                          ((isset($maxlength["users.$key"])) ? "maxlength=\"" . $maxlength["users.$key"] . "\" " : '') .
  420.                          (($level < $min_user_editing_level) ? "disabled=\"disabled\" " : "") .
  421.                           "value=\"" . htmlspecialchars($data[$key]) . "\">\n";
  422.                     // if the field was disabled then we still need to pass through the value as a hidden input
  423.                     if ($level < $min_user_editing_level)
  424.                     {
  425.                       echo "<input type=\"hidden\" name=\"$var_name\" value=\"" . $data[$key] . "\">\n";
  426.                     }
  427.                     break;
  428.                   case 'email':
  429.                     generate_input($label_text, $var_name, $data[$key], FALSE, isset($maxlength["users.$key"]) ? $maxlength["users.$key"] : NULL);
  430.                     break;
  431.                   default:    
  432.                     // Output a checkbox if it's a boolean or integer <= 2 bytes (which we will
  433.                     // assume are intended to be booleans)
  434.                     if (($field['nature'] == 'boolean') ||
  435.                         (($field['nature'] == 'integer') && isset($field['length']) && ($field['length'] <= 2)) )
  436.                     {
  437.                       echo "<label for=\"$var_name\">$label_text:</label>\n";
  438.                       echo "<input type=\"checkbox\" class=\"checkbox\" " .
  439.                             "id=\"$var_name\" name=\"$var_name\" value=\"1\"" .
  440.                             ((!empty($data[$key])) ? " checked=\"checked\"" : "") .
  441.                             ">\n";
  442.                     }
  443.                     // Output a select box if they want one
  444.                     elseif (count($select_options["users.$key"]) > 0)
  445.                     {
  446.                       generate_select($label_text, $var_name, $data[$key], $select_options["users.$key"]);
  447.                     }
  448.                     // Output a textarea if it's a character string longer than the limit for a
  449.                     // text input
  450.                     elseif (($field['nature'] == 'character') && isset($field['length']) && ($field['length'] > $text_input_max))
  451.                     {
  452.                       generate_textarea($label_text, $var_name, $data[$key]);  
  453.                     }
  454.                     // Otherwise output a text input
  455.                     else
  456.                     {
  457.                       generate_input($label_text, $var_name, $data[$key], FALSE, isset($maxlength["users.$key"]) ? $maxlength["users.$key"] : NULL);
  458.                     }
  459.                     break;
  460.                 } // end switch
  461.                 echo "</div>\n";
  462.             } // end switch
  463.            
  464.            
  465.             // Then output any error messages associated with the field
  466.             // except for the password field which is a special case
  467.             switch($key)
  468.             {
  469.               case 'email':
  470.                 if (!empty($invalid_email))
  471.                 {
  472.                   echo "<p class=\"error\">" . get_vocab('invalid_email') . "</p>\n";
  473.                 }
  474.                 break;
  475.               case 'name':
  476.                 if (!empty($name_not_unique))
  477.                 {
  478.                   echo "<p class=\"error\">'" . htmlspecialchars($taken_name) . "' " . get_vocab('name_not_unique') . "<p>\n";
  479.                 }
  480.                 if (!empty($name_empty))
  481.                 {
  482.                   echo "<p class=\"error\">" . get_vocab('name_empty') . "<p>\n";
  483.                 }
  484.                 break;
  485.             }
  486.                      
  487.           } // end foreach
  488.      
  489.           print "<div><p>" . get_vocab("password_twice") . "...</p></div>\n";
  490.  
  491.           for ($i=0; $i<2; $i++)
  492.           {
  493.             print "<div>\n";
  494.             print "<label for=\"password$i\">" . get_vocab("users.password") . ":</label>\n";
  495.             print "<input type=\"password\" id=\"password$i\" name=\"password$i\" value=\"\">\n";
  496.             print "</div>\n";
  497.           }
  498.          
  499.           // Now do any password error messages
  500.           if (!empty($pwd_not_match))
  501.           {
  502.             echo "<p class=\"error\">" . get_vocab("passwords_not_eq") . "</p>\n";
  503.           }
  504.           if (!empty($pwd_invalid))
  505.           {
  506.             echo "<p class=\"error\">" . get_vocab("password_invalid") . "</p>\n";
  507.             if (isset($pwd_policy))
  508.             {
  509.               echo "<ul class=\"error\">\n";
  510.               foreach ($pwd_policy as $rule => $value)
  511.               {
  512.                 echo "<li>$value " . get_vocab("policy_" . $rule) . "</li>\n";
  513.               }
  514.               echo "</ul>\n";
  515.             }
  516.           }
  517.          
  518.           if ($editing_last_admin)
  519.           {
  520.             echo "<p><em>(" . get_vocab("warning_last_admin") . ")</em></p>\n";
  521.           }
  522.           ?>
  523.           <input type="hidden" name="Action" value="Update">    
  524.           <input class="submit" type="submit" value="<?php echo(get_vocab("save")); ?>">
  525.          
  526.         </div>
  527.         </fieldset>
  528.       </form>
  529.       <?php
  530.       /* Administrators get the right to delete users, but only those at the same level as them or lower */
  531.       if (($Id >= 0) && ($level >= $min_user_editing_level) && ($level >= $data['level']))
  532.       {
  533.         echo "<form id=\"form_delete_users\" method=\"post\" action=\"" . htmlspecialchars(basename($PHP_SELF)) . "\">\n";
  534.         echo "<div>\n";
  535.         echo "<input type=\"hidden\" name=\"Action\" value=\"Delete\">\n";
  536.         echo "<input type=\"hidden\" name=\"Id\" value=\"$Id\">\n";
  537.         echo "<input class=\"submit\" type=\"submit\" " .
  538.               (($editing_last_admin) ? "disabled=\"disabled\"" : "") .
  539.               "value=\"" . get_vocab("delete_user") . "\">\n";
  540.         echo "</div>\n";
  541.         echo "</form>\n";
  542.       }
  543. ?>
  544.       </div>
  545. <?php
  546.  
  547.   // Print footer and exit
  548.   print_footer(TRUE);
  549. }
  550.  
  551. /*---------------------------------------------------------------------------*\
  552. |             Edit a given entry - 2nd phase: Update the database.            |
  553. \*---------------------------------------------------------------------------*/
  554.  
  555. if (isset($Action) && ($Action == "Update"))
  556. {
  557.   // If you haven't got the rights to do this, then exit
  558.   $my_id = sql_query1("SELECT id FROM $tbl_users WHERE name='".addslashes($user)."' LIMIT 1");
  559.   if (($level < $min_user_editing_level) && ($Id != $my_id ))
  560.   {
  561.     Header("Location: edit_users.php");
  562.     exit;
  563.   }
  564.  
  565.   // otherwise go ahead and update the database
  566.   else
  567.   {
  568.     $values = array();
  569.     $q_string = ($Id >= 0) ? "Action=Edit" : "Action=Add";
  570.     foreach ($fields as $field)
  571.     {
  572.       $fieldname = $field['name'];
  573.       $type = get_form_var_type($field);
  574.       if ($fieldname == 'id')
  575.       {
  576.         // id: don't need to do anything except add the id to the query string;
  577.         // the field itself is auto-incremented
  578.         $q_string .= "&Id=$Id";
  579.         continue;
  580.       }
  581.       // first, get all the other form variables and put them into an array, $values, which
  582.       // we will use for entering into the database assuming we pass validation
  583.       $values[$fieldname] = get_form_var(VAR_PREFIX. $fieldname, $type);
  584.       // Truncate the field to the maximum length as a precaution.
  585.       if (isset($maxlength["users.$fieldname"]))
  586.       {
  587.         $values[$fieldname] = substr($values[$fieldname], 0, $maxlength["users.$fieldname"]);
  588.       }
  589.       // we will also put the data into a query string which we will use for passing
  590.       // back to this page if we fail validation.   This will enable us to reload the
  591.       // form with the original data so that the user doesn't have to
  592.       // re-enter it.  (Instead of passing the data in a query string we
  593.       // could pass them as session variables, but at the moment MRBS does
  594.       // not rely on PHP sessions).
  595.       switch ($fieldname)
  596.       {
  597.         // some of the fields get special treatment
  598.         case 'name':
  599.           // name: convert it to lower case
  600.           $q_string .= "&$fieldname=" . urlencode($values[$fieldname]);
  601.           $values[$fieldname] = strtolower($values[$fieldname]);
  602.           break;
  603.         case 'password':
  604.           // password: if the password field is blank it means
  605.           // that the user doesn't want to change the password
  606.           // so don't do anything; otherwise get the MD5 hash.
  607.           // Note: we don't put the password in the query string
  608.           // for security reasons.
  609.           if (!empty($password0))
  610.           {
  611.             $values[$fieldname]=md5($password0);
  612.           }
  613.           break;
  614.         case 'level':
  615.           // level:  set a safe default (lowest level of access)
  616.           // if there is no value set
  617.           $q_string .= "&$fieldname=" . $values[$fieldname];
  618.           if (!isset($values[$fieldname]))
  619.           {
  620.             $values[$fieldname] = 0;
  621.           }
  622.           // Check that we are not trying to upgrade our level.    This shouldn't be possible
  623.           // but someone might have spoofed the input in the edit form
  624.           if ($values[$fieldname] > $level)
  625.           {
  626.             Header("Location: edit_users.php");
  627.             exit;
  628.           }
  629.           break;
  630.         default:
  631.           $q_string .= "&$fieldname=" . urlencode($values[$fieldname]);
  632.           break;
  633.       }
  634.     }
  635.  
  636.     // Now do some form validation
  637.     $valid_data = TRUE;
  638.     foreach ($values as $fieldname => $value)
  639.     {
  640.       switch ($fieldname)
  641.       {
  642.         case 'name':
  643.           // check that the name is not empty
  644.           if (empty($value))
  645.           {
  646.             $valid_data = FALSE;
  647.             $q_string .= "&name_empty=1";
  648.           }
  649.           // Check that the name is unique.
  650.           // If it's a new user, then to check to see if there are any rows with that name.
  651.           // If it's an update, then check to see if there are any rows with that name, except
  652.           // for that user.
  653.           $query = "SELECT id FROM $tbl_users WHERE name='" . addslashes($value) . "'";
  654.           if ($Id >= 0)
  655.           {
  656.             $query .= " AND id!='$Id'";
  657.           }
  658.           $query .= " LIMIT 1";  // we only want to know if there is at least one instance of the name
  659.           $result = sql_query($query);
  660.           if (sql_count($result) > 0)
  661.           {
  662.             $valid_data = FALSE;
  663.             $q_string .= "&name_not_unique=1";
  664.             $q_string .= "&taken_name=$value";
  665.           }
  666.           break;
  667.         case 'password':
  668.           // check that the two passwords match
  669.           if ($password0 != $password1)
  670.           {
  671.             $valid_data = FALSE;
  672.             $q_string .= "&pwd_not_match=1";
  673.           }
  674.           // check that the password conforms to the password policy
  675.           // if it's a new user (Id < 0), or else it's an existing user
  676.           // trying to change their password
  677.           if (($Id <0) || !empty($password0))
  678.           {
  679.             if (!validate_password($password0))
  680.             {
  681.               $valid_data = FALSE;
  682.               $q_string .= "&pwd_invalid=1";
  683.             }
  684.           }
  685.           break;
  686.         case 'email':
  687.           // check that the email address is valid
  688.           if (!empty($value) && !validate_email_list($value))
  689.           {
  690.             $valid_data = FALSE;
  691.             $q_string .= "&invalid_email=1";
  692.           }
  693.           break;
  694.       }
  695.     }
  696.  
  697.     // if validation failed, go back to this page with the query
  698.     // string, which by now has both the error codes and the original
  699.     // form values
  700.     if (!$valid_data)
  701.     {
  702.       Header("Location: edit_users.php?$q_string");
  703.       exit;
  704.     }
  705.  
  706.    
  707.     // If we got here, then we've passed validation and we need to
  708.     // enter the data into the database
  709.    
  710.     $sql_fields = array();
  711.  
  712.     // For each db column get the value ready for the database
  713.     foreach ($fields as $field)
  714.     {
  715.       $fieldname = $field['name'];
  716.       if ($fieldname != 'id')
  717.       {
  718.         // pre-process the field value for SQL
  719.         $value = $values[$fieldname];
  720.         switch ($field['nature'])
  721.         {
  722.           case 'integer':
  723.             if (!isset($value) || ($value === ''))
  724.             {
  725.               // Try and set it to NULL when we can because there will be cases when we
  726.               // want to distinguish between NULL and 0 - especially when the field
  727.               // is a genuine integer.
  728.               $value = ($field['is_nullable']) ? 'NULL' : 0;
  729.             }
  730.             break;
  731.           default:
  732.             $value = "'" . addslashes($value) . "'";
  733.             break;
  734.         }
  735.        
  736.         /* If we got here, we have a valid, sql-ified value for this field,
  737.          * so save it for later */
  738.         $sql_fields[$fieldname] = $value;
  739.       }                  
  740.     } /* end for each column of user database */
  741.  
  742.     /* Now generate the SQL operation based on the given array of fields */
  743.     if ($Id >= 0)
  744.     {
  745.       /* if the Id exists - then we are editing an existing user, rather th
  746.        * creating a new one */
  747.  
  748.       $assign_array = array();
  749.       $operation = "UPDATE $tbl_users SET ";
  750.  
  751.       foreach ($sql_fields as $fieldname => $value)
  752.       {
  753.         // Note that we don't have to escape or quote the fieldname
  754.         // thanks to the restriction on custom field names
  755.         array_push($assign_array,"$fieldname=$value");
  756.       }
  757.       $operation .= implode(",", $assign_array) . " WHERE id=$Id;";
  758.     }
  759.     else
  760.     {
  761.       /* The id field doesn't exist, so we're adding a new user */
  762.  
  763.       $fields_list = array();
  764.       $values_list = array();
  765.  
  766.       foreach ($sql_fields as $fieldname => $value)
  767.       {
  768.         array_push($fields_list,$fieldname);
  769.         array_push($values_list,$value);
  770.       }
  771.       // Note that we don't have to escape or quote the fieldname
  772.       // thanks to the restriction on custom field names
  773.       $operation = "INSERT INTO $tbl_users " .
  774.         "(". implode(",",$fields_list) . ")" .
  775.         " VALUES " . "(" . implode(",",$values_list) . ");";
  776.     }
  777.  
  778.     /* DEBUG lines - check the actual sql statement going into the db */
  779.     //echo "Final SQL string: <code>" . htmlspecialchars($operation) . "</code>";
  780.     //exit;
  781.     $r = sql_command($operation);
  782.     if ($r == -1)
  783.     {
  784.       // Get the error message before the print_header() call because the print_header()
  785.       // function can contain SQL queries and so reset the error message.
  786.       trigger_error(sql_error(), E_USER_WARNING);
  787.       print_header(0, 0, 0, "", "");
  788.  
  789.       // This is unlikely to happen in normal operation. Do not translate.
  790.        
  791.       print "<form class=\"edit_users_error\" method=\"post\" action=\"" . htmlspecialchars(basename($PHP_SELF)) . "\">\n";
  792.       print "  <fieldset>\n";
  793.       print "  <legend></legend>\n";
  794.       print "    <p class=\"error\">Error updating the $tbl_users table.</p>\n";
  795.       print "    <input type=\"submit\" value=\" " . get_vocab("ok") . " \">\n";
  796.       print "  </fieldset>\n";
  797.       print "</form>\n";
  798.  
  799.       // Print footer and exit
  800.       print_footer(TRUE);
  801.     }
  802.  
  803.     /* Success. Redirect to the user list, to remove the form args */
  804.     Header("Location: edit_users.php");
  805.   }
  806. }
  807.  
  808. /*---------------------------------------------------------------------------*\
  809. |                                Delete a user                                |
  810. \*---------------------------------------------------------------------------*/
  811.  
  812. if (isset($Action) && ($Action == "Delete"))
  813. {
  814.   $target_level = sql_query1("SELECT level FROM $tbl_users WHERE id=$Id LIMIT 1");
  815.   if ($target_level < 0)
  816.   {
  817.     fatal_error(TRUE, "Fatal error while deleting a user");
  818.   }
  819.   // you can't delete a user if you're not some kind of admin, and then you can't
  820.   // delete someone higher than you
  821.   if (($level < $min_user_editing_level) || ($level < $target_level))
  822.   {
  823.     showAccessDenied(0, 0, 0, "", "");
  824.     exit();
  825.   }
  826.  
  827.   $r = sql_command("delete from $tbl_users where id=$Id;");
  828.   if ($r == -1)
  829.   {
  830.     print_header(0, 0, 0, "", "");
  831.  
  832.     // This is unlikely to happen in normal  operation. Do not translate.
  833.    
  834.     print "<form class=\"edit_users_error\" method=\"post\" action=\"" . htmlspecialchars(basename($PHP_SELF)) . "\">\n";
  835.     print "  <fieldset>\n";
  836.     print "  <legend></legend>\n";
  837.     print "    <p class=\"error\">Error deleting entry $Id from the $tbl_users table.</p>\n";
  838.     print "    <p class=\"error\">" . sql_error() . "</p>\n";
  839.     print "    <input type=\"submit\" value=\" " . get_vocab("ok") . " \">\n";
  840.     print "  </fieldset>\n";
  841.     print "</form>\n";
  842.  
  843.     // Print footer and exit
  844.     print_footer(TRUE);
  845.   }
  846.  
  847.   /* Success. Do not display a message. Simply fall through into the list display. */
  848. }
  849.  
  850. /*---------------------------------------------------------------------------*\
  851. |                          Display the list of users                          |
  852. \*---------------------------------------------------------------------------*/
  853.  
  854. /* Print the standard MRBS header */
  855.  
  856. print_header(0, 0, 0, "", "");
  857.  
  858. print "<h2>" . get_vocab("user_list") . "</h2>\n";
  859.  
  860. print "<h3> <a href='edit_organisations.php'>" . get_vocab("add_type_organisation") . " - ". get_vocab("add_organisation")."</a></h3>\n";
  861.  
  862. if ($level >= $min_user_editing_level) /* Administrators get the right to add new users */
  863. {
  864.   print "<form id=\"add_new_user\" method=\"post\" action=\"" . htmlspecialchars(basename($PHP_SELF)) . "\">\n";
  865.   print "  <div>\n";
  866.   print "    <input type=\"hidden\" name=\"Action\" value=\"Add\">\n";
  867.   print "    <input type=\"hidden\" name=\"Id\" value=\"-1\">\n";
  868.   print "    <input type=\"submit\" value=\"" . get_vocab("add_new_user") . "\">\n";
  869.   print "  </div>\n";
  870.   print "</form>\n";
  871. }
  872.  
  873. if ($initial_user_creation != 1)   // don't print the user table if there are no users
  874. {
  875.   // Get the user information
  876.   $res = sql_query("SELECT * FROM $tbl_users ORDER BY level DESC, name");
  877.   // Build an array with the user info
  878.   $info = array();
  879.   for ($i = 0; ($row = sql_row_keyed($res, $i)); $i++)
  880.   {
  881.     $info[] = $row;
  882.   }
  883.   // Display it in a table [Actually two tables side by side so that we can
  884.   // achieve a "Freeze Panes" effect: there doesn't seem to be a good way of
  885.   // getting a colgroup to scroll, so we have to distort the mark-up a little]
  886.   echo "<div id=\"user_list\">\n";
  887.   echo "<div class=\"freeze_panes\">\n";
  888.   // (a) the "header" columns containing the user names
  889.   // For the header column we just want to use the level and name fields
  890.   $columns = array('level', 'name');
  891.   echo freeze_panes_table_html($info, $columns, 'header_columns', TRUE);
  892.  
  893.   // (b) the "body" columns containing the user info
  894.   // For the body column we want all the other columns, except the id and password
  895.   $columns[] = 'id';
  896.   $columns[] = 'password';
  897.   $all_columns = array();
  898.   foreach ($fields as $field)
  899.   {
  900.     $all_columns[] = $field['name'];
  901.   }
  902.   $columns = array_diff($all_columns, $columns);
  903.   echo freeze_panes_table_html($info, $columns, 'body_columns', FALSE);
  904.   echo "</div>\n";   // freeze_panes
  905.   echo "</div>\n";
  906. }   // ($initial_user_creation != 1)
  907.  
  908. require_once "trailer.inc";
  909.  
  910. ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement