PHP вызывая функцию необъекта - PullRequest
2 голосов
/ 21 марта 2011

У меня проблемы с созданием класса сеанса - я пытаюсь передать ему объект базы данных для вызова его функций, однако я продолжаю получать сообщение об ошибке неопределенной функции, как 46 из ssession.class.php, OR, так странно, как этот звук дает мне различную ошибку, которая вызывается для необъекта. Я думал, что вы можете хранить объекты как переменные класса и не понимаю, почему он не находит базу данных.

<?php

include("http://www.walkingspheres.com/include/database.class.php");
include("http://www.walkingspheres.com/include/mailer.php");
include("http://www.walkingspheres.com/include/form.php");

class Session
{
   var $username;     //Username given on sign-up
   var $sessionid;    //Random value generated on current login
   var $userlevel;    //The level to which the user pertains
   var $time;         //Time user was last active (page loaded)
   var $logged_in;    //True if user is logged in, false otherwise
   var $userinfo = array();  //The array holding all user info
   var $url;          //The page url current being viewed
   var $referrer;     //Last recorded site page viewed
   var $database;

   /* Class constructor */
   function Session($db){
      $this->time = time();
      $this->databse = $db;
      $this->startSession();
   }

   /**
    * startSession - Performs all the actions necessary to 
    * initialize this session object. Tries to determine if the
    * the user has logged in already, and sets the variables 
    * accordingly. Also takes advantage of this page load to
    * update the active visitors tables.
    */
   function startSession(){
      session_start();   //Tell PHP to start the session

      /* Determine if user is logged in */
      $this->logged_in = $this->checkLogin();

      /**
       * Set guest value to users not logged in, and update
       * active guests table accordingly.
       */
      if(!$this->logged_in){
         $this->username = $_SESSION['username'] = GUEST_NAME;
         $this->userlevel = GUEST_LEVEL;
         $this->database->addActiveGuest($_SERVER['REMOTE_ADDR'], $this->time);
      }
      /* Update users last active timestam*/
      else{
         $this->database->addActiveUser($this->username, $this->time);
      }

      /* Remove inactive visitors from database */
      $this->database->removeInactiveUsers();
      $this->database->removeInactiveGuests();

      /* Set referrer page */
      if(isset($_SESSION['url'])){
         $this->referrer = $_SESSION['url'];
      }else{
         $this->referrer = "/";
      }

      /* Set current url */
      $this->url = $_SESSION['url'] = $_SERVER['PHP_SELF'];
   }

   /**
    * checkLogin - Checks if the user has already previously
    * logged in, and a session with the user has already been
    * established. Also checks to see if user has been remembered.
    * If so, the database is queried to make sure of the user's 
    * authenticity. Returns true if the user has logged in.
    */
   function checkLogin(){  

            /* Check if user has been remembered */
      if(isset($_COOKIE['cookname']) && isset($_COOKIE['cookid'])){
         $this->username = $_SESSION['username'] = $_COOKIE['cookname'];
         $this->sessionid   = $_SESSION['sessionid']   = $_COOKIE['cookid'];
      }

      /* Username and sessionid have been set and not guest */
      if(isset($_SESSION['username']) && isset($_SESSION['sessionid']) &&
         $_SESSION['username'] != GUEST_NAME){
         /* Confirm that username and sessionid are valid */
         if($this->database->confirmSessionID(
                    $_SESSION['username'],$_SESSION['sessionid'])!= 0)
         {
            /* Variables are incorrect, user not logged in */
            unset($_SESSION['username']);
            unset($_SESSION['sessionid']);
            return false;
         }

         /* User is logged in, set class variables */
         $this->userinfo  = $this->database->getUserInfo($_SESSION['username']);
         $this->username  = $this->userinfo['username'];
         $this->sessionid    = $this->userinfo['sessionid'];
         $this->userlevel = $this->userinfo['userlevel'];
         return true;
      }

      /* User not logged in */
      else{
         return false;
      }
   }

