<?php
class saxuedatabase extends saxueobject {
		static public $instance = array();

		public function saxuedatabase() {
				$this -> saxueobject();
		} 

		public function retinstance() {
				return self :: $instance;
		} 

		public function close( $_db = null ) {
				if ( is_object( $_db ) ) {
						$_db -> close();
				} else if ( !empty( self :: $instance ) ) {
						foreach ( self :: $instance as $db ) {
								$db -> close();
						} 
				} 
		} 

		public function getinstance( $dbset = array() ) {
				if ( !is_array( $dbset ) ) {
						$dbset = array();
				} 
				if ( !isset( $dbset['dbtype'] ) ) {
						$dbset['dbtype'] = SAXUE_DB_TYPE;
				} 
				if ( !isset( $dbset['dbhost'] ) ) {
						$dbset['dbhost'] = SAXUE_DB_HOST;
				} 
				if ( !isset( $dbset['dbuser'] ) ) {
						$dbset['dbuser'] = SAXUE_DB_USER;
				} 
				if ( !isset( $dbset['dbpass'] ) ) {
						$dbset['dbpass'] = SAXUE_DB_PASS;
				} 
				if ( !isset( $dbset['dbname'] ) ) {
						$dbset['dbname'] = SAXUE_DB_NAME;
				} 
				if ( !isset( $dbset['dbpconnect'] ) ) {
						$dbset['dbpconnect'] = SAXUE_DB_PCONNECT;
				} 
				if ( !isset( $dbset['dbcharset'] ) && defined( "SAXUE_DB_CHARSET" ) ) {
						$dbset['dbcharset'] = SAXUE_DB_CHARSET;
				} 
				if ( !isset( $dbset['dbusage'] ) ) {
						$dbset['dbusage'] = 0;
				} else {
						$dbset['dbusage'] = intval( $dbset['dbusage'] );
				} 
				$inskey = md5( implode( "|", $dbset ) );
				if ( !isset( self :: $instance[$inskey] ) ) {
						switch ( $dbset['dbtype'] ) {
								case "mysql" :
										require_once( "mysql/db.php" );
										self :: $instance[$inskey] = new saxuemysqldatabase();
										break;
								case "sqlite" :
										require_once( "sqlite/db.php" );
										self :: $instance[$inskey] = new saxuesqlitedatabase();
										break;
								default :
										saxue_printfail( "The database type (" . $dbset['dbtype'] . ") is not exists!", 0 );
										return false;
						} 
						self :: $instance[$inskey] -> setdbset( $dbset );
				} 
				return self :: $instance[$inskey];
		} 
} 

class saxueobjectdata extends saxueobject {
		public $_isNew = false;

		public function saxueobjectdata() {
				$this -> saxueobject();
		} 

		public function setnew() {
				$this -> _isNew = true;
		} 

		public function unsetnew() {
				$this -> _isNew = false;
		} 

		public function isnew() {
				return $this -> _isNew;
		} 

		public function initvar( $_key, $_type, $_value = null, $_caption = "", $_required = false, $_maxlength = null, $_isdirty = false ) {
				$this -> vars[$_key] = array( "type" => $_type, "value" => $_value, "caption" => $_caption, "required" => $_required, "maxlength" => $_maxlength, "isdirty" => $_isdirty, "default" => "", "options" => "" );
		} 

		public function setoptions( $_key, $_options ) {
				$this -> vars[$_key]['options'] = $_options;
		} 

		public function setvar( $_key, $_value, $_isdirty = true ) {
				if ( !empty( $_key ) && isset( $_value ) ) {
						if ( !isset( $this -> vars[$_key] ) ) {
								$this -> initvar( $_key, SAXUE_TYPE_TXTBOX );
						} 
						$this -> vars[$_key]['value'] = $_value;
						$this -> vars[$_key]['isdirty'] = $_isdirty;
				} 
		} 

		public function setvars( $_vars, $_isdirty = false ) {
				if ( is_array( $_vars ) ) {
						foreach ( $_vars as $_key => $_value ) {
								$this -> setvar( $_key, $_value, $_isdirty );
						} 
				} 
		} 

