<html>
<! AddUser.php                                                >
<! Chapter 11, Oracle Database XE PHP Web Programming         >
<! by Michael McLaughlin                                      >
<!                                                            >
<! This demonstrates session authentication from a file on    >
<! the server-side of the transaction.                        >
<head>
<title>
  Chapter 11 : AddUser.php
</title>
<style type="text/css">
  div#centered {border:0;height:50%;top:25%;left:25%;width:50%;
                position:absolute;}
</style>
</head>
<body>
<?php
  // Start session.
  session_start();
  $_SESSION['sessionid'] = session_id();

  print $_SESSION['sessionid']."<br>";

  // Verify if new session call.
  if ((!isset($_SESSION['userid'])) || (isset($_POST['userid'])))
  {
    // Suppress errors and delete application maintained file.
    @unlink($_SESSION['sessionid']);

    // Regenerate when a new user is logging in.
    if (isset($_SESSION['userid']))
      if (($_SESSION['userid'] != $_POST['userid']) ||
          ($_SESSION['passwd'] != $_POST['passwd']))
      {
        session_regenerate_id();
        $_SESSION['sessionid'] = session_id();
      }

    // Verify log in account and password.
    if (verify_authentication())
    {
      // Write verified login information to a session file.
      write_session_pairs($_SESSION['sessionid']
                         ,array("userid",$_POST['userid']));
      write_session_pairs($_SESSION['sessionid']
                         ,array("passwd",$_POST['passwd']));

      // Read the current session data from the file.
      read_session_pairs($_SESSION['sessionid']);

      // Display the form.
      addUserForm(array("form"=>"AddUser.php"));
    }
    else
    {
      // Destroy the session and force re-authentication.
      session_destroy();

      // Redirect to the login form.
      signOnForm();
    }
  }
  else // Process current session new user form action.
  {
    // Read the current session data from the file.
    read_session_pairs($_SESSION['sessionid']);

    // Assign inputs to variables.
    $userid = $_POST['newuserid'];
    $passwd = $_POST['newpasswd'];

    // Set message and write new credentials.
    if (($code = verify_valid_credentials($userid,$passwd)) == 0)
    {
      // Join user and encrypted password into a colon delimited string.
      $data = implode(":",array($userid,md5($passwd)));

      // Calll the function to append a line to a file.
      write_string("simplepassword.txt",$data);
    }

    // Display next user form.
    addUserForm(array("code"=>$code
                     ,"form"=>"AddUser.php"
                     ,"userid"=>$userid));
  }

  /* Library functions.
  || ----------------------------------------------------------------
  ||  Function Name               Return Type  Parameters
  || ---------------------------  -----------  ----------------------
  ||  get_message()               string       int      $code
  ||                                           string   $userid
  ||  read_session_pairs()        void         string   $session
  ||  update_session_pair()       void         string   $session
  ||                                           string   $name_in
  ||                                           string   $value_in
  ||  verify_authentication()     bool
  ||  verify_user()               bool         string   $userid
  ||  verify_valid_credentials()  int          string   $userid
  ||                                           string   $passwd
  ||  write_session_pairs()       void         string   $file
  ||                                           array    $pairs
  ||  write_string()              void         resource $file
  ||                                           string   $string
  */

  // ----------------------------------------------------------------

  // Build user message string.
  function get_message($code,$userid)
  {
    // Designate message by error code.
    switch ($code)
    {
      case 0:
        return "You have added user [$userid] successfully.";
      case 1:
        return "User [$userid] is already in use.";
      case 2:
        return "User [$userid] must start with a character.";
      case 3:
        return "User [$userid] must be between 6 and 10 characters.";
      case 4:
        return "The password must be between 6 and 10 characters.";
    }
  }

  // ----------------------------------------------------------------

  // Define function to read and assign $_SESSION variables.
  function read_session_pairs($session)
  {
    // Declare a read file resource.
    if ($fp = @fopen($session,'r'))
    {
      // Read the file into an array of strings.
      $file = file($session);

      // Write session data to environment.
      foreach ($file as $pairs)
      {
        list($name,$value) = explode(":",$pairs);
        $_SESSION[$name] = trim($value);
      }

      // Close the open file handle.
      fclose($fp);
    }
  }

  // ----------------------------------------------------------------

  // Define function to read and update server-side session file.
  function update_session_pair($session,$name_in,$value_in)
  {
    // Read file contents to an array of strings.
    $contents = file($session);

    // Delete the base file.
    if (unlink($session))
    {
      // Read contents.
      foreach ($contents as $pairs)
      {
        // Parse contents to variables.
        list($name,$value) = explode(":",$pairs);

        // Check for matching index value and trim line returns.
        if ($name == $name_in)
          $value = trim($value_in);
        else
          $value = trim($value);

        // Append lines to a new file.
        write_session_pairs($session,array($name,$value));
      }
    }
  }

  // ----------------------------------------------------------------

  // Define a Basic Authentication function.
  function verify_authentication()
  {
    // Check for session variables..
    if ((isset($_SESSION['userid'])) && (isset($_SESSION['passwd'])))
      $session_valid = true;
    else
      $session_valid = false;

    // Check for input variables.
    if ((isset($_POST['userid'])) && (isset($_POST['passwd'])))
      $post_valid = true;
    else
      $post_valid = false;

    // Check that its worth the time to validate.
    if (($session_valid) || ($post_valid))
    {
      // Read the file into an array of strings.
      $passwords = @file("simplepassword.txt");

      // Verify array contains data.
      if (isset($passwords))
      {
        // Read through the value list.
        foreach ($passwords as $credentials)
        {
          // Break the delimited lines into scalar variables.
          list($username,$password) = explode(":",$credentials);

          // Find a match and return valid credentials or invalid ones.
          if (($session_valid) && ($_SESSION['userid'] == $username) &&
              ($_SESSION['passwd'] == $password))
            return true;
          else if (($post_valid) && ($_POST['userid'] == $username) &&
                   (md5($_POST['passwd']) == trim($password)))
            return true;
        }
      }
      // Return a negative validation.
      return false;
    }

    // Return invalid credentials.
    return false;
  }

  // ----------------------------------------------------------------

  // Check for existing user.
  function verify_user($userid)
  {
    // Read the file into an array of strings.
    $passwords = @file("simplepassword.txt");

    // Verify array contains data.
    if (isset($passwords))
    {
      // Read through the value list.
      foreach ($passwords as $credentials)
      {
        // Break the delimited lines into scalar variables.
        list($username,$password) = explode(":",$credentials);

        // Return there is a user.
        if ($userid == $username)
          return true;
      }
    }

    // Return there is no existing user.
    return false;
  }

  // ----------------------------------------------------------------

  // Check user name and password meet rules.
  function verify_valid_credentials($userid,$passwd)
  {
    switch(true)
    {
      // Does user name already exist.
      case (verify_user($userid)):
        return 1;

      // Does user name start with an alphabetic character.
      case (!ereg("([a-zA-Z]+[a-zA-Z0-9]{0,1})",substr($userid,0,1))):
        return 2;

      // Does user name start with a letter for a 6-10 character string.
      case (!ereg("([a-zA-Z]+[a-zA-Z0-9]{5,10})",$userid)):
        return 3;

      // Does password start contain a 6-10 character string.
      case (!ereg("([a-zA-Z0-9]{5,10})",$passwd)):
        return 4;

      // Acknowledge everything is fine.
      default:
        return 0;
    }
  }

  // ----------------------------------------------------------------

  // Define function to write a server-side session file.
  function write_session_pairs($file,$pairs)
  {
    // Break array into colon delimited string.
    $string = implode(":",$pairs);

    // Set control variable.
    $newfile = !is_file($file);

    // Declare an write file resource.
    if ($fp = fopen($file,'a+'))
    {
      // Append a line return after the first line.
      if ($newfile)
        fwrite($fp,$string);
      else
        fwrite($fp,"\n".$string);

      // Close the open file handle.
      fclose($fp);
    }
  }

  // ----------------------------------------------------------------

  // Define function to write a colon delimited file.
  function write_string($file,$string)
  {
    // Declare an write file resource.
    if ($fp = fopen($file,'a+'))
    {
      // Read the two-dimensional array and write or append to a file.
      fwrite($fp,"\n".$string);

      // Close the open file handle.
      fclose($fp);
    }
  }

  // ----------------------------------------------------------------

  // Build dynamic data entry form.
  function addUserForm($args)
  {
    // Define local variables.
    $code;
    $form;
    $userid;

    // Parse form parameters.
    foreach ($args as $name => $value)
    {
      switch (true)
      {
        case ($name == "form"):
          $form = $value;
          break;
        case ($name == "code"):
          $code = $value;
          break;
        case ($name == "userid"):
          $userid = $value;
          break;
      }
    }

    // Initialize return variable.
    $out  = '<div id=centered>';

    // Set and append next form target file.
    $out .= '<form method="post" action="'.$form.'">';

    // Append balance of form header.
    $out .= '<table border="4"
                    bgcolor="beige"
                    bordercolor="silver"
                    cellspacing="0">';
    $out .= '<tr><td align="center" width="400">';
    $out .= '<font size=+3>New User</font>';
    $out .= '</td></tr>';

    // Verify if optional message.
    if ((isset($code)) && (is_int($code)))
    {
      $out .= '<tr><td align="center" bgcolor="white" width="400">';
      $out .= '<font color=blue>'.get_message($code,$userid).'</font>';
      $out .= '</td></tr>';
    }

    // Append standard data entry components.
    $out .= '<tr><td>';
    $out .= '<table border="0" cellpadding="5" cellspacing="0">';
    $out .= '<tr>';
    $out .= '<td align="right" width="200">User ID:</td>';
    $out .= '<td width="200">';
    $out .= '<input name="newuserid" type="text">';
    $out .= '</td>';
    $out .= '</tr>';
    $out .= '<tr>';
    $out .= '<td align="right">User Password:</td>';
    $out .= '<td><input name="newpasswd" type="password"></td>';
    $out .= '</tr>';
    $out .= '<tr>';
    $out .= '</table>';
    $out .= '</td></tr>';
    $out .= '<tr><td align="center" colspan="2">';
    $out .= '<table border="0" cellpadding="5" cellspacing="0">';
    $out .= '<tr>';
    $out .= '<td align="center" valign="center">';
    $out .= '<input name="submit" type="submit" value="Add User">';
    $out .= '</td>';
    $out .= '</tr>';
    $out .= '</table>';
    $out .= '</td></tr>';
    $out .= '</table>';
    $out .= '</form>';
    $out .= '<form method="post" action="SignOn.php">';
    $out .= '<table border="0" cellpadding="5" cellspacing="0">';
    $out .= '<tr>';
    $out .= '<td align="right" valign="center" width="400">';
    $out .= '<input name="submit" type="submit" value="Log Out">';
    $out .= '</td>';
    $out .= '</tr>';
    $out .= '</table>';
    $out .= '</div>';

    // Return the form for rendering in a web page.
    print $out;
  }

  // Build dynamic data entry form.
  function signOnForm()
  {
    // Initialize return variable.
    $out  = '<div id=centered>';

    // Set and append next form target file.
    $out .= '<form method="post" action="AddUser.php">';

    // Append balance of form header.
    $out .= '<table border="4"
                    bgcolor="beige"
                    bordercolor="silver"
                    cellspacing="0">';
    $out .= '<tr><td align="center" width="400">';
    $out .= '<font size=+3>User Login</font>';
    $out .= '</td></tr>';
    $out .= '<tr><td>';
    $out .= '<table border="0" cellpadding="5" cellspacing="0">';
    $out .= '<tr>';
    $out .= '<td align="right" width="200">User ID:</td>';
    $out .= '<td width="200"><input name="userid" type="text"></td>';
    $out .= '</tr>';
    $out .= '<tr>';
    $out .= '<td align="right">User Password:</td>';
    $out .= '<td><input name="passwd" type="password"></td>';
    $out .= '</tr>';
    $out .= '<tr>';
    $out .= '</table>';
    $out .= '</td></tr>';
    $out .= '<tr><td align="center" colspan="2">';
    $out .= '<table border="0" cellpadding="5" cellspacing="0">';
    $out .= '<tr>';
    $out .= '<td align="center" valign="center">';
    $out .= '<input name="submit" type="submit" value="Login">';
    $out .= '</td>';
    $out .= '</tr>';
    $out .= '</table>';
    $out .= '</td></tr>';
    $out .= '</table>';
    $out .= '</form>';
    $out .= '</div>';

    // Return the form for rendering in a web page.
    print $out;
  }
?>
</body>
</html>