   /**
    * login - The user has submitted his username and password
    * through the login form, this function checks the authenticity
    * of that information in the database and creates the session.
    * Effectively logging in the user if all goes well.
    */
   function login($subuser, $subpass, $subremember){
      $form;  //The database and form object

      /* Username error checking */
      $field = "user";  //Use field name for username
      if(!$subuser || strlen($subuser = trim($subuser)) == 0){
         $form->setError($field, "* Username not entered");
      }
      else{
         /* Check if username is not alphanumeric */
         if(!preg_match("/^([0-9a-z])*$/", $subuser)){
            $form->setError($field, "* Username not alphanumeric");
         }
      }

      /* Password error checking */
      $field = "pass";  //Use field name for password
      if(!$subpass){
         $form->setError($field, "* Password not entered");
      }

      /* Return if form errors exist */
      if($form->num_errors > 0){
         return false;
      }

      /* Checks that username is in database and password is correct */
      $subuser = stripslashes($subuser);
      $result = $this->database->confirmUserPass($subuser, md5($subpass));

      /* Check error codes */
      if($result == 1){
         $field = "user";
         $form->setError($field, "* Username not found");
      }
      else if($result == 2){
         $field = "pass";
         $form->setError($field, "* Invalid password");
      }

      /* Return if form errors exist */
      if($form->num_errors > 0){
         return false;
      }

      /* Username and password correct, register session variables */
      $this->userinfo  = $this->database->getUserInfo($subuser);
      $this->username  = $_SESSION['username'] = $this->userinfo['username'];
      $this->sessionid    = $_SESSION['sessionid']   = $this->generateRandID();
      $this->userlevel = $this->userinfo['userlevel'];

      /* Insert sessionid into database and update active users table */
      $this->database->updateUserField($this->username, "sessionid", $this->sessionid);
      $this->database->addActiveUser($this->username, $this->time);
      $this->database->removeActiveGuest($_SERVER['REMOTE_ADDR']);

      /**
       * This is the cool part: the user has requested that we remember that
       * he/she logged in, so we set two cookies. One to hold his/her username,
       * and one to hold his/her random value sessionid. It expires by the time
       * specified in definitions.php. Now, next time he/she comes to our site, we will
       * log him/her in automatically, but only if she/he didn't log out before they left
      */
      if($subremember){
         setcookie("cookname", $this->username, time()+COOKIE_EXPIRE, COOKIE_PATH);
         setcookie("cookid",   $this->sessionid,   time()+COOKIE_EXPIRE, COOKIE_PATH);
      }

      /* Login completed successfully */
      return true;
   }

   /**
    * logout - Gets called when the user wants to be logged out of the
    * website. It deletes any cookies that were stored on the users
    * computer as a result of him wanting to be remembered, and also
    * unsets session variables and demotes his user level to guest.
    */
   function logout(){
      /**
       * Delete cookies - the time must be in the past,
       * so just negate what you added when creating the
       * cookie.
       */
      if(isset($_COOKIE['cookname']) && isset($_COOKIE['cookid'])){
         setcookie("cookname", "", time()-COOKIE_EXPIRE, COOKIE_PATH);
         setcookie("cookid",   "", time()-COOKIE_EXPIRE, COOKIE_PATH);
      }

      /* Unset PHP session variables */
      unset($_SESSION['username']);
      unset($_SESSION['sessionid']);
      unset($_SESSION['error_array']);
      unset($_SESSION['value_array']);
      unset($_SESSION['regsuccess']);

      /* Reflect fact that user has logged out */
      $this->logged_in = false;

      /**
       * Remove from active users table and add to
       * active guests tables.
       */
      $this->database->removeActiveUser($this->username);
      $this->database->addActiveGuest($_SERVER['REMOTE_ADDR'], $this->time);

      /* Set user level to guest */
      $this->username  = GUEST_NAME;
      $this->userlevel = GUEST_LEVEL;
   }

   /**
    * register - Gets called when the user has just submitted the
    * registration form. Determines if there were any errors with
    * the entry fields, if so, it records the errors and returns
    * 1. If no errors were found, it registers the new user and
    * returns 0. Returns 2 if registration failed.
    */