		public function getvars( $_format = "" ) {
				if ( in_array( $_format, array( "s", "e", "q", "t", "o", "n" ) ) ) {
						$_ret = array();
						foreach ( $this -> vars as $_k => $_v ) {
								$_ret[$_k] = $this -> getvar( $_k, $_format );
						} 
						return $_ret;
				} 
				return $this -> vars;
		} 

		public function getvar( $_key, $_format = "s" ) {
				if ( isset( $this -> vars[$_key]['value'] ) ) {
						if ( is_string( $this -> vars[$_key]['value'] ) ) {
								switch ( strtolower( $_format ) ) {
										case "s" :
												return saxue_htmlstr( $this -> vars[$_key]['value'] );
										case "e" :
												return preg_replace( "/&amp;#(\\d+);/isU", "&#\\1;", htmlspecialchars( $this -> vars[$_key]['value'], ENT_QUOTES ) );
										case "q" :
												return saxue_dbslashes( $this -> vars[$_key]['value'] );
										case "t" :
												return $this -> vars[$_key]['caption'];
										case "o" :
												return !empty( $this -> vars[$_key]['options'][$this -> vars[$_key]['value']] ) ? $this -> vars[$_key]['options'][$this -> vars[$_key]['value']] : "";
										case "n" :
												return $this -> vars[$_key]['value'];
								} 
						} 
						return $this -> vars[$_key]['value'];
				} 
				return false;
		} 
} 

class saxuequeryhandler extends saxueobject {
		public $db;
		public $sqlres;

		public function saxuequeryhandler( $_db = "" ) {
				$this -> saxueobject();
				if ( empty( $_db ) || !is_object( $_db ) ) {
						$this -> db = &saxuedatabase :: getinstance();
				} else {
						$this -> db = &$_db;
				} 
		} 

		public function setdb( $_db ) {
				$this -> db = &$_db;
		} 

		public function getdb() {
				return $this -> db;
		} 

		public function execute( $_criteria = null, $_full = false, $_nobuffer = false ) {
				if ( is_object( $_criteria ) ) {
						$_sql = $_criteria -> getsql();
						if ( !$_full ) {
								$_sql .= " " . $_criteria -> renderwhere();
						} 
						$this -> sqlres = $this -> db -> query( $_sql, 0, 0, $_nobuffer );
						return $this -> sqlres;
				} elseif ( !empty( $_criteria ) ) {
						$this -> sqlres = $this -> db -> query( $_criteria, 0, 0, $_nobuffer );
						return $this -> sqlres;
				} 
				return false;
		} 

		public function queryobjects( $_criteria = null, $_nobuffer = false ) {
				$_limit = $_start = 0;
				$_sql = "SELECT " . $_criteria -> getfields() . " FROM " . $_criteria -> gettables() . " " . $_criteria -> renderwhere();
				if ( $_criteria -> getgroupby() != "" ) {
						$_sql .= " GROUP BY " . $_criteria -> getgroupby();
				} 
				if ( $_criteria -> getsort() != "" ) {
						$_sql .= " ORDER BY " . $_criteria -> getsort() . " " . $_criteria -> getorder();
				} 
				$_limit = $_criteria -> getlimit();
				$_start = $_criteria -> getstart();
				$this -> sqlres = $this -> db -> query( $_sql, $_limit, $_start, $_nobuffer );
				return $this -> sqlres;
		} 

		public function getobject( $_result = "" ) {
				if ( $_result == "" ) {
						$_result = $this -> sqlres;
				} 
				if ( !$_result ) {
						return false;
				} 
				$_row = $this -> db -> fetcharray( $_result );
				if ( !$_row ) {
						return false;
				} 
				$_dbrowobj = new saxueobjectdata();
				$_dbrowobj -> setvars( $_row );
				return $_dbrowobj;
		} 

		public function getrow( $_result = "" ) {
				if ( $_result == "" ) {
						$_result = $this -> sqlres;
				} 
				if ( !$_result ) {
						return false;
				} 
				$_row = $this -> db -> fetcharray( $_result );
				if ( !$_row ) {
						return false;
				} 
				return $_row;
		} 

