32 | get_msg(); ?> 33 | -------------------------------------------------------------------------------- /lib/config.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright 2011-2012 Monji Dolon 11 | * @license http://www.gnu.org/licenses/gpl.html GNU General Public License (GPL) v3 12 | * @link http://devgrow.com/jquery-mobile-php-mvc-framework/ 13 | */ 14 | 15 | // Define global Variables. 16 | define("APP_NAME", "jQuery Mobile MVC Framework"); 17 | define("APP_DESCRIPTION", "A simple PHP MVC framework utilizing jQuery Mobile"); 18 | define("APP_KEYWORDS", "jquery mobile, jquery mobile mvc, jquery mobile php, jquery mobile framework"); 19 | define("PASSWORD_SALT", "justjquerying"); 20 | define("CACHE_ENABLE", true); 21 | define("BASE_DIR", dirname(dirname(__FILE__))); 22 | define("LIB_DIR", dirname(__FILE__)); 23 | define("COOKIE_DOMAIN", ""); 24 | 25 | //If site disposed not in root path 26 | define("BASE_URL", ''); 27 | 28 | // Set the default controller hte user is directed to (aka homepage). 29 | define('ROUTER_DEFAULT_CONTROLLER', 'site'); 30 | define('ROUTER_DEFAULT_ACTION', 'home'); 31 | 32 | // The following controllers/actions will not be cached: 33 | $do_not_cache = array("user",""); 34 | 35 | // Load helper functions and the model classes. 36 | require_once(LIB_DIR."/helpers.php"); 37 | require_once(LIB_DIR."/models/cache.php"); 38 | require_once(LIB_DIR."/models/user.php"); 39 | require_once(LIB_DIR."/models/template.php"); 40 | -------------------------------------------------------------------------------- /lib/helpers.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright 2011-2012 Monji Dolon 11 | * @license http://www.gnu.org/licenses/gpl.html GNU General Public License (GPL) v3 12 | * @link http://devgrow.com/jquery-mobile-php-mvc-framework/ 13 | */ 14 | 15 | /** 16 | * Load the controller file automatically if it is referenced in a function. 17 | * 18 | * @param $name The name of the controller. 19 | */ 20 | function __autoload($name){ 21 | require_once LIB_DIR.'/controllers/'.strtolower($name).'.php'; 22 | } 23 | 24 | /** 25 | * Redirect the user to any page on the site. 26 | * 27 | * @param $location URL of where you want to return the user to. 28 | */ 29 | function return_to($location){ 30 | $location = '/'.$location; 31 | header("Location: $location"); 32 | exit(); 33 | } 34 | 35 | /** 36 | * Check to see if user is logged in and if not, redirect them to the login page. 37 | * If they're logged in, let them proceed. 38 | */ 39 | function login_required(){ 40 | global $user, $template; 41 | if(!$user->is_logged){ 42 | $template->set_msg("You must be logged in to access this section.",false); 43 | User::login(); 44 | exit(); 45 | } 46 | } 47 | 48 | /** 49 | * This function prints variables in the template, after setting them with the 50 | * $template->set_variable() function. Possible to extend this to support multiple 51 | * languages, as well as optionally returning a value (instead of echoing). 52 | * 53 | * @param $id The name of the variable, prints the value passed from controller. 54 | */ 55 | function __($id) { 56 | global $template; 57 | 58 | echo $template->variables[$id]; 59 | } 60 | 61 | ?> -------------------------------------------------------------------------------- /lib/controllers/user.php: -------------------------------------------------------------------------------- 1 | 11 | * @copyright 2011-2012 Monji Dolon 12 | * @license http://www.gnu.org/licenses/gpl.html GNU General Public License (GPL) v3 13 | * @link http://devgrow.com/jquery-mobile-php-mvc-framework/ 14 | */ 15 | 16 | class User { 17 | 18 | /** 19 | * Default user profile page. 20 | */ 21 | function index(){ 22 | global $template, $user; 23 | login_required(); 24 | 25 | $template->assign('user_name', $user->name); 26 | $template->assign('user_email', $user->email); 27 | $template->set_title('My Profile'); 28 | $template->render("user","profile",true); 29 | } 30 | 31 | /** 32 | * Login page. 33 | * 34 | * Sends the user to the homepage if they're already logged in. If they try to 35 | * login, validates their info and redirects them to homepage. 36 | */ 37 | function login(){ 38 | global $user, $template; 39 | if($user->is_logged) 40 | return_to('site/home'); 41 | else{ 42 | if($_POST['task'] == 'login'){ 43 | $user->login($_POST['email'],$_POST['password']); 44 | $template->set_msg($user->msg, $user->ok); 45 | if($user->ok && $_POST['return_to']){ 46 | return_to($_POST['return_to']); 47 | }elseif($user->ok) 48 | return_to('site/home'); 49 | } 50 | } 51 | $template->set_title('Login'); 52 | $template->render("user","login",true); 53 | } 54 | 55 | /** 56 | * Logout page. 57 | * 58 | * Simply logs the user out if they're logged in, then renders the login page. 59 | */ 60 | function logout(){ 61 | global $user, $template; 62 | if($user->is_logged()){ 63 | $user->logout(); 64 | $template->set_msg($user->msg, $user->ok); 65 | } 66 | return_to('user/login'); 67 | } 68 | 69 | /** 70 | * Edit profile page. 71 | */ 72 | function edit(){ 73 | global $user, $template; 74 | login_required(); 75 | if($_POST){ 76 | if($user->update($_POST)) $template->set_msg($user->msg, $user->ok); 77 | $template->set_msg($user->msg, $user->ok); 78 | } 79 | $template->assign('user_email',$user->email); 80 | $template->assign('user_name',$user->name); 81 | $template->set_title('Update Information'); 82 | $template->render("user","edit",true); 83 | } 84 | 85 | /** 86 | * User registration page. 87 | */ 88 | function register(){ 89 | global $user, $template; 90 | if($_POST){ 91 | if($user->create($_POST)){ 92 | $template->set_msg($user->msg, $user->ok); 93 | if($_POST['return_to']) 94 | return_to($_POST['return_to']); 95 | else 96 | return_to("site/home"); 97 | } 98 | $template->set_msg($user->msg, $user->ok); 99 | $template->assign('email',$_POST['email']); 100 | $template->assign('name',$_POST['name']); 101 | } 102 | $template->set_title('Register'); 103 | $template->render("user","register",true); 104 | } 105 | 106 | } -------------------------------------------------------------------------------- /lib/models/cache.php: -------------------------------------------------------------------------------- 1 | 15 | * @copyright 2011-2012 Monji Dolon 16 | * @license http://www.gnu.org/licenses/gpl.html GNU General Public License (GPL) v3 17 | * @link http://devgrow.com/jquery-mobile-php-mvc-framework/ 18 | */ 19 | 20 | class CacheModel { 21 | 22 | var $cacheDir = "./cache"; 23 | var $cacheTime = 21600; // 6 hours = 6*60*60 24 | var $caching = false; 25 | var $cacheFile; 26 | var $cacheFileName; 27 | 28 | /** 29 | * Create an md5 hash of the currently requested URL, set the filename based on the hash. 30 | */ 31 | function __construct(){ 32 | // Hash the requested URI. 33 | $this->cacheFile = md5($_SERVER['REQUEST_URI']); 34 | 35 | // Set the filename using the hash. 36 | $this->cacheFileName = $this->cacheDir.'/'.$this->cacheFile.'.cache'; 37 | 38 | // If the cache directory doesn't exist, create it and set correct permissions. 39 | if(!is_dir($this->cacheDir)) { 40 | mkdir($this->cacheDir, 0755); 41 | } 42 | } 43 | 44 | /** 45 | * Starts the cache object; must call this function at the beginning of the content/page 46 | * you are trying to cache, then call the end function at the (duh) end of it. 47 | */ 48 | function start(){ 49 | global $do_not_cache; 50 | 51 | // Get the current URI and identify the current request. 52 | $location = explode('/',$_SERVER['REQUEST_URI']); 53 | 54 | // If this page isn't in the "Do not cache" list, and caching is enabled, either 55 | // start the cache process if the previous cache is older than cacheTime or doesn't exist, 56 | // or else just render the existing cache file. 57 | if(!in_array($location[0],$do_not_cache) && CACHE_ENABLE){ 58 | if(file_exists($this->cacheFileName) && (time() - filemtime($this->cacheFileName)) < $this->cacheTime){ 59 | $this->caching = false; 60 | echo file_get_contents($this->cacheFileName); 61 | exit(); 62 | }else{ 63 | $this->caching = true; 64 | ob_start(); 65 | } 66 | } 67 | } 68 | 69 | /** 70 | * Starts the cache object; must call this function at the beginning of the content/page 71 | * you are trying to cache, then call the end function at the (duh) end of it. 72 | */ 73 | function end(){ 74 | if($this->caching){ 75 | file_put_contents($this->cacheFileName,ob_get_contents()); 76 | ob_end_flush(); 77 | } 78 | } 79 | 80 | /** 81 | * This function deletes the cache file for the current URI. 82 | */ 83 | function purge(){ 84 | if(file_exists($this->cacheFile) && is_writable($this->cacheDir)) unlink($this->cacheFile); 85 | } 86 | 87 | /** 88 | * This function deletes all of the cache files in the cache directory. 89 | */ 90 | function purge_all(){ 91 | if(!$dirhandle = @opendir($this->cacheDir)) return; 92 | while(false != ($filename = readdir($dirhandle))){ 93 | if(substr($filename,-4) == '.cache') { 94 | $filename = $this->cacheDir. "/". $filename; 95 | unlink($filename); 96 | } 97 | } 98 | } 99 | } 100 | ?> -------------------------------------------------------------------------------- /lib/controllers/router.php: -------------------------------------------------------------------------------- 1 | 12 | * @copyright 2011-2012 Monji Dolon 13 | * @license http://www.gnu.org/licenses/gpl.html GNU General Public License (GPL) v3 14 | * @link http://devgrow.com/jquery-mobile-php-mvc-framework/ 15 | */ 16 | 17 | class Router { 18 | public $request_uri; 19 | public $routes; 20 | public $controller, $controller_name; 21 | public $action, $id; 22 | public $params; 23 | public $route_found = false; 24 | 25 | public function __construct() { 26 | $request = $_SERVER['REQUEST_URI']; 27 | $pos = strpos($request, '?'); 28 | if ($pos) $request = substr($request, 0, $pos); 29 | 30 | //In accordance with the BASE_URL 31 | if (BASE_URL) { 32 | $urllen = strlen($request)-strlen(BASE_URL); 33 | $request = substr($request, -$urllen, $urllen); 34 | } 35 | 36 | $this->request_uri = $request; 37 | $this->routes = array(); 38 | } 39 | 40 | public function map($rule, $target=array(), $conditions=array()) { 41 | $this->routes[$rule] = new Route($rule, $this->request_uri, $target, $conditions); 42 | } 43 | 44 | public function default_routes() { 45 | $this->map('/:controller'); 46 | $this->map('/:controller/:action'); 47 | $this->map('/:controller/:action/:id'); 48 | } 49 | 50 | private function set_route($route) { 51 | $this->route_found = true; 52 | $params = $route->params; 53 | $this->controller = $params['controller']; unset($params['controller']); 54 | $this->action = $params['action']; unset($params['action']); 55 | $this->id = $params['id']; 56 | $this->params = array_merge($params, $_GET); 57 | 58 | if (empty($this->controller)) $this->controller = ROUTER_DEFAULT_CONTROLLER; 59 | if (empty($this->action)) $this->action = ROUTER_DEFAULT_ACTION; 60 | if (empty($this->id)) $this->id = null; 61 | 62 | $w = explode('_', $this->controller); 63 | foreach($w as $k => $v) $w[$k] = ucfirst($v); 64 | $this->controller_name = implode('', $w); 65 | } 66 | 67 | public function execute() { 68 | foreach($this->routes as $route) { 69 | if ($route->is_matched) { 70 | $this->set_route($route); 71 | break; 72 | } 73 | } 74 | } 75 | } 76 | 77 | class Route { 78 | public $is_matched = false; 79 | public $params; 80 | public $url; 81 | private $conditions; 82 | 83 | function __construct($url, $request_uri, $target, $conditions) { 84 | $this->url = $url; 85 | $this->params = array(); 86 | $this->conditions = $conditions; 87 | $p_names = array(); $p_values = array(); 88 | 89 | preg_match_all('@:([\w]+)@', $url, $p_names, PREG_PATTERN_ORDER); 90 | $p_names = $p_names[0]; 91 | 92 | $url_regex = preg_replace_callback('@:[\w]+@', array($this, 'regex_url'), $url); 93 | $url_regex .= '/?'; 94 | 95 | if (preg_match('@^' . $url_regex . '$@', $request_uri, $p_values)) { 96 | array_shift($p_values); 97 | foreach($p_names as $index => $value) $this->params[substr($value,1)] = urldecode($p_values[$index]); 98 | foreach($target as $key => $value) $this->params[$key] = $value; 99 | $this->is_matched = true; 100 | } 101 | 102 | unset($p_names); unset($p_values); 103 | } 104 | 105 | function regex_url($matches) { 106 | $key = str_replace(':', '', $matches[0]); 107 | if (array_key_exists($key, $this->conditions)) { 108 | return '('.$this->conditions[$key].')'; 109 | } 110 | else { 111 | return '([a-zA-Z0-9_\+\-%]+)'; 112 | } 113 | } 114 | } 115 | 116 | ?> 117 | -------------------------------------------------------------------------------- /lib/controllers/app.php: -------------------------------------------------------------------------------- 1 | 12 | * @copyright 2011-2012 Monji Dolon 13 | * @license http://www.gnu.org/licenses/gpl.html GNU General Public License (GPL) v3 14 | * @link http://devgrow.com/jquery-mobile-php-mvc-framework/ 15 | */ 16 | 17 | class App { 18 | 19 | /** 20 | * Main constructor function, used to initialize the models, connect to the DB and 21 | * route the user to where they need to go. 22 | */ 23 | function __construct(){ 24 | global $template, $user, $db; 25 | 26 | // Start the user session, used for storing cookies. 27 | session_start(); 28 | 29 | // Connect to the database. 30 | try { 31 | // If your application uses MySQL, use the following line instead: 32 | // $db = new PDO("mssql:host=$host;dbname=$dbname, $user, $pass"); 33 | $db = new PDO('sqlite:' . BASE_DIR . '/db/sqlite.db'); 34 | } catch (Exception $e) { 35 | die($e); 36 | } 37 | 38 | // Check to see if the 'user' table exists and if not, create it. 39 | $this->check_db(); 40 | 41 | // Create new Template and User models. 42 | $template = new TemplateModel; 43 | $user = new UserModel; 44 | 45 | // Figure out which controller the user is requesting and perform the 46 | // correct actions. 47 | $this->router(); 48 | } 49 | 50 | /** 51 | * Figure out where the user is trying to get to and route them to the 52 | * appropriate controller/action. 53 | */ 54 | function router() { 55 | 56 | // Create a new Router instance. 57 | $r = new Router(); 58 | 59 | // Configure the routes, where the user should go when they access the 60 | // specified URL structures. Default controller and action is set in the 61 | // config.php file. 62 | $r->map('/', array('controller' => ROUTER_DEFAULT_CONTROLLER, 'action' => ROUTER_DEFAULT_ACTION)); 63 | $r->map('/user', array('controller' => 'user', 'action' => 'index')); 64 | $r->map('/login', array('controller' => 'user', 'action' => 'login')); 65 | $r->map('/logout', array('controller' => 'user', 'action' => 'logout')); 66 | $r->map('/signup', array('controller' => 'user', 'action' => 'register')); 67 | $r->map('/users/:id', array('controller' => 'users'), array('id' => '[\d]{1,8}')); 68 | 69 | // Load instructions for basic routing and send the user on their way! 70 | $r->default_routes(); 71 | $r->execute(); 72 | 73 | // Extracting info about where the user is headed, in order to match the 74 | // URL with the correct controllers/actions. 75 | $controller = $r->controller; 76 | $model = $r->controller_name; 77 | $action = $r->action; 78 | $id = $r->id; 79 | $params = $r->params; // Returns an array(...) 80 | $matched = $r->route_found; // Bool, where True is if a route was found. 81 | 82 | if($matched){ 83 | // If going to a site page, treat it in special manner, otherwise load 84 | // the appropriate controller/action and pass in the variables and 85 | // parameters specified by the URL. 86 | if($controller == "site"){ 87 | $site = new Site; 88 | $site->load_page($action); 89 | }elseif(file_exists(LIB_DIR.'/controllers/'.$controller.'.php')){ 90 | $$controller = new $model; 91 | if(method_exists($$controller,$action)) $$controller->$action($id, $params[0], $params[1]); 92 | else Site::load_page('error'); 93 | }else Site::load_page('error'); 94 | }else Site::load_page('home'); 95 | } 96 | 97 | /** 98 | * Check to see if the proper tables exist in the database and if not, 99 | * create them. 100 | */ 101 | function check_db() { 102 | global $db; 103 | 104 | $sql = 'CREATE TABLE IF NOT EXISTS users ( 105 | id INTEGER PRIMARY KEY, 106 | name TEXT, 107 | email TEXT, 108 | password TEXT, 109 | create_ip TEXT, 110 | create_date TEXT, 111 | status INTEGER 112 | )'; 113 | $query = $db->prepare($sql); 114 | $query->execute(); 115 | } 116 | } 117 | ?> -------------------------------------------------------------------------------- /lib/models/template.php: -------------------------------------------------------------------------------- 1 | 11 | * @copyright 2011-2012 Monji Dolon 12 | * @license http://www.gnu.org/licenses/gpl.html GNU General Public License (GPL) v3 13 | * @link http://devgrow.com/jquery-mobile-php-mvc-framework/ 14 | */ 15 | 16 | class TemplateModel { 17 | 18 | var $variables = array(); 19 | var $title; 20 | var $msg; 21 | var $msg_type; 22 | 23 | /** 24 | * Simple function used to load template views. If only a view/model is specified, 25 | * load only the file from the base template directory. If an action is specified, 26 | * the file/model name is expected to also be the name of the folder in which the 27 | * actual view file is being held. 28 | * 29 | * @param $file The name of the view/model file 30 | * @param $action When specified, name of the file ($file used as dir name). 31 | * This param is optional. 32 | */ 33 | function load($file, $action = null){ 34 | global $template, $user; 35 | 36 | // If an action is specified, include the specific action. 37 | $file = LIB_DIR . "/views/" . $file; 38 | if($action) { 39 | $file .= '/'.$action; 40 | } 41 | $file .= ".php"; 42 | 43 | // Load the view file only if it exists. 44 | if(file_exists($file)) { 45 | include_once $file; 46 | } 47 | } 48 | 49 | /** 50 | * Renders default template views, based on the model and action supplied (including 51 | * header and footer views). 52 | * 53 | * @param $model The name of the model file 54 | * @param $action When specified, name of the file ($file used as dir name) 55 | * @param $html When specified, name of the file ($file used as dir name) 56 | * @param $caching_enabled (optional): When specified, name of the file ($file used as dir name) 57 | */ 58 | function render($model, $action = null, $html = false, $caching_enabled = true){ 59 | 60 | $this->load("header"); 61 | 62 | // Start caching everything rendered. We start this after the 63 | // header, since the header may contain user session information 64 | // that shouldn't be cached. 65 | if($caching_enabled) { 66 | $cache = new CacheModel; 67 | $cache->start(); 68 | } 69 | 70 | // Add a container DIV to the view HTML about to be inclued. 71 | if($html) { 72 | echo '
'; 73 | } 74 | 75 | // Load this specific view 76 | $this->load($model, $action); 77 | 78 | // Close the container DIV. 79 | if($html) echo '
'; 80 | 81 | $this->load("footer"); 82 | 83 | // Stop caching. 84 | if($caching_enabled) { 85 | $cache->end(); 86 | } 87 | 88 | } 89 | 90 | /** 91 | * Used to assign variables that can be used in the template files. 92 | * 93 | * @param $name Name of the variable to be assigned 94 | * @param $value String or Array object 95 | */ 96 | function assign($name, $value){ 97 | $this->variables[$name] = $value; 98 | } 99 | 100 | /** 101 | * Used to assign the page title of the rendered HTML file. 102 | * 103 | * @param $title Title of the rendered HTML file () 104 | */ 105 | function set_title($title){ 106 | $this->title = $title; 107 | } 108 | 109 | /** 110 | * This function prints the page title that has been set in the controller, 111 | * should only be used in the header view. 112 | */ 113 | function page_title(){ 114 | if($this->title) $str = $this->title.' - '.APP_NAME.'.com'; 115 | else $str = APP_NAME.'.com - '.APP_KEYWORDS; 116 | echo $str; 117 | } 118 | 119 | /** 120 | * Set any status or error messages to be passed into the view files. 121 | * 122 | * @param $the_msg The message to be displayed in the status box. 123 | * @param $type Type of message, either 'success' or 'error' - 124 | * passed into the DIV object as a class (used for styling). 125 | */ 126 | function set_msg($the_msg, $type = null){ 127 | $this->msg = $the_msg; 128 | $this->msg_type = $type; 129 | } 130 | 131 | /** 132 | * Displays the status or error message in the template. 133 | */ 134 | function get_msg(){ 135 | if($this->msg_type) { 136 | $style = "success"; 137 | } else { 138 | $style = "error"; 139 | } 140 | if($this->msg) { 141 | echo "
".$this->msg."
\n"; 142 | } 143 | } 144 | 145 | } 146 | ?> -------------------------------------------------------------------------------- /lib/models/user.php: -------------------------------------------------------------------------------- 1 | 11 | * @copyright 2011-2012 Monji Dolon 12 | * @license http://www.gnu.org/licenses/gpl.html GNU General Public License (GPL) v3 13 | * @link http://devgrow.com/jquery-mobile-php-mvc-framework/ 14 | */ 15 | 16 | class UserModel { 17 | 18 | var $user_id; 19 | var $name; 20 | var $email; 21 | var $password; 22 | var $ok; 23 | var $msg; 24 | var $is_logged; 25 | 26 | /** 27 | * Set all internal variables to 'Guest' status, then check to see if 28 | * a user session or cookie exists. 29 | */ 30 | function __construct(){ 31 | global $db; 32 | 33 | $this->user_id = 0; 34 | $this->email = "Guest"; 35 | $this->name = "Guest"; 36 | $this->ok = false; 37 | 38 | if(!$this->check_session()) $this->check_cookie(); 39 | 40 | return $this->ok; 41 | } 42 | 43 | /** 44 | * This function checks to see whether or not a PHP Session is set. 45 | */ 46 | function check_session(){ 47 | if(!empty($_SESSION['auth_email']) && !empty($_SESSION['auth_secret'])) 48 | return $this->check($_SESSION['auth_email'], $_SESSION['auth_secret']); 49 | else 50 | return false; 51 | } 52 | 53 | 54 | /** 55 | * Check to see if any cookies exist on the user's computer/browser. 56 | */ 57 | function check_cookie(){ 58 | if(!empty($_COOKIE['auth_email']) && !empty($_COOKIE['auth_secret'])) 59 | return $this->check($_COOKIE['auth_email'], $_COOKIE['auth_secret']); 60 | else 61 | return false; 62 | } 63 | 64 | /** 65 | * Create a user and by default, log them in once the account has been created. 66 | * 67 | * @param $info An array that contains the following info about the user: 68 | * - name, email, password, password2 (password repeated), status (optional) 69 | * @param $login Bool, whether or not to log the user in after creating account. 70 | */ 71 | function create($info,$login = true){ 72 | global $db; 73 | 74 | // Hash the password using the salt specified in config.php 75 | $password = md5($info['password'] . PASSWORD_SALT); 76 | 77 | // If user status isn't set, assume default status (1) 78 | $status = $info['status'] ? $info['status'] : 1; 79 | 80 | // Store the IP address that the user create's the account with. 81 | $create_ip = $_SERVER['REMOTE_ADDR']; 82 | 83 | // Reset flag used for error detection. 84 | $this->ok = false; 85 | 86 | // Validate all of the user input fields. 87 | if(!$info['name'] || !$info['email'] || !$info['password'] || !$info['password2']){ 88 | $this->msg = "Error! All fields are required."; 89 | return false; 90 | }elseif($info['password'] != $info['password2']){ 91 | $this->msg = "Error! Passwords do not match."; 92 | return false; 93 | }elseif(!$this->validEmail($info['email'])){ 94 | $this->msg = "Error! Please enter a valid e-mail address."; 95 | return false; 96 | } 97 | 98 | // Check to see if a user with that email address already exists. 99 | $query = $db->prepare("SELECT id, password FROM users WHERE email = :email"); 100 | $query->execute([':email'=>$email]); 101 | if($query->rowCount() == 1){ 102 | $this->msg = "Error! E-mail address is already in use."; 103 | }else{ 104 | // User doesn't exist, so create a new account! 105 | $query = $db->prepare("INSERT INTO users (name, email, password, status, create_ip) VALUES (:name, :email, :password, :status, :create_ip)"); 106 | $query->execute([':name'=>$info['name'],':email'=>$info['email'],':password'=>$password,':status'=>$status,':create_ip'=>$create_ip]); 107 | $this->msg = "User successfully added."; 108 | $this->ok = true; 109 | if($login) $this->login($info['email'],$info['password']); 110 | return true; 111 | } 112 | return false; 113 | } 114 | 115 | /** 116 | * Update a user's information. 117 | * 118 | * @param $info An array that contains the following info about the user: 119 | * - name, email, password, password2 (password repeated), status (optional) 120 | */ 121 | function update($info) { 122 | global $db; 123 | 124 | // Reset our error detection flag, which is used to set the status message later on. 125 | $this->ok = false; 126 | 127 | // Validate email address again. 128 | if(!$this->validEmail($info['email'])) { 129 | $this->msg = "Error! Please enter a valid e-mail address."; 130 | return false; 131 | } 132 | 133 | // Start building the SQL query with the data submitted so far. 134 | $sql = "name = :name, email = :email"; 135 | $exec = [':name'=>$info['name'], ':email'=>$info['email']]; 136 | 137 | // If a password has been entered, validate it, re-hash it and add it to the SQL query. 138 | if($info['password']){ 139 | if($info['password'] != $info['password2']){ 140 | $this->msg = "Error! Passwords do not match."; 141 | return false; 142 | } 143 | $password = md5($info['password'] . PASSWORD_SALT); 144 | $sql .= ", password = :password"; 145 | $exec[':password'] = $password; 146 | } 147 | 148 | // Create the finalized SQL query that will update our database. 149 | $sql = "UPDATE users SET ".$sql." WHERE id = :id"; 150 | $exec[':id'] = $this->user_id; 151 | $query = $db->prepare($sql); 152 | 153 | // Successfully updated the user data. 154 | if($query->execute($exec)) { 155 | // Let the user know via a cheeky message (OK not really cheeky). 156 | $this->msg = "Info successfully updated."; 157 | 158 | // Set user status flag back to true, peace has been restored. 159 | $this->ok = true; 160 | 161 | // Set new email and password info in the session and cookies. 162 | $_SESSION['auth_email'] = $email; 163 | if($info['password']) $_SESSION['auth_secret'] = $password; 164 | setcookie("auth_email", $email, time()+60*60*24*30, "/", COOKIE_DOMAIN); 165 | if($info['password']) setcookie("auth_secret", $password, time()+60*60*24*30, "/", COOKIE_DOMAIN); 166 | 167 | // Update local variables to reflect new changes. 168 | $this->name = $info['name']; 169 | $this->email = $info['email']; 170 | 171 | return true; 172 | } else { 173 | // There seems to have been a problem with the query somewhere. 174 | $this->msg = "There was a problem, please try again."; 175 | } 176 | return false; 177 | } 178 | 179 | /** 180 | * Function used to let hte user login, checking their email and password against 181 | * what's stored in the database. 182 | * 183 | * @param $email The user's email address. 184 | * @param $password The user's password, directly from POST. 185 | */ 186 | function login($email, $password) { 187 | global $db; 188 | 189 | // One of the fields is missing, deliver an error message. 190 | if(!$email || !$password) { 191 | $this->msg = "Error! Both E-mail and Password are required to login."; 192 | return false; 193 | } 194 | 195 | // Get user data using the email address supplied. 196 | $query = $db->prepare("SELECT id, password, name FROM users WHERE email = :email"); 197 | $query->execute([':email'=>$email]); 198 | 199 | // Set our user flag to false. 200 | $this->ok = false; 201 | 202 | // Fetch all results and process the data if the row exists. 203 | $results = $query->fetchAll(); 204 | if(count($results) == 1) { 205 | // Get the salted and hashed password stored in the database. 206 | $db_password = $results[0]['password']; 207 | 208 | // Salt the current password and if it matches the stored password, 209 | // proceed with logging in the user. 210 | if(md5($password . PASSWORD_SALT) == $db_password) { 211 | 212 | // Set session and cookie information. 213 | $_SESSION['auth_email'] = $email; 214 | $_SESSION['auth_secret'] = md5($results[0]['id'] . $results[0]['email']); 215 | setcookie("auth_email", $email, time()+60*60*24*30, "/", COOKIE_DOMAIN); 216 | setcookie("auth_secret", md5($results[0]['id'] . $results[0]['email']), time()+60*60*24*30, "/", COOKIE_DOMAIN); 217 | 218 | // Set local variables with the user's info. 219 | $this->user_id = $results[0]['id']; 220 | $this->name = $results[0]['name']; 221 | $this->email = $email; 222 | $this->ok = true; 223 | $this->is_logged = true; 224 | 225 | // Set status message. 226 | $this->msg = "Login Successful!"; 227 | 228 | return true; 229 | } else { 230 | $this->msg = "Error! Password is incorrect."; 231 | } 232 | } else { 233 | $this->msg = "Error! User does not exist."; 234 | } 235 | return false; 236 | } 237 | 238 | /** 239 | * This function checks the session/cookie info to see if it's real by comparing it 240 | * to what is stored in the database. 241 | * 242 | * @param $email The user's email address stored in session/cookie. 243 | * @param $secret The user's secret hash, a combination of their user id (from DB) 244 | * and their email address. 245 | */ 246 | function check($email, $secret) { 247 | global $db; 248 | 249 | // Get the user's info from the database. 250 | $query = $db->prepare("SELECT id, password, name FROM users WHERE email = :email"); 251 | $query->execute([':email'=>$email]); 252 | 253 | $results = $query->fetchAll(); 254 | if(count($results) == 1) 255 | { 256 | if(md5($results[0]['id'] . $results[0]['email']) == $secret) { 257 | $this->user_id = $results[0]['id']; 258 | $this->email = $email; 259 | $this->name = $results[0]['name']; 260 | $this->ok = true; 261 | $this->is_logged = true; 262 | return true; 263 | } 264 | } 265 | return false; 266 | } 267 | 268 | /** 269 | * Check to see if the user is logged in based on their session data. 270 | */ 271 | function is_logged(){ 272 | if($this->check($_SESSION['auth_email'], $_SESSION['auth_secret'])) return true; 273 | else return false; 274 | } 275 | 276 | /** 277 | * Get a user's information from the database. 278 | * 279 | * @param $field The field value to retrieve (if left blank, will return complete row) 280 | * @param $email The user's email address. If not specified, will load current user's info. 281 | */ 282 | function get_info($field = "*", $email = null){ 283 | global $db; 284 | 285 | if(!$email) $email = $this->email; 286 | $query = $db->query("SELECT $field FROM users WHERE email = '$email'"); 287 | $query->execute(); 288 | $results = $db->fetchAll(); 289 | if($field == "*") return $results[0]; 290 | else return $results[0][$field]; 291 | } 292 | 293 | /** 294 | * Log out the current user by setting all the local variables to their 295 | * default values and resetting our PHP session and cookie info. 296 | */ 297 | function logout(){ 298 | $this->user_id = 0; 299 | $this->email = "Guest"; 300 | $this->name = "Guest"; 301 | $this->ok = true; 302 | $this->msg = "You have been logged out!"; 303 | $this->is_logged = false; 304 | 305 | $_SESSION['auth_email'] = ""; 306 | $_SESSION['auth_secret'] = ""; 307 | setcookie("auth_email", "", time() - 3600, "/", COOKIE_DOMAIN); 308 | setcookie("auth_secret", "", time() - 3600, "/", COOKIE_DOMAIN); 309 | } 310 | 311 | /** 312 | * Validate the user's email address. 313 | * Courtesy LinuxJournal.com : http://www.linuxjournal.com/article/9585?page=0,3 314 | * 315 | * @param $email The email address to validate. 316 | */ 317 | function validEmail($email){ 318 | $isValid = true; 319 | $atIndex = strrpos($email, "@"); 320 | if (is_bool($atIndex) && !$atIndex){ 321 | $isValid = false; 322 | } 323 | else{ 324 | $domain = substr($email, $atIndex+1); 325 | $local = substr($email, 0, $atIndex); 326 | $localLen = strlen($local); 327 | $domainLen = strlen($domain); 328 | if ($localLen < 1 || $localLen > 64){ 329 | $isValid = false; 330 | }else if ($domainLen < 1 || $domainLen > 255){ 331 | $isValid = false; 332 | }else if ($local[0] == '.' || $local[$localLen-1] == '.'){ 333 | $isValid = false; 334 | }else if (preg_match('/\\.\\./', $local)){ 335 | $isValid = false; 336 | }else if (!preg_match('/^[A-Za-z0-9\\-\\.]+$/', $domain)){ 337 | $isValid = false; 338 | }else if (preg_match('/\\.\\./', $domain)){ 339 | $isValid = false; 340 | }else if(!preg_match('/^(\\\\.|[A-Za-z0-9!#%&`_=\\/$\'*+?^{}|~.-])+$/', str_replace("\\\\","",$local))){ 341 | if (!preg_match('/^"(\\\\"|[^"])+"$/', str_replace("\\\\","",$local))){ 342 | $isValid = false; 343 | } 344 | } 345 | if ($isValid && !(checkdnsrr($domain,"MX") || checkdnsrr($domain,"A"))){ 346 | $isValid = false; 347 | } 348 | } 349 | return $isValid; 350 | } 351 | } 352 | ?> 353 | --------------------------------------------------------------------------------