   function register($subuser,$subpass,$subemail,$c_pass,$c_email,$home,$bday){
      global $form, $mailer;  //The database, form and mailer object

      /* Username error checking */
      $field = "user";  //Use field name for username
      $subuser=trim($subuser);
      if(strlen($subuser) == 0){
         $form->setError($field, "* Username not entered");
      }
      else{
         /* Spruce up username, check length */
         $subuser = stripslashes($subuser);
         if(strlen($subuser) < 5){
            $form->setError($field, "* Username below 5 characters");
         }
         else if(strlen($subuser) > 30){
            $form->setError($field, "* Username above 30 characters");
         }
         /* Check if username is not alphanumeric */
         else if(!preg_match("/^([0-9a-z])+$/", $subuser)){
            $form->setError($field, "* Username not alphanumeric");
         }
         /* Check if username is reserved */
         else if(strcasecmp($subuser, GUEST_NAME) == 0){
            $form->setError($field, "* Username reserved word");
         }
         /* Check if username is already in use */
         else if($this->database->usernameTaken($subuser)){
            $form->setError($field, "* Username already in use");
         }
         /* Check if username is banned */
         else if($this->database->usernameBanned($subuser)){
            $form->setError($field, "* Username banned");
         }
      }

      /* Password error checking */
      $field = "password";  //Use field name for password
      $subpass=trim($subpass);
      $c_pass=trim($c_pass);
      if(strlen($subpass)==0 || strlen($c_pass)==0){
         $form->setError($field, "* Password not entered");
      }
      else{
         /* Spruce up password and check length*/
         if(strlen($subpass) < 4){
            $form->setError($field, "* Password too short");
         }
         /* Check if password is not alphanumeric */
         else if(!preg_match("/^([0-9a-z])+$/", $subpass)){
            $form->setError($field, "* Password not alphanumeric");
         }
         /* Check if both passwords entered match */
         else if(strcmp($subpass,$c_pass) != 0){
            $form->setError($field, "* Passwords don't match");
     }
      }

      /* Email error checking */
      $field = "email";  //Use field name for email
      $subemail=trim($subemail);
      $c_email=trim($c_email);
      if(strlen($subemail) == 0){
         $form->setError($field, "* Email not entered");
      }
      else{
         /* Check if valid email address */
         $regex = "/^[_+a-z0-9-]+(\.[_+a-z0-9-]+)*"
                 ."@[a-z0-9-]+(\.[a-z0-9-]{1,})*"
                 ."\.([a-z]{2,}){1}$/";
         if(!preg_match($regex,$subemail)){
            $form->setError($field, "* Email invalid");
         }
         else if(strcmp($subemail,$c_email)!=0){
           $form->setError($field, "* Emails don't match");
     }
      }

      /* Errors exist, have user correct them */
      if($form->num_errors > 0){
         return 1;
      }
      /* No errors, add the new account to the db */
      else{
        $home=trim($home);
        $bday=trim($bday);
         if($this->database->addNewUser($subuser, md5($subpass),$subemail,$home,$bday)){
            if(EMAIL_WELCOME){
               $mailer->sendWelcome($subuser,$subemail,$subpass);
            }
            return 0;  //New user added succesfully
         }else{
            return 2;  //Registration attempt failed
         }
      }
   }

   /**
    * editAccount - Attempts to edit the user's account information
    * including the password, which it first makes sure is correct
    * if entered, if so and the new password is in the right
    * format, the change is made. All other fields are changed
    * automatically.
    */
   function editAccount($subcurpass, $subnewpass, $subemail){
      global $form;  //The database and form object
      /* New password entered */
      if($subnewpass){
         /* Current Password error checking */
         $field = "curpass";  //Use field name for current password
         if(!$subcurpass){
            $form->setError($field, "* Current Password not entered");
         }
         else{
            /* Check if password too short or is not alphanumeric */
            $subcurpass = stripslashes($subcurpass);
            if(strlen($subcurpass) < 4 ||
               !preg_match("/^([0-9a-z])+$/", ($subcurpass = trim($subcurpass)))){
               $form->setError($field, "* Current Password incorrect");
            }
            /* Password entered is incorrect */
            if($this->database->confirmUserPass($this->username,md5($subcurpass)) != 0){
               $form->setError($field, "* Current Password incorrect");
            }
         }

         /* New Password error checking */
         $field = "newpass";  //Use field name for new password
         /* Spruce up password and check length*/
         $subpass = stripslashes($subnewpass);
         if(strlen($subnewpass) < 4){
            $form->setError($field, "* New Password too short");
         }
         /* Check if password is not alphanumeric */
         else if(!preg_match("/^([0-9a-z])+$/", ($subnewpass = trim($subnewpass)))){
            $form->setError($field, "* New Password not alphanumeric");
         }
      }
      /* Change password attempted */
      else if($subcurpass){
         /* New Password error reporting */
         $field = "newpass";  //Use field name for new password
         $form->setError($field, "* New Password not entered");
      }

      /* Email error checking */
      $field = "email";  //Use field name for email
      if($subemail && strlen($subemail = trim($subemail)) > 0){
         /* Check if valid email address */
         $regex = "/^[_+a-z0-9-]+(\.[_+a-z0-9-]+)*"
                 ."@[a-z0-9-]+(\.[a-z0-9-]{1,})*"
                 ."\.([a-z]{2,}){1}$/";
         if(!preg_match($regex,$subemail)){
            $form->setError($field, "* Email invalid");
         }
         $subemail = stripslashes($subemail);
      }

      /* Errors exist, have user correct them */
      if($form->num_errors > 0){
         return false;  //Errors with form
      }

      /* Update password since there were no errors */
      if($subcurpass && $subnewpass){
         $this->database->updateUserField($this->username,"password",md5($subnewpass));
      }

      /* Change Email */
      if($subemail){
         $this->database->updateUserField($this->username,"email",$subemail);
      }

      /* Success! */
      return true;
   }