		public function getcount( $_criteria = null ) {
				if ( is_object( $_criteria ) ) {
						if ( $_criteria -> getgroupby() == "" ) {
								$_sql = "SELECT COUNT(*) FROM " . $_criteria -> gettables() . " " . $_criteria -> renderwhere();
								$_nobuffer = true;
						} else {
								$_sql = "SELECT COUNT(" . $_criteria -> getgroupby() . ") FROM " . $_criteria -> gettables() . " " . $_criteria -> renderwhere() . " GROUP BY " . $_criteria -> getgroupby();
								$_nobuffer = false;
						} 
						$_result = $this -> db -> query( $_sql, 0, 0, $_nobuffer );
						if ( !$_result ) {
								return 0;
						} 
						if ( $_criteria -> getgroupby() == "" ) {
								list( $_count ) = $this -> db -> fetchrow( $_result );
						} else {
								$_count = $this -> db -> getrowsnum( $_result );
						}
						return $_count;
				} 
				return 0;
		}

		public function updatefields( $_table, $_fields, $_criteria = null ) {
				$_sql = "UPDATE " . $_table . " SET ";
				$_start = true;
				if ( is_array( $_fields ) ) {
						foreach ( $_fields as $_k => $_v ) {
								if ( !$_start ) {
										$_sql .= ", ";
								} else {
										$_start = false;
								} 
								if ( is_numeric( $_v ) ) {
										$_sql .= $_k . "=" . $this -> db -> quotestring( $_v );
								} else {
										$_sql .= $_k . "=" . $this -> db -> quotestring( $_v );
								} 
						} 
				} else {
						$_sql .= $_fields;
				} 
				if ( isset( $_criteria ) && !is_object( $_criteria ) ) {
						$_sql .= " WHERE " . $_criteria;
				} elseif ( isset( $_criteria ) && is_subclass_of( $_criteria, "criteriaelement" ) ) {
						$_sql .= " " . $_criteria -> renderwhere();
				} 
				if ( !$_result = $this -> db -> query( $_sql ) ) {
						return false;
				} 
				return true;
		} 

		public function makeupsql( $table, $prows, $mode = "INSERT", $where = "" ) {
				switch ( $mode ) {
						case "INSERT":
						case "insert":
						case "REPLACE":
						case "replace":
								$fields = "";
								$values = "";
								foreach ( $prows as $k => $v ) {
										if ( $fields != "" ) {
												$fields .= ", ";
										} 
										$fields .= "`$k`";
										if ( $values != "" ) {
												$values .= ", ";
										} 
										$values .= "'" . saxue_dbslashes( $v ) . "'";
								} 
								$sql = strtoupper( $mode ) . " INTO $table ($fields) VALUES ($values)";
								break;
						case "UPDATE":
						case "update":
								$fields = "";
								foreach ( $prows as $k => $v ) {
										if ( $fields != "" ) {
												$fields .= ", ";
										} 
										$fields .= "`$k` = '" . saxue_dbslashes( $v ) . "'";
								} 
								$sql = strtoupper( $mode ) . " $table SET $fields WHERE ";
								if ( is_array( $where ) ) {
										$limits = "";
										foreach ( $where as $k => $v ) {
												if ( $limits != "" ) {
														$limits .= " AND ";
												} 
												$limits .= "`$k` = '" . saxue_dbslashes( $v ) . "'";
										} 
										$sql .= $limits;
								} else {
										$sql .= $where;
								} 
								break;
						default:
								return $sql = "";
				} 
				return $sql;
		} 
} 

class saxueobjecthandler extends saxuequeryhandler {
		public $basename;
		public $autoid;
		public $dbname;
		public $fullname = false;

		public function saxueobjecthandler( $_db = "" ) {
				$this -> saxuequeryhandler( $_db );
		} 

		public function create( $isNew = true, $data = '' ) {
				$tmpvar = "Saxue" . ucfirst( $this -> basename );
				${$this -> basename} = new $tmpvar();
				if ( $isNew ) {
						${$this -> basename} -> setnew();
				} 
				if ( false !== $data ){
						if ( empty( $data ) ) {
								$data = $_POST;
						} elseif ( is_object( $data ) ) {
								$data = get_object_vars( $data );
						} 
						foreach( ${$this -> basename} -> vars as $key => $val ) {
								if ( isset ( $data[$key] ) ) {
										${$this -> basename} -> setvar( $key, $data[$key] );
								} 
						} 
				}
				return ${$this -> basename};
		} 

