<?php
define('NOCONNFILE_ERROR',10001);
define('CONNECTION_ERROR',10002);
define('NODATABASE_ERROR',10003);
define('EXECQUERY_ERROR',10008);
define('NOFOUND_ERROR',10009);
define('NOACCESS_ERROR',10010);
define('NO_ERROR',10004);
define('INIT_PROCEDURE',10005);
define('ACTION_PROCEDURE',10006);
//-------------------------------------------
// std input class
//-------------------------------------------
class stdInput {
private $type;
private $name;
private $value;
private $values=array();
private $label='';
private $labels=array();
private $handlers;
//----------------------------
public function __construct ($type, $name, $value, $label='') {
$this->type=$type;
$this->name=$name;
//-----------------------------values
if (is_array($value)) {
for ($i=0; $i<count($value); $i++) {
$el=array();
if (substr($value[$i], strlen($value[$i])-1,1)=='*') {
$el["checked"]=true;
$el["value"]=substr($value[$i],0,strlen($value[$i])-1);
}
else {
$el["checked"]=false;
$el["value"]=$value[$i];
}
$this->values[]=$el;
}
} else
$this->value=$value;
//----------------------------labels
if (is_array($label)) {
for ($i=0;$i<count($label);$i++) {
$this->labels[]=$label[$i];
}
} else {
$this->label=$label;
}
}
//----------------------------
public function addHandler ($handler) {
$this->handlers[]=array('event'=>$handler[0],'handler'=>$handler[1]);
}
//----------------------------
public function draw() {
$tmp='';
$handlers_str='';
for ($i=0; $i<count($this->handlers); $i++) {
$handlers_str.=$this->handlers[$i]['event'].'="'.$this->handlers[$i]['handler'].'" ';
}
switch (strtoupper($this->type)) {
case 'TEXT':
case 'PASSWORD':
case 'SUBMIT':
case 'RESET':
case 'BUTTON':
case 'FILE':
case 'HIDDEN':
if ($this->label)
$tmp.="<label for=\"{$this->name}\">{$this->label}</label>";
$tmp.="<input $handlers_str type=\"{$this->type}\" name=\"{$this->name}\" value=\"{$this->value}\" />";
break;
//---------------------------------
case 'TEXTAREA':
if ($this->label)
$tmp.="<p>{$this->label}</p>";
$tmp.="<textarea $handlers_str name=\"{$this->name}\">{$this->value}</textarea>";
break;
//---------------------------------
case 'RADIO':
case 'CHECKBOX':
for ($i=0; $i<count($this->values); $i++) {
$checked=($this->values[$i]['checked']) ? 'checked':'';
$tmp.="<p><input $handlers_str type=\"{$this->type}\" name=\"{$this->name}\"
value=\"{$this->values[$i]['value']}\" $checked />";
$tmp.=" {$this->labels[$i]}</p>";
}
break;
case 'SELECT':
$tmp="<select $handlers_str name=\"{$this->name}\">";
for ($i=0; $i<count($this->values); $i++) {
$selected= ($this->values[$i]['checked']) ? 'selected': '';
$tmp.="<option value=\"{$this->values[$i]['value']}\" $selected>{$this->labels[$i]}</option>";
}
$tmp.="</select>";
break;
}
return $tmp;
}
}
//-------------------------------------------
// fieldset class
//-------------------------------------------
class stdFieldset {
private $fields=array();
private $legend;
//----------------------------
public function __construct($legend) {
$this->legend=$legend;
}
//----------------------------
public function addField($type, $name, $value, $label) {
$a= new stdInput($type, $name, $value, $label);
$this->fields[]= &$a;
return $a;
}
//----------------------------
public function draw() {
$tmp="<fieldset><legend>{$this->legend}</legend>";
for ($i=0; $i<count($this->fields);$i++) {
$tmp.=$this->fields[$i]->draw();
}
$tmp.='</fieldset>';
return $tmp;
}
}
//-------------------------------------------
// std form class
//-------------------------------------------
class stdForm {
private $action;
private $scripts=array();
private $fieldsets=array();
private $hidden_fields=array();
private $buttons=array();
//----------------------------
// constructor
//----------------------------
public function __construct($action, $onsubmit="") {
if (is_array($onsubmit)) {
$this->scripts['onsubmit']=array('handler'=>$onsubmit[0], 'script'=>$onsubmit[1]);
}
$this->action=$action;
}
//----------------------------
// add field set
//----------------------------
public function addFieldset($legend) {
$a = new stdFieldset($legend);
$this->fieldsets[]= &$a;
return $a;
}
//----------------------------
// add hidden
//----------------------------
public function addHidden($name, $value) {
$this->hidden_fields[]= new stdInput('HIDDEN', $name, $value);
}
//----------------------------
// add button
//----------------------------
public function addButton($type, $name, $value, $onclick="") {
if (is_array($onclick)) {
$this->scripts[$name]=array('handler'=>$onclick[0], 'script'=>$onclick[1]);
$handler=$onclick[0];
}
else
$handler='';
$a=new stdInput($type, $name, $value);
if (is_array($onclick))
$a->addHandler(array('onclick',$onclick[0]));
$this->buttons[]= &$a;
}
//----------------------------
public function draw() {
$tmp='';
$tmp.=$this->drawHeader();
for ($i=0; $i<count($this->fieldsets);$i++) {
$tmp.=$this->fieldsets[$i]->draw();
}
for ($i=0; $i<count($this->hidden_fields); $i++) {
$tmp.=$this->hidden_fields[$i]->draw();
}
for ($i=0; $i<count($this->buttons); $i++) {
$tmp.=$this->buttons[$i]->draw();
}
$tmp.=$this->drawFooter();
return $tmp;
}
//----------------------------
private function drawHeader() {
$tmp='';
foreach ($this->scripts as $script) {
$tmp.='<script type="text/javascript">';
$tmp.=$script['script'];
$tmp.='</script>';
}
if (isset($this->scripts['onsubmit'])) {
$subm='onsubmit="'.$this->scripts['onsubmit']['handler'].'"';
} else
$subm='';
$tmp.= '<div class="formblock"><form '.$subm.' action="'.
$this->action.'" method="POST" enctype="application/x-www-form-urlencoded">';
return $tmp;
}
//----------------------------
private function drawFooter() {
return '</form><div style="clear:both"></div></div>';
}
}
//-------------------------------------------
// guestbook form
//-------------------------------------------
class gbForm extends stdForm {
//-------------------------------
private $std_onsubmit=array(
'return check_form(this);',
'function check_form(f) {
for (var i=0; i<f.elements.length; i++) {
if (f.elements[i].value=="") {
alert(f.elements[i].name+" should be filled");
return false;
}
}
return true;
}');
//-------------------------------
private $stdcancel_onclick=array();
//-------------------------------
private $buttons=array();
//-------------------------------
// gbForm constructor
//-------------------------------
public function __construct($action_value, $step_value, $buttons, $onsubmit="") {
//--------------------------------------
$this->stdcancel_onclick=array(
'back_to_list();',
"function back_to_list() { window.location.assign('{$_SERVER["PHP_SELF"]}');}");
//-------------------------------------
$this->buttons=array (
'post'=>array('SUBMIT', ''),
'update'=>array('SUBMIT', ''),
'reset'=>array('RESET',''),
'cancel'=>array('BUTTON',$this->stdcancel_onclick),
'yes'=>array('SUBMIT',''),
'no'=>array('BUTTON',$this->stdcancel_onclick),
'login'=>array('SUBMIT',''),
'logout'=>array('SUBMIT',''),
'register'=>array('SUBMIT',''),
'save'=>array('SUBMIT',''));
//-------------------------------------
if ($onsubmit=='default')
$subm = $this->std_onsubmit;
else
$subm=$onsubmit;
parent::__construct($_SERVER["PHP_SELF"], $subm);
$this->addHidden('action',$action_value);
$this->addHidden('step',$step_value);
for ($i=0;$i<count($buttons); $i++) {
$this->addButton($this->buttons[$buttons[$i]][0],
$buttons[$i], $buttons[$i], $this->buttons[$buttons[$i]][1]);
}
}
}
//-------------------------------------------
// add record form
//-------------------------------------------
class addrecForm extends gbForm {
//------------------------------
public function __construct($loggedIn) {
parent::__construct('add',2,array('post','reset','cancel'), 'default');
$fset=$this->addFieldset('adding guestbook entry');
if (!$loggedIn)
$fset->addField('TEXT','entry_author','anonimous','Input name');
$fset->addField('TEXT','entry_caption','','Input title');
$fset->addField('TEXTAREA','entry_text','','Input text');
}
}
//-------------------------------------------
// edit record form
//-------------------------------------------
class editrecForm extends gbForm {
//------------------------------
public function __construct($inrow) {
parent::__construct('edit',2,array('update','cancel'), 'default');
$fset=$this->addFieldset('editing guestbook entry');
$fset->addField('TEXT','entry_caption',$inrow['entry_caption'],'Input title');
$fset->addField('TEXTAREA','entry_text',$inrow['entry_text'],'Input text');
}
}
//-------------------------------------------
// delete form
//-------------------------------------------
class deleteForm extends gbForm {
public function __construct() {
parent::__construct('delete',2,array('yes','no'),'default');
$fset=$this->addFieldset('record will be deleted. Are you sure?');
}
}
//-------------------------------------------
// login form
//-------------------------------------------
class loginForm extends gbForm {
public function __construct() {
parent::__construct('login',2, array('login','reset','cancel'),'default');
$fset=$this->addFieldset('logging in');
$fset->addField('TEXT','username','','Input your name');
$fset->addField('PASSWORD','password','','Input password');
}
}
//-------------------------------------------
// logout form
//-------------------------------------------
class logoutForm extends gbForm {
public function __construct() {
parent::__construct('logout',2, array('yes','no'),'default');
$fset=$this->addFieldset('Are you sure you want to quit?');
}
}
//-------------------------------------------
// register form
//-------------------------------------------
class registerForm extends gbForm {
public function __construct() {
$onsubmit=array('return check_form(this);',
' function check_form(f) {
var isok=true;
if (f.username.value=="") {
isok=false;
alert("user name cannot be empty");
}
if (f.password.value=="") {
isok=false;
alert("password cannot be empty");
}
if (f.password.value!=f.confpass.value) {
isok=false;
alert("password confirmation doesn\'t suit");
}
return isok;
}');
parent::__construct('register',2, array('register','reset','cancel'),$onsubmit);
$fset=$this->addFieldset('Registering user');
$fset->addField('TEXT','username','','Input user name');
$fset->addField('PASSWORD','password','','Input password');
$fset->addField('PASSWORD','confpass','','Confirm password');
$fset->addField('TEXT','useremail','','Input email');
$fset=$this->addFieldset('Input your gender');
$fset->addField('RADIO','gender',array('M*','F'), array('male','female'));
$fset=$this->addFieldset('Input your country');
$fset->addField('SELECT','country', array('US*','UK','Russia','China'),
array('United States','United Kingdom', 'Russia', 'China'));
$fset=$this->addFieldset('Input your interests');
$fset->addField('CHECKBOX','interests[]', array('movies*','books*','art'), array('movies','books','art'));
}
}
//-------------------------------------------
// connection file form
//-------------------------------------------
class connectionfileForm extends gbForm {
public function __construct($action, $inf) {
parent::__construct($action, 2, array('save','cancel'), 'default');
$fset=$this->addFieldset('editing connection params');
$fset->addField('TEXT','host',$inf[0],'Input database host');
$fset->addField('TEXT','username',$inf[1],'Input database username');
$fset->addField('TEXT','password',$inf[2],'Input database password');
$fset->addField('TEXT','database',$inf[3],'Input database name');
}
}
//-------------------------------------------
// GuestBook Model
//-------------------------------------------
class gbModel {
const PARAM_FILE='connparams.txt';
const ENTRIES_PER_PAGE=4;
public static $gb;
//-----------------------------------
public $loginref='';
public $registerref='';
public $conmenu;
public $gbpage='';
public $breadcrumbs='';
public $navigation='';
public $addeditform='';
public $debugblock='';
//-----------------------------------
private $errorno=NO_ERROR;
private $error_message='';
private $error_procedure=0;
public $logged_in=false;
public $user_id=0;
//-----------------------------------
public $action='';
public $step=1;
public $current_element=0;
public $current_page=1;
public $got_params=false;
public $current_procedure=0;
public $redirect_path='';
//-----------------------------------
public $conn_params = array (
'host'=>'', 'username'=>'', 'password'=>'', 'database'=>'');
private $db;
//-------------------------------------------
// constructor
//-------------------------------------------
private function __construct() {
}
//-------------------------------------------------trass
private function trass($instr, $isvar=false) {
if ($isvar) {
$this->debugblock.='<pre>'.print_r($instr, true).'</pre><br/>';
} else {
$this->debugblock.=$instr.'<br/>';
}
}
//-------------------------------------------
// get connection parameters
//-------------------------------------------
private function getconnparams() {
$this->trass('getting connection parameters');
if (!file_exists(gbModel::PARAM_FILE))
throw new Exception ('params file doesn\'t exist', NOCONNFILE_ERROR);
$tmp=file(gbModel::PARAM_FILE);
foreach ($tmp as &$item) {
$item=substr($item, strpos($item,':')+1);
$item=substr($item,0, strlen($item)-2);
}
$this->conn_params['host']= $tmp[0];
$this->conn_params['username'] = $tmp[1];
$this->conn_params['password'] = $tmp[2];
$this->conn_params['database'] = $tmp[3];
}
//-------------------------------------------
// connection to database
//-------------------------------------------
private function connect() {
$this->trass('connecting');
$this->db= @new mysqli($this->conn_params['host'],
$this->conn_params['username'],
$this->conn_params['password'],
$this->conn_params['database']);
if (mysqli_connect_errno())
throw new Exception(mysqli_connect_error(), CONNECTION_ERROR);
}
//-------------------------------------------
// check whether the database exists
//-------------------------------------------
private function checkDB() {
$this->trass('check whether the database exists');
$result=$this->db->query('select * from gb');
if ($result===FALSE)
throw new Exception ('Database doesn\'t exist', NODATABASE_ERROR);
}
//-------------------------------------------
// initialize model
//-------------------------------------------
public function init() {
$this->trass('init model');
if (!$this->got_params)
$this->getconnparams();
$this->connect();
if ($this->action!='database')
$this->checkDB();
}
//-------------------------------------------
// model handler (init, actions, errors)
//-------------------------------------------
public function defaultProcess() {
$this->trass('default model process');
if (!in_array($this->action, array('error','connfile','editconnfile'))) {
$current_procedure=INIT_PROCEDURE;
try {
$this->init();
}
catch (Exception $e) {
$this->handle_errors($e);
return;
}
}
$current_procedure=ACTION_PROCEDURE;
try {
$this->performAction();
}
catch (Exception $e) {
$this->handle_errors($e);
return;
}
}
//-------------------------------------------
// perform actions
//-------------------------------------------
private function performAction() {
$this->trass('perform actions');
$this->trass("action={$this->action}");
$this->trass("step={$this->step}");
//----------------------------------------
//-----------------------------
switch ($this->action) {
case 'error':
$this->showErrorPage();
break;
case 'add':
switch ($this->step) {
case 1: $this->drawAddForm();
break;
case 2: $this->addRecord();
break;
} break;
case 'edit':
switch ($this->step) {
case 1: $this->drawAddForm(true);
break;
case 2: $this->saveRecord();
break;
} break;
case 'delete':
switch ($this->step) {
case 1: $this->drawDeleteForm();
break;
case 2: $this->deleteRecord();
break;
} break;
case 'login':
switch ($this->step) {
case 1: $this->drawLoginForm();
break;
case 2: $this->login();
break;
} break;
case 'logout':
switch ($this->step) {
case 1: $this->drawLogoutForm();
break;
case 2: $this->logout();
break;
} break;
case 'register':
switch ($this->step) {
case 1: $this->drawRegisterForm();
break;
case 2: $this->register();
break;
} break;
case 'connfile':
switch ($this->step) {
case 1: $this->drawConnFileForm();
break;
case 2: $this->saveConnection();
break;
} break;
case 'editconnfile':
switch ($this->step) {
case 1: $this->drawConnFileForm(true);
break;
case 2: $this->saveConnection();
break;
} break;
case 'database':
switch ($this->step) {
case 1: $this->drawCreateDatabaseForm();
break;
case 2: $this->createDatabase();
break;
} break;
}
//-----------------------
if (!in_array($this->action, array('connfile','editconnfile','database','error'))) {
$this->drawLoginRef();
$this->drawRegisterRef();
}
if (
(in_array($this->action, array('view','add','edit'))) ||
( ($this->action=='error') &&
(in_array($this->errorno,array(NOFOUND_ERROR, NOACCESS_ERROR))) )
) {
$this->drawBreadCrumbs();
if ($this->action!='error')
$this->drawPage();
$this->drawNavigation();
}
//-----------------------------
$this->drawConMenu(array('view','editconnfile','database'),
array('home','check conection file','recreate database'));
}
//-------------------------------------------
// execute query
//-------------------------------------------
private function execQuery($sql) {
if (!$this->db->query($sql))
throw new Exception ('error while executing query: '.$sql.' '.$this->db->error,EXECQUERY_ERROR);
}
//-------------------------------------------
// get single row
//-------------------------------------------
private function getSingle($sql) {
$result=$this->db->query($sql);
if ($result===FALSE)
throw new Exception ('error while executing query: '.$sql.' '.$this->db->error,EXECQUERY_ERROR);
$outinf=array();
if ($row=$result->fetch_array(MYSQLI_NUM)) {
for ($i=0; $i<$result->field_count; $i++) {
$field_info=$result->fetch_field();
$outinf[$field_info->name]=$row[$i];
}
}
else
throw new Exception ('error no data found: '.$sql, NOFOUND_ERROR);
$result->free();
return $outinf;
}
//-------------------------------------------
// exec param query
//-------------------------------------------
private function execQueryP($sql, $param) {
$stmt=$this->db->prepare($sql);
call_user_func_array(array($stmt,'bind_param'), $param);
if (!$stmt->execute())
throw new Exception('error while executing query: '.$sql.' '.$stmt->error, EXECQUERY_ERROR);
$recid=$stmt->insert_id;
$stmt->close();
return $recid;
}
//-------------------------------------------
// draw context menu
//-------------------------------------------
private function drawConMenu($actions,$labels) {
$tmp='<ul>';
for ($i=0; $i<count($actions);$i++) {
$tmp.='<li>'.$this->link("action={$actions[$i]}",$labels[$i]).'</li>';
}
$tmp.='</ul>';
$this->conmenu=$tmp;
}
//-------------------------------------------
// draw login reference
//-------------------------------------------
private function drawLoginRef() {
$tmp='<div class="login_block">';
if (!$this->logged_in)
$tmp.=$this->link('action=login','LogIn');
else
{
$myname=$this->getUserName($this->user_id);
$tmp.='Hello '.$myname.$this->link('action=logout','LogOut');
}
$tmp.='</div>';
$this->loginref=$tmp;
}
//-------------------------------------------
// get user name by id
//-------------------------------------------
private function getUserName($user_id) {
$usr=$this->getSingle("select user_name from gbusers where id={$user_id}");
return $usr["user_name"];
}
//-------------------------------------------
// draw register reference
//-------------------------------------------
private function drawRegisterRef() {
$tmp='<div class="register_block">';
if (!$this->logged_in)
$tmp.=$this->link('action=register','Register');
$tmp.='</div>';
$this->registerref=$tmp;
}
//-------------------------------------------
// draw guestbook page
//-------------------------------------------
public function drawPage() {
$this->trass('draw page');
$sql='select a.id, a.entry_author, a.entry_date, '.
'a.entry_caption, a.entry_text, b.user_name, a.entry_author_id from gb a '.
'left join gbusers b on a.entry_author_id=b.id ';
$result=$this->db->query($sql);
if ($result===FALSE)
throw new Exception ('error executing query: '.$sql, EXECQUERY_ERROR);
$this->trass($result->num_rows);
$result->data_seek(($this->current_page-1)* gbModel::ENTRIES_PER_PAGE);
$num=0;
$this->gbpage='';
while (($row=$result->fetch_assoc()) && ($num < gbModel::ENTRIES_PER_PAGE)) {
$this->gbpage.= "<div class =\"gbentry\">".
"<div class=\"gbauthor\">".
(($row['user_name']!==NULL) ? $row['user_name'] : $row['entry_author'])."</div>".
"<div class=\"gbdate\">{$row['entry_date']}</div>".
"<div class=\"gbcaption\">{$row['entry_caption']}</div>".
"<div class=\"gbtext\">{$row['entry_text']}</div>".
$this->get_buttons($row['entry_author_id'], $row['id']).
"</div>";
$num++;
}
$this->trass($num);
$result->free();
$this->gbpage.=$this->get_edit_panel();
}
//-------------------------------------------
// draw post buttons
//-------------------------------------------
private function get_buttons($author_id, $entry_id) {
$tmp="<div class=\"entry_buttons\">";
if ((!$this->logged_in) || ($this->user_id!=$author_id))
return $tmp.'</div>';
$tmp.=$this->link("action=edit&element=$entry_id",'edit');
$tmp.=$this->link("action=delete&element=$entry_id",'delete');
return $tmp.'</div>';
}
//---------------------------------------------
// draw page edit panel
//---------------------------------------------
private function get_edit_panel() {
$tmp='<div class="edit_panel">';
$tmp.=$this->link('action=add','add record to guestbook');
return $tmp.'</div>';
}
//---------------------------------------------
// draw breadcrumbs
//---------------------------------------------
private function drawBreadCrumbs() {
$this->breadcrumbs='<div class="breadcrumbs">You are at the page: '.
$this->current_page.'</div>';
}
//---------------------------------------------
// draw navigation block
//---------------------------------------------
private function drawNavigation() {
$tmp="<div class=\"navigation_block\">";
$n_pages=$this->num_pages();
for ($i=1; $i<=$n_pages; $i++) {
$tmp.='<div class="navigation_element_block">';
if ($i==$this->current_page) {
$tmp.=$i;
} else {
$tmp.=$this->link("action=view&page=$i", $i);
}
$tmp.='</div>';
}
$tmp.='</div>';
$this->navigation=$tmp;
}
//-------------------------------------------
// count pages
//-------------------------------------------
private function num_pages() {
$res=$this->getSingle('select count(*) cnt from gb');
$this->trass($res, true);
return ceil($res['cnt']/gbModel::ENTRIES_PER_PAGE);
}
//-------------------------------------------
// add (edit) record form
//-------------------------------------------
private function drawAddForm($edit=false) {
$title='';
$text='';
$this->trass('draw adding (editing) form');
if ($edit)
$this->checkPrivileges();
if ($edit) {
$row=$this->getSingle("select * from gb where id={$this->current_element}");
$frm= new editrecForm($row);
} else {
$frm=new addrecForm($this->logged_in);
}
$tmp=$frm->draw();
$this->addeditform=$tmp;
}
//-------------------------------------------
// add record to database
//-------------------------------------------
private function addRecord() {
$this->trass('adding record');
if ($this->logged_in) {
$entry_author=$this->getUserName($this->user_id);
} else {
$entry_author=$this->filter($_REQUEST["entry_author"]);
}
$entry_date=date('YmdHis');
$entry_caption=$this->filter($_REQUEST["entry_caption"]);
$entry_text=$this->filter($_REQUEST["entry_text"]);
$sql='insert into gb(entry_author_id, entry_author, entry_date, entry_caption, entry_text)'.
' values(?,?,?,?,?)';
$num_rec = $this->execQueryP($sql, array('issss',$this->user_id,
$entry_author, $entry_date, $entry_caption, $entry_text));
$stmt=$this->db->Prepare($sql);
$this->addeditform.=
'record successfully added '.
$this->link("action=viewrecord&element=$num_rec",'View record').
$this->link("action=edit&element=$num_rec",'Edit record');
}
//-------------------------------------------
// save record to database
//-------------------------------------------
private function saveRecord() {
$this->trass('saving record');
$this->checkPrivileges();
if ($this->logged_in) {
$entry_author=$this->getUserName($this->user_id);
} else {
$entry_author=$_REQUEST['entry_author'];
}
$entry_date=date('YmdHis');
$entry_caption=$this->filter($_REQUEST["entry_caption"]);
$entry_text=$this->filter($_REQUEST["entry_text"]);
$sql='update gb set entry_author=?, entry_date=?,'.
'entry_caption=?, entry_text=? where id=?';
$stmt=$this->execQueryP($sql, array('ssssi', $entry_author, $entry_date,
$entry_caption, $entry_text,
$this->current_element));
$this->addeditform=
'record successfully updated'.
$this->link("action=viewrecord&element={$this->current_element}",'View record').
$this->link("action=edit&element={$this->current_element}",'Edit record');
}
//-------------------------------------------
// draw delete record form
//-------------------------------------------
private function drawDeleteForm() {
$this->checkPrivileges();
$delform= new deleteForm();
$this->gbpage=$delform->draw();
}
//-------------------------------------------
// delete record from database
//-------------------------------------------
private function deleteRecord() {
$this->checkPrivileges();
$this->execQuery("delete from gb where id={$this->current_element}");
$this->gbpage='record successfully deleted '.
$this->link("action=view",'back to list');
}
//-------------------------------------------
// draw login form
//-------------------------------------------
private function drawLoginForm() {
$loginform = new loginForm();
$this->gbpage=$loginform->draw();
}
//-------------------------------------------
// login
//-------------------------------------------
private function login() {
$uname=$this->filter($_REQUEST["username"]);
$sql='select user_name, user_password, id from gbusers '.
"where user_name='{$uname}'";
$isok=false;
try {
$row=$this->getSingle($sql);
if ($row['user_password']==$_REQUEST["password"])
$isok=true;
}
catch (Exception $e) {
}
if ($isok) {
$this->logged_in=true;
$this->user_id=$row['id'];
$this->gbpage="Hello $uname".
$this->link('action=view','return to list');
}
else
$this->gbpage="Error: invalid password or user doesn't exist".
$this->link('action=login','try again').
$this->link('action=view','back to list');
}
//-------------------------------------------
// draw logout form
//-------------------------------------------
private function drawLogoutForm() {
$logoutform = new logoutForm();
$this->gbpage=$logoutform->draw();
}
//-------------------------------------------
// logout
//-------------------------------------------
private function logout() {
$this->logged_in=false;
$this->user_id=0;
$this->setRedirect('action=view');
}
//-------------------------------------------
// draw register form
//-------------------------------------------
private function drawRegisterForm() {
$this->trass('draw register form');
$regform = new registerForm();
$this->gbpage=$regform->draw();
}
//-------------------------------------------
private function register() {
$uname=$this->filter($_REQUEST["username"]);
$passw=$_REQUEST["password"];
$email=$this->filter($_REQUEST["useremail"]);
$gender=$this->filter($_REQUEST["gender"]);
$country=$this->filter($_REQUEST["country"]);
$interests=$this->filter(implode(",",$_REQUEST["interests"]));
$comments=$this->filter($_REQUEST["comments"]);
$sql="select * from gbusers where user_name=\"$uname\"";
$result=$this->db->Query($sql);
if ($result===FALSE) {
throw new Exception ('Error while executing query: '.$sql, EXECQUERY_ERROR);
}
if ($result->num_rows>0) {
$this->gbpage= <<<INF
Error: user already exists
{$this->link("action=register",'try again')}
{$this->link("action=view", 'back to list')}
INF;
return;
}
$sql="insert into gbusers(user_name, user_password, user_email) ".
"values(?,?,?)";
$this->user_id=$this->execQueryP($sql, array("sss", $uname, $passw, $email));
$this->logged_in=true;
$this->gbpage="user successfully created ".
$this->link("action=view",'back to list');
}
//-------------------------------------------
// draw form for connection file editing
//-------------------------------------------
private function drawConnFileForm($edit=false) {
$this->trass('draw connection file edit form');
if ($edit) {
if (!file_exists(gbModel::PARAM_FILE))
throw new Exception ('no connection file', NOCONNFILE_ERROR);
$inf=file(gbModel::PARAM_FILE);
foreach ($inf as &$item) {
$item=substr($item, strpos($item,':')+1);
$item=substr($item,0, strlen($item)-2);
}
}
if (!isset($inf))
$inf=array('','','','');
$connfileForm= new connectionfileForm($this->action,$inf);
$this->gbpage = $connfileForm->draw();
}
//-------------------------------------------
// save connection file
//-------------------------------------------
private function saveConnection() {
$fh=fopen(gbModel::PARAM_FILE,'wb');
fwrite($fh,'host:'.$_REQUEST["host"]."\r\n");
fwrite($fh,'username:'.$_REQUEST["username"]."\r\n");
fwrite($fh,'password:'.$_REQUEST["password"]."\r\n");
fwrite($fh,'database:'.$_REQUEST["database"]."\r\n");
fclose($fh);
$this->gbpage= 'file successfully written'.
$this->link('action=editconnfile','edit connection file').
$this->link('action=view', 'go to guestbook');
}
//-------------------------------------------
// draw create database form
//-------------------------------------------
private function drawCreateDatabaseForm() {
$this->gbpage=<<<INF
<script type="text/javascript">
function back_to_list() {
window.location.assign("{$_SERVER["PHP_SELF"]}");
}
</script>
Database will be recreated. Are you sure?
<form action="{$_SERVER["PHP_SELF"]}" method="POST" enctype="application/x-www-form-urlencoded">
<input type="HIDDEN" name="action" value="database" />
<input type="HIDDEN" name="step" value=2 />
<input type="SUBMIT" name="submit" value="ok" />
<input type="BUTTON" value="cancel" onclick="back_to_list();" />
</form>
INF;
}
//-------------------------------------------
// create database
//-------------------------------------------
private function createDatabase() {
$sqls=array();
$sqls[]='drop table if exists gb';
$sqls[]='drop table if exists gbusers';
$sqls[]='create table gb (id int(11) not null auto_increment,
entry_author_id int(11),
entry_author varchar(50),
entry_date datetime,
entry_caption varchar(200),
entry_text varchar(1000),
primary key(`id`))';
$sqls[]='create table gbusers(id int(11) not null auto_increment,
user_name varchar(50),
user_password varchar(50),
user_email varchar(100),
user_gender varchar(1),
user_interests varchar(200),
user_country varchar(50),
user_picture varchar(100),
primary key(`id`))';
foreach ($sqls as $sql)
$this->execQuery($sql);
session_destroy();
$this->gbpage='database successfully created'.
$this->link('action=view','Home');
}
//-------------------------------------------
// set redirect path
//-------------------------------------------
private function setRedirect($action) {
$this->redirect_path=$_SERVER["PHP_SELF"]."?$action";
}
//-------------------------------------------
// filter form data
//-------------------------------------------
private function filter($instr) {
return $this->db->real_escape_string(htmlentities($instr));
}
//-------------------------------------------
// check user privileges
//-------------------------------------------
private function checkPrivileges() {
if ($this->user_id===0)
throw new Exception ('data access denied', NOACCESS_ERROR);
$sql="select entry_author_id from gb where id={$this->current_element}";
$row=$this->getSingle($sql);
}
//-------------------------------------------
// show error page
//-------------------------------------------
private function showErrorPage() {
$this->trass('show error page');
$tmp='<div id="errormessage_block">';
switch ($this->errorno) {
case NOCONNFILE_ERROR:
$tmp.='Connection file doesn\'t exist';
$tmp.=$this->link('action=connfile','Create connection file?');
break;
case CONNECTION_ERROR:
$tmp.='Connection failed';
$tmp.=$this->link('action=editconnfile','Check connection file?');
break;
case NODATABASE_ERROR:
$tmp.='Database doesn\'t exist';
$tmp.=$this->link('action=database','Create database?');
break;
case NOFOUND_ERROR:
$tmp.=$this->error_message;
break;
case NOACCESS_ERROR:
$tmp.=$this->error_message;
$tmp.=$this->link('action=view','back');
break;
default:
$tmp.=$this->error_message;
$tmp.=$this->link('action=view','back');
}
$tmp.='</div>';
$this->gbpage=$tmp;
}
//-------------------------------------------
// draw reference link
//-------------------------------------------
private function link($action,$text) {
return "<a href=\"{$this->getRoute($action)}\">$text</a>";
}
//-------------------------------------------
// get route address
//-------------------------------------------
private function getRoute($action) {
return $_SERVER["PHP_SELF"]."?$action";
}
//-------------------------------------------
// handle all exceptions
//-------------------------------------------
private function handle_errors($e) {
$this->trass('handle error');
$this->trass('error:'.$e->getMessage());
if ($this->action=='error')
die ('exception while error handling');
$this->errorno=$e->getCode();
$this->error_message=$e->getMessage();
$this->error_procedure=$this->current_procedure;
$this->action='error';
$this->defaultProcess();
}
//-------------------------------------------
// get guestbook instance
//-------------------------------------------
static function getGb() {
if (!isset(gbModel::$gb))
gbModel::$gb = new gbModel();
return gbModel::$gb;
}
}
//-----------------------------------------------------------------------------
// GuestBook Controller
//-----------------------------------------------------------------------------
class gbController {
public $gb;
public static $controller;
//-------------------------------------------
// constructor
//-------------------------------------------
private function __construct() {
$this->gb= gbModel::getGb();
$this->process();
}
//-------------------------------------------
// get controller instance
//-------------------------------------------
static function getController() {
if (!isset(gbController::$controller))
gbController::$controller= new gbController();
return gbController::$controller;
}
//-------------------------------------------
// controller main procedure
//-------------------------------------------
public function process() {
session_start();
$this->restoreSession();
$this->processInput();
$this->triggerGB();
$this->saveSession();
session_commit();
if ($this->gb->redirect_path)
header("Location: {$this->gb->redirect_path}");
}
//-------------------------------------------
// restore session
//-------------------------------------------
private function restoreSession() {
if (isset($_SESSION['current_page']))
$this->gb->current_page=$_SESSION['current_page'];
if (isset($_SESSION['current_element']))
$this->gb->current_element=$_SESSION['current_element'];
if (isset($_SESSION['got_params']))
$this->gb->got_params=$_SESSION['got_params'];
if (isset($_SESSION['conn_params']))
$this->gb->conn_params=$_SESSION['conn_params'];
if (isset($_SESSION['logged_in']))
$this->gb->logged_in=$_SESSION['logged_in'];
if (isset($_SESSION['user_id']))
$this->gb->user_id=$_SESSION['user_id'];
}
//-------------------------------------------
// save session
//-------------------------------------------
private function saveSession() {
$_SESSION['current_page']=$this->gb->current_page;
$_SESSION['current_element']=$this->gb->current_element;
$_SESSION['got_params']=$this->gb->got_params;
$_SESSION['conn_params']=$this->gb->conn_params;
$_SESSION['logged_in']=$this->gb->logged_in;
$_SESSION['user_id']=$this->gb->user_id;
}
//-------------------------------------------
// process input parameters
//-------------------------------------------
private function processInput() {
//--------------------------
if (isset($_REQUEST['action'])) {
$this->gb->action=$_REQUEST['action'];
}
else
$this->gb->action='view';
//--------------------------
if (isset($_REQUEST['step'])) {
$this->gb->step=$_REQUEST['step'];
}
else
$this->gb->step=1;
//--------------------------
if (isset($_REQUEST['page'])) {
$this->gb->current_page=$_REQUEST['page'];
}
//--------------------------
if (isset($_REQUEST['element'])) {
$this->gb->current_element=$_REQUEST['element'];
}
}
//-------------------------------------------
// trigger guestbook main process
//-------------------------------------------
private function triggerGB() {
$this->gb->defaultProcess();
}
}