   /**
    * isAdmin - Returns true if currently logged in user is
    * an administrator, false otherwise.
    */
   function isAdmin(){
      return ($this->userlevel == ADMIN_LEVEL ||
              $this->username  == ADMIN_NAME);
   }

   /**
     * confirmFriends - pre: sessionid, requestingid
     * returns true if they are both friends
     * else returns false
     */
   function confirmFriends($uid,$rid){
     $q = "SELECT name FROM friends WHERE userid_fk='$uid' AND fid='$rid' ";
     $res->$this->database->query($q);
     if($res){  //exists
       return true;
     }
     else
       return false;
   } 

   /**
    * generateRandID - Generates a string made up of randomized
    * letters (lower and upper case) and digits and returns
    * the md5 hash of it to be used as a sessionid.
    */
   function generateRandID(){
      return md5($this->generateRandStr(16));
   }

   /**
    * generateRandStr - Generates a string made up of randomized
    * letters (lower and upper case) and digits, the length
    * is a specified parameter.
    */
   function generateRandStr($length){
      $randstr = "";
      for($i=0; $i<$length; $i++){
         $randnum = mt_rand(0,61);
         if($randnum < 10){
            $randstr .= chr($randnum+48);
         }else if($randnum < 36){
            $randstr .= chr($randnum+55);
         }else{
            $randstr .= chr($randnum+61);
         }
      }
      return $randstr;
   }
}

/**
 * Initialize session object - This must be initialized before
 * the form object because the form uses session variables,
 * which cannot be accessed unless the session has started.
 */

$session = new Session($database);

/* Initialize form object */
$form = new Form();
?>

Моя другая проблема, и ниже вы увидите класс базы данных, но у меня есть session_start (); наверху всех моих страниц и по какой-то причине смесь между базой данных и сессией отказывается фактически регистрировать или входить в систему кого-либо. Может быть, кто-то может определить причину?

<?php

require_once("http://www.walkingspheres.com/definitions.php");

class MySQLDB
{
   var $connection;         //The MySQL database connection
   var $num_active_users;   //Number of active users viewing site
   var $num_active_guests;  //Number of active guests viewing site
   var $num_members;        //Number of signed-up users
   /* Note: call getNumMembers() to access $num_members! */

   /* Class constructor */
   function MySQLDB(){
      /* Make connection to database */
      $this->connection = mysql_connect("localhost","name","pass") or die(mysql_error());
      mysql_select_db("pen15_users", $this->connection) or die(mysql_error());

      /**
       * Only query database to find out number of members
       * when getNumMembers() is called for the first time,
       * until then, default value set.
       */
      $this->num_members = -1;

      if(TRACK_VISITORS){
         /* Calculate number of users at site */
         $this->calcNumActiveUsers();

         /* Calculate number of guests at site */
         $this->calcNumActiveGuests();
      }
   }