		public function get( $fieldvalue, $fieldname = "" ) {
				if ( 0 < strlen( $fieldvalue ) ) {
						if ( $fieldname == "" ) {
								$fieldname = $this -> autoid;
						} 
						$sql = "SELECT * FROM " . saxue_dbprefix( $this -> dbname, $this -> fullname ) . " WHERE " . $fieldname . "='" . saxue_dbslashes( $fieldvalue ) . "'";
						if ( !$result = $this -> db -> query( $sql, 1, 0, true ) ) {
								return false;
						} 
						$datarow = $this -> db -> fetcharray( $result );
						if ( is_array( $datarow ) ) {
							$tmpvar = "Saxue" . ucfirst( $this -> basename );
							${$this -> basename} = new $tmpvar();
							${$this -> basename} -> setvars( $datarow );
							return ${$this -> basename};
						} 
				} 
				return false;
		}

		public function insert( &$baseobj ) {
				if ( strcasecmp( get_class( $baseobj ), "saxue" . $this -> basename ) != 0 ) {
						return false;
				} 
				if ( $baseobj -> isnew() ) {
						if ( is_numeric( $baseobj -> getvar( $this -> autoid, "n" ) ) ) {
								${$this -> autoid} = intval( $baseobj -> getvar( $this -> autoid, "n" ) );
						} else {
								${$this -> autoid} = $this -> db -> genid( $this -> dbname . "_" . $this -> autoid . "_seq" );
						} 
						$sql = "INSERT INTO " . saxue_dbprefix( $this -> dbname, $this -> fullname ) . " (";
						$values = ") VALUES (";
						$start = true;
						foreach ( $baseobj -> vars as $k => $v ) {
								if ( !$start ) {
										$sql .= ", ";
										$values .= ", ";
								} else {
										$start = false;
								} 
								$sql .= $k;
								if ( $v['type'] == SAXUE_TYPE_INT ) {
										if ( $k != $this -> autoid ) {
												if ( !is_numeric( $v['value'] ) ) {
														$v['value'] = @intval( $v['value'] );
												} 
												$values .= $this -> db -> quotestring( $v['value'] );
										} else {
												$values .= ${$this -> autoid};
										} 
								} else {
										$values .= $this -> db -> quotestring( $v['value'] );
								} 
						} 
						$sql .= $values . ")";
						unset( $values );
				} else {
						$sql = "UPDATE " . saxue_dbprefix( $this -> dbname, $this -> fullname ) . " SET ";
						$start = true;
						foreach ( $baseobj -> vars as $k => $v ) {
								if ( ( $k != $this -> autoid ) && $v['isdirty'] ) {
										if ( !$start ) {
												$sql .= ", ";
										} else {
												$start = false;
										} 
										if ( $v['type'] == SAXUE_TYPE_INT ) {
												if ( !is_numeric( $v['value'] ) ) {
														$v['value'] = @intval( $v['value'] );
												} 
												$sql .= $k . "=" . $this -> db -> quotestring( $v['value'] );
										} else {
												$sql .= $k . "=" . $this -> db -> quotestring( $v['value'] );
										} 
								} 
						} 
						if ( $start ) {
								return true;
						} 
						$sql .= " WHERE " . $this -> autoid . "=" . intval( $baseobj -> vars[$this -> autoid]['value'] );
				} 
				$result = $this -> db -> query( $sql );
				if ( !$result ) {
						return false;
				} 
				if ( $baseobj -> isnew() ) {
						$baseobj -> setvar( $this -> autoid, $this -> db -> getinsertid() );
				} 
				return true;
		} 

		public function delete( $criteria = 0, $fieldname = "" ) {
				$sql = "";
				if ( is_numeric( $criteria ) ) {
						$criteria = intval( $criteria );
						if ( $fieldname == "" ) {
								$fieldname = $this -> autoid;
						}
						$sql = "DELETE FROM " . saxue_dbprefix( $this -> dbname, $this -> fullname ) . " WHERE " . $fieldname . "=" . $criteria;
				} elseif ( is_object( $criteria ) && is_subclass_of( $criteria, "criteriaelement" ) ) {
						$tmpstr = $criteria -> renderwhere();
						if ( !empty( $tmpstr ) ) {
								$sql = "DELETE FROM " . saxue_dbprefix( $this -> dbname, $this -> fullname ) . " " . $tmpstr;
						} 
				} elseif ( !empty( $criteria ) ) {
						$sql = "DELETE FROM " . saxue_dbprefix( $this -> dbname, $this -> fullname ) . " WHERE " . $criteria;
				} 
				if ( empty( $sql ) ) {
						return false;
				} 
				$result = $this -> db -> query( $sql );
				if ( !$result ) {
					return false;
				} 
				return true;
		} 

		public function queryobjects( $_criteria = null, $_nobuffer = false ) {
				$_limit = $_start = 0;
				if ( is_null( $_criteria ) ) {
						$_sql = "SELECT * FROM " . saxue_dbprefix( $this -> dbname, $this -> fullname );
				} else {
						$_sql = "SELECT " . $_criteria -> getfields() . " FROM " . saxue_dbprefix( $this -> dbname, $this -> fullname );
				}
				if ( isset( $_criteria ) && is_subclass_of( $_criteria, "criteriaelement" ) ) {
						$_sql .= " " . $_criteria -> renderwhere();
						if ( $_criteria -> getgroupby() != "" ) {
								$_sql .= " GROUP BY " . $_criteria -> getgroupby();
						} 
						if ( $_criteria -> getsort() != "" ) {
								$_sql .= " ORDER BY " . $_criteria -> getsort() . " " . $_criteria -> getorder();
						} 
						$_limit = $_criteria -> getlimit();
						$_start = $_criteria -> getstart();
				} 
				$this -> sqlres = $this -> db -> query( $_sql, $_limit, $_start, $_nobuffer );
				return $this -> sqlres;
		} 

		public function getobject( $_result = "" ) {
				if ( $_result == "" ) {
						$_result = $this -> sqlres;
				} 
				if ( !$_result ) {
						return false;
				} 
				$_tmpval = "Saxue" . ucfirst( $this -> basename );
				$_row = $this -> db -> fetcharray( $_result );
				if ( !$_row ) {
						return false;
				} 
				$_dbrowobj = new $_tmpval();
				$_dbrowobj -> setvars( $_row );
				return $_dbrowobj;
		} 

		public function getcount( $_criteria = null ) {
				$_sql = "SELECT COUNT(*) FROM " . saxue_dbprefix( $this -> dbname, $this -> fullname );
				$_nobuffer = true;
				if ( isset( $_criteria ) && is_subclass_of( $_criteria, "criteriaelement" ) ) {
						$_sql .= " " . $_criteria -> renderwhere();
						if ( $_criteria -> getgroupby() != "" ) {
								$_sql = "SELECT COUNT(" . $_criteria -> getgroupby() . ") FROM " . saxue_dbprefix( $this -> dbname, $this -> fullname ) . " " . $_criteria -> renderwhere() . " GROUP BY " . $_criteria -> getgroupby();
								$_nobuffer = false;
						} 
				} 
				$_result = $this -> db -> query( $_sql, 0, 0, $_nobuffer );
				if ( !$_result ) {
						return 0;
				} 
				if ( isset( $_criteria ) && is_subclass_of( $_criteria, "criteriaelement" ) && $_criteria -> getgroupby() != "" ) {
						$_count = $this -> db -> getrowsnum( $_result );
				} else {
						list( $_count ) = $this -> db -> fetchrow( $_result );
				}
				return $_count;
		} 

		public function updatefields( $_fields, $_criteria = null ) {
				$_sql = "UPDATE " . saxue_dbprefix( $this -> dbname, $this -> fullname ) . " SET ";
				$_start = true;
				if ( is_array( $_fields ) ) {
						foreach ( $_fields as $_k => $_v ) {
								if ( !$_start ) {
										$_sql .= ", ";
								} else {
										$_start = false;
								} 
								if ( is_numeric( $_v ) ) {
										$_sql .= $_k . "=" . $this -> db -> quotestring( $_v );
								} else {
										$_sql .= $_k . "=" . $this -> db -> quotestring( $_v );
								} 
						} 
				} else {
						$_sql .= $_fields;
				} 
				if ( isset( $_criteria ) && !is_object( $_criteria ) ) {
						$_sql .= " WHERE " . $_criteria;
				} elseif ( isset( $_criteria ) && is_subclass_of( $_criteria, "criteriaelement" ) ) {
						$_sql .= " " . $_criteria -> renderwhere();
				} 
				if ( !( $_result = $this -> db -> query( $_sql ) ) ) {
						return false;
				} 
				return true;
		} 
} 