   /**
    * confirmUserPass - Checks whether or not the given
    * username is in the database, if so it checks if the
    * given password is the same password in the database
    * for that user. If the user doesn't exist or if the
    * passwords don't match up, it returns an error code
    * (1 or 2). On success it returns 0.
    */
   function confirmUserPass($username, $password){
      /* Verify that user is in database */
      $q = "SELECT password FROM members WHERE username = '$username'";
      $result = mysql_query($q, $this->connection);
      if(!$result || (mysql_numrows($result) < 1)){
         return 1; //Indicates username failure
      }

      /* Retrieve password from result, strip slashes */
      $dbarray = mysql_fetch_array($result);
      $dbarray['password'] = stripslashes($dbarray['password']);
      $password = stripslashes($password);

      /* Validate that password is correct */
      if($password == $dbarray['password']){
         return 0; //Success! Username and password confirmed
      }
      else{
         return 2; //Indicates password failure
      }
   }

   /**
    * confirmSessionID - Checks whether or not the given
    * username is in the database, if so it checks if the
    * given userid is the same userid in the database
    * for that user. If the user doesn't exist or if the
    * userids don't match up, it returns an error code
    * (1 or 2). On success it returns 0.
    */
  public function confirmSessionId($username, $sessionid){
      /* Add slashes if necessary (for query) */
      if(!get_magic_quotes_gpc()) {
          $username = addslashes($username);
      }

      /* Verify that user is in database */
      $q = "SELECT sessionid FROM members WHERE username = '$username'";
      $result = mysql_query($q, $this->connection);
      if(!$result || (mysql_numrows($result) < 1)){
         return 1; //Indicates username failure
      }

      /* Retrieve id from result, strip slashes */
      $dbarray = mysql_fetch_array($result);

      /* Validate that sessionid is correct */
      if($sessionid == $dbarray['sessionid']){
         return 0; //Success! Username and session confirmed
      }
      else{
         return 2; //Indicates userid invalid
      }
   }

   /**
    * usernameTaken - Returns true if the username has
    * been taken by another user, false otherwise.
    */
   function usernameTaken($username){
      $q = "SELECT username FROM members WHERE username = '$username'";
      $result = mysql_query($q, $this->connection);
      return (mysql_numrows($result) > 0);
   }

   /**
    * usernameBanned - Returns true if the username has
    * been banned by the administrator.
    */
   function usernameBanned($username){
      if(!get_magic_quotes_gpc()){
         $username = addslashes($username);
      }
      $q = "SELECT username FROM banned_users WHERE username = '$username'";
      $result = mysql_query($q, $this->connection);
      return (mysql_numrows($result) > 0);
   }

   /**
    * addNewUser - Inserts the given (username, password, email)
    * info into the database. Appropriate user level is set.
    * Returns true on success, false otherwise.
    */
   function addNewUser($username,$password,$email,$home,$bday){
      $time = time();
      /* If admin sign up, give admin user level */
      if(strcasecmp($username, 'pen15') == 0 ||
         strcasecmp($username, 'Charlie DeHart')==0 ){
         $ulevel = 9;
      }else{
         $ulevel = 1;
      }
      $home=trim($home);
      $bday=trim($day);
      if($home='' || $home=NULL)
        $home = 'default';

      if($bday='' || $bday=NULL)
        $bday = 'default';

      $sessionid = '1'; 

      $q = "INSERT INTO members(username, password,";
            "email, userlevel, timestamp, home, birthday, sessionid) ";
            "VALUES ('$username','$password','$email','$ulevel','$time',";
            "'$home','$bday','$sessionid')";

      return mysql_query($q, $this->connection);
   }

   /**
    * updateUserField - Updates a field, specified by the field
    * parameter, in the user's row of the database.
    */
   function updateUserField($username, $field, $value){
    $q = "UPDATE members SET ".$field." = '$value' WHERE username = '$username'";
      return mysql_query($q, $this->connection);
   }

   /**
    * getUserInfo - Returns the result array from a mysql
    * query asking for all information stored regarding
    * the given username. If query fails, NULL is returned.
    */
   function getUserInfo($username){
      $q = "SELECT * FROM members WHERE username = '$username'";
      $result = mysql_query($q, $this->connection);
      /* Error occurred, return given name by default */
      if(!$result || (mysql_numrows($result) < 1)){
         return NULL;
      }
      /* Return result array */
      $dbarray = mysql_fetch_array($result);
      return $dbarray;
   }

}

/* Create database connection */
$database = new MySQLDB;

?>

Большое спасибо за любые комментарии, помощь или объяснение того, что включение файла, создающего новый класс внизу, вызовет конструктор.

Ответы [ 3 ]

1 голос
/ 22 марта 2011
  $this->databse = $db;

Это должна быть $ this-> база данных

Должен ненавидеть опечатки, а? Так как присвоение свойства объекта выполняется неправильно, $ this-> database имеет значение null, и, следовательно, функция (в данном случае это скорее метод), которую вы пытаетесь вызвать, не определена.

На другой ноте (поскольку вышеприведенный комментарий должен исправить вашу текущую проблему): вы подвергаете себя смерти.

function confirmUserPass($username, $password){
  /* Verify that user is in database */
  $q = "SELECT password FROM members WHERE username = '$username'";
  $result = mysql_query($q, $this->connection);

Что если я сделаю $ username чем-то, что делает какой-то SQL, который вы не хотите? Это не будет сложно. Пожалуйста, используйте mysql_escape_string (да, я могу ошибаться в отношении точного названия функции, я всегда работаю с PDO в настоящее время) или измените ваш код на подготовленные операторы. В противном случае вы будете страдать от внедрения SQL (http://en.wikipedia.org/wiki/SQL_injection)

Сделайте то же самое для КАЖДОГО отдельного ввода данных в БД, который был первоначально предоставлен пользователем (и часто даже если он был косвенно представлен пользователем)

1 голос
/ 22 марта 2011
include("http://www.walkingspheres.com/include/database.class.php");
include("http://www.walkingspheres.com/include/mailer.php");
include("http://www.walkingspheres.com/include/form.php");

Хлоп!

Ух ты, allow_url_fopen включен? Похоже на это. Это или у вас уровень сообщений об ошибках перевернут далеко вниз. Если эти строки кода работают, , тогда ваш код использует неправильную настройку PHP, которая может быть огромной дырой в безопасности .

include выполняет код . Вы include -ing-URL. Это означает, что PHP делает веб-запросы для загрузки этих файлов. Если бы кто-то смог обмануть ваш код для выполнения произвольного include, он мог бы выполнить свой код на вашем сервере, и вы бы никогда не узнали.

Это PHP-скрипты. Весьма вероятно, что они выполняются при выполнении запроса вместо возврата исходного кода и вместо этого ничего не возвращают. Это или PHP правильно настроен, но ваш уровень сообщений об ошибках скрывает проблему.

Измените все эти include, include_once, require и require_once для использования путей в файловой системе вместо URL-адресов.

Также увеличьте уровень сообщений об ошибках во время разработки, используя следующие две строки кода:

ini_set('display_errors', true);
error_reporting(-1);

Я готов поспорить, что включение отчетов об ошибках заставит PHP скулить невероятно громко о проблемах, которые у вас возникают, от проблем сериализации до опечатки базы данных.

Кроме того, не могли бы вы сказать нам, где вы взяли этот "сеанс" класс? Он действительно очень старый, и у людей постоянно возникают проблемы. Он плохо спроектирован и, вероятно, не должен использоваться в современную эпоху. Мне бы очень хотелось знать, откуда он взялся, чтобы я мог иметь автора - * гм * - переучиться и / или иметь центр обработки данных, размещающий его на орбите.

0 голосов
/ 21 марта 2011

(Ваш код довольно длинный, и я не пытался все это понять - но я видел одну вещь, которая кажется странной)


У вашего MySQLDB класса есть свойство $connection, представляющее собой resource - полученное как возвращаемое значение mysql_connect() функция.


Ресурсы не могут быть сериализованы - см. Справочную страницу serialize() для справки (цитирование) :

serialize() обрабатывает все типы, , кроме тип ресурса .


Я предполагаю, что свойство $database вашего Session класса указывает на экземпляр вашего MYSQLDB класса - который содержит ресурс.

Этот ресурс нельзя сериализовать, поэтому он не может быть сохранен в $_SESSION; или, более конкретно, его нельзя восстановить из сеанса.


Чтобы решить эту конкретную проблему, вам следует повторно подключиться к базе данных при загрузке сеанса - здесь могут помочь магические методы __sleep() и __wakeup(), здесь.

...