class criteriaelement extends saxueobject {
		public $order = "ASC";
		public $sort = "";
		public $limit = 0;
		public $start = 0;
		public $groupby = "";
		public $sql = "";
		public $fields = "*";
		public $tables = "";

		public function criteriaelement() {
				$this -> saxueobject();
		} 

		public function setsql( $_sql ) {
				$this -> sql = $_sql;
		} 

		public function getsql() {
				return $this -> sql;
		} 

		public function setfields( $_fields ) {
				$this -> fields = $_fields;
		} 

		public function getfields() {
				return $this -> fields;
		} 

		public function settables( $_tables ) {
				$this -> tables = $_tables;
		} 

		public function gettables() {
				return $this -> tables;
		} 

		public function setsort( $_sort ) {
				$this -> sort = $_sort;
		} 

		public function getsort() {
				return $this -> sort;
		} 

		public function setorder( $_order ) {
				if ( "DESC" == strtoupper( $_order ) ) {
						$this -> order = "DESC";
				} else if ( "ASC" == strtoupper( $order ) ) {
						$this -> order = "ASC";
				} 
		} 

		public function getorder() {
				return $this -> order;
		} 

		public function setlimit( $_limit = 0 ) {
				if ( isset( $_limit ) && is_numeric( $_limit ) ) {
						$this -> limit = intval( $_limit );
				} else {
						$this -> limit = 1;
				} 
		} 

		public function getlimit() {
				return $this -> limit;
		} 

		public function setstart( $_start = 0 ) {
				$this -> start = intval( $_start );
		} 

		public function getstart() {
				return $this -> start;
		} 

		public function setgroupby( $_groupby ) {
				$this -> groupby = $_groupby;
		} 

		public function getgroupby() {
				return $this -> groupby;
		} 
} 

class criteriacompo extends criteriaelement {
		public $criteriaElements = array();
		public $conditions = array();

		public function criteriacompo( $_ele = null, $_condition = "AND" ) {
				if ( isset( $_ele ) && is_object( $_ele ) ) {
						$this -> add( $_ele, $_condition );
				} 
		} 

		public function add( &$_criteriaElement, $_condition = "AND" ) {
				$this -> criteriaElements[] = &$_criteriaElement;
				$this -> conditions[] = $_condition;
				return $this;
		} 

		public function render() {
				$_ret = "";
				$_count = count( $this -> criteriaElements );
				if ( 0 < $_count ) {
						$_ret = "(" . $this -> criteriaElements[0] -> render();
						for ( $_i = 1; $_i < $_count; $_i++ ) {
								$_ret .= " " . $this -> conditions[$_i] . " " . $this -> criteriaElements[$_i] -> render();
						} 
						$_ret .= ")";
				} 
				return $_ret;
		} 

		public function renderwhere() {
				$_ret = $this -> render();
				$_ret = ( $_ret != "" ? "WHERE " . $_ret : $_ret );
				return $_ret;
		} 
} 

class criteria extends criteriaelement {
		public $column;
		public $operator;
		public $value;

		public function criteria( $_column, $_value = "", $_operator = "=" ) {
				$this -> column = $_column;
				$this -> value = $_value;
				$this -> operator = $_operator;
		} 

		public function render() {
				if ( !empty( $this -> column ) ) {
						$_clause = $this -> column . " " . $this -> operator;
				} else {
						$_clause = "";
				} 
				if ( isset( $this -> value ) ) {
						if ( $this -> column == "" && $this -> operator == "" ) {
								$_clause .= " " . trim( $this -> value );
						} else if ( strtoupper( $this -> operator ) == "IN" ) {
								$_clause .= " " . $this -> value;
						} else {
								$_clause .= " '" . saxue_dbslashes( trim( $this -> value ) ) . "'";
						}
				} 
				return $_clause;
		} 

		public function renderwhere() {
				$_ret = $this -> render();
				$_ret = ( $_ret != "" ? "WHERE " . $_ret : $_ret );
				return $_ret;
		} 
} 
