<?php
/**
 * N.U.C.O.K.E. Main central development core
 * © Hsilamot 2011
 * developed by Hidalgo Rionda
 * This Core is designed to be used as a full Apache Alias
 * this means / should redirect to /path/to/script/api.php
 *
 * i'm making this collection of classes and examples to make it simple for people to create
 * advanced PHP sites, since most of us want friendly URL's and to avoid copy/paste of our code
 * i'm trying to create a set of standard libraries which can be used to create powerful sites.
 *
 * this is the first release of NuCoKe collection
 *
 * +----------------------------------------------------------------------+
 * |                       N.U.C.O.K.E. v 2.0.1763                        |
 * |             released under Creative Commons BY-NC-SA 3.0             |
 * |          http://creativecommons.org/licenses/by-nc-sa/3.0/           |
 * +----------------------------------------------------------------------+
 *
 * +----------------------------------------------------------------------+
 * |                              changelog                               |
 * | v1.0.1 (Hsilamot) first release                                      |
 * | v2.0.1649 (Hsilamot) second release                                  |
 * +----------------------------------------------------------------------+
 *
 * remember ALL SQL sentences must be formed with single quote characters ->'<- NOT double ->"<-
 * THIS IS PRE-BETA, it is not complete yet.
 * Also remember to vaccine all customer SQL sentences
 *
 * @access public
 * @author Hsilamot <php@hsilamot.com>
 * @license http://creativecommons.org/licenses/by-nc-sa/3.0/
 * @version 2.0.1763
 */
if (get_magic_quotes_gpc()) {
	/* this will remove Magic Quotes */
	$process = array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST);
	while (list($key, $val) = each($process)) {
		foreach ($val as $k => $v) {
			unset($process[$key][$k]);
			if (is_array($v)) {
				$process[$key][stripslashes($k)] = $v;
				$process[] = &$process[$key][stripslashes($k)];
			} else {
				$process[$key][stripslashes($k)] = stripslashes($v);
			}
		}
	}
	unset($process);
}
class NuCoKe {
	/**
	 * database pointers
	 * @access protected
	 * @var array pointers to databases
	 */
	protected $database=array();
	/**
	 * database configurations
	 * @access public
	 * @var array data for the database configurations
	 */
	private $db=array();
	/**
	 * main config array containing all the configuration of the class
	 * @access protected
	 * @var array config variables
	 */
	protected $config=array();
	/**
	 * error log
	 * @access public
	 * @var array data for the errors
	 */
	private $errors=array();
	/**
	 * integer containing the http response code
	 * @access public
	 * @var int response code for http request
	 */
	public $http_code=200;
	/**
	 * this array contains the cookies to be sent to the browser, once sent they can be modified but will not be resent
	 * @access private
	 * @var array cookies
	 */
	private $http_cookies=array();
	/**
	 * this array contains the headers to be sent to the browser, once sent they can be modified but will not be resent
	 * @access private
	 * @var array headers to return to the browser
	 */
	private $http_headers=array();
	/**
	 * is class initialized
	 * @access private
	 * @var bool is class initialized
	 */
	private $init=false;
	/**
	 * The actual full URL of the user
	 * @access public
	 * @var string full URL
	 */
	public $url;
	/**
	 * The UserAgent of the class
	 * @access protected
	 * @var array data of the user agent
	 */
	protected $user_agent=array();
	/**
	 * for multiple purpose use, will save and reload
	 * @access protected
	 * @var array multiple purpose use
	 */
	protected $var=array();
	/**
	 * will initialize the class
	 * @access public
	 * @version 1.0.79
	 * @param array $config array containing any extra configuration from the user
	 * @param object $nucoke previously initialized nucoke
	 * @return boolean if success
	 */
	public function __construct($config=array(),$nucoke=null) {
		if (is_object($nucoke)) {
			$version = $nucoke->version();
			if ($version[2]>1664) {
				$inherit = $nucoke->inherit();
				$this->database = $inherit['database'];
				$this->db = $inherit['db'];
				$this->config = $inherit['config'];
				$this->http_code = $inherit['http_code'];
				$this->http_headers = $inherit['http_headers'];
				$this->init = $inherit['init'];
				$this->url = $inherit['url'];
				$this->init = $inherit['init'];
				$this->user_agent = $inherit['user_agent'];
			}
		}
		if ($this->init==false) {
		/* we set the error handler */
		set_error_handler(array($this, 'error_handler'));
		error_reporting(-1);
		/* we will now set the default configuration */
		$this->config['start'] = microtime(true); /* time we started the class */
		$this->config['timezone'] = 'America/Mexico_City'; /* timezone we will set the PHP (http://www.php.net/manual/en/timezones.php) */
		$this->config['name'] = 'NuCoKe'; /* this is the version of the user's proyect'*/
		$this->config['version'] = '1.0.0'; /* this is the version of the user's proyect'*/
		$this->config['charset'] = 'UTF-8'; /* the Charset we will be working on */
		$this->config['path'] = getcwd(); /* the Main path we will be working on */
		$this->config['index'] = array(); /* list of indexing pages */
		$this->config['nucoke_db'] = null; /* name of the NuCoKe Database */
		$this->config['nucoke_db_default'] = null; /* name of the default database */
		$this->config['nucoke_var'] = null; /* name of the database for storing global variables */
		$this->config['nucoke_versionize'] = null; /* name of the database for storing versionize hashes */
		$version = $this->version(); $this->user_agent_add('NuCoKe v'.$version[0].'.'.$version[1]); /* will add self to the user agent string */
		/* we will parse any configuration added from user end */
		if (!is_array($config)) { $config = array(); trigger_error('NuCoKe: Unknown configuration type passed on __initialize($config)',E_USER_NOTICE); }
		foreach ($config as $name => $value) {
			switch ($name) {
				case 'timezone':
					$this->config['timezone'] = $value; break;
				case 'name':
					$this->config['name'] = $value; break;
				case 'version':
					$this->config['version'] = $value; break;
				case 'charset':
					$this->config['charset'] = $value; break;
				case 'path':
					$this->config['path'] = $value; break;
				case 'db':
					$this->config['nucoke_db'] = $value; break;
				case 'db_default':
					$this->config['nucoke_db_default'] = $value; break;
				case 'var':
					$this->config['nucoke_var'] = $value; break;
				case 'versionize':
					$this->config['nucoke_versionize'] = $value; break;
				default:
					trigger_error('NuCoKe: Unknown configuration name \''.$name.'\'',E_USER_NOTICE); break;
			}
		}
		if (!date_default_timezone_set($this->config['timezone'])) { trigger_error('TimeZone invalid!'); } /* we set the timezone */
		$this->http_header('Date',date(DATE_RFC822,time())); /* time in which the request is being served */
		$this->http_code=200; /* we got a HTTP OK code for now */
		/* we now change the work directory path */
		if (is_dir($this->config['path'])) {
			$chdir = chdir($this->config['path']);
			if (!$chdir) {
				trigger_error('NuCoKe: Could not set working directory to \''.$this->config['path'].'\'',E_USER_ERROR);
			}
		} else {
			trigger_error('NuCoKe: The directory \''.$this->config['path'].'\' does not exist, could not change work directory',E_USER_ERROR);
		}
		/* we check the URL requested from the client */
		if (isset($_SERVER['REQUEST_URI'])) { $this->url = $_SERVER['REQUEST_URI']; } else {
			if (php_sapi_name()=='cli') {
				$this->url = str_replace($this->get_path(),'',$_SERVER['PHP_SELF']);
			} else {
				$this->url = '/';
			}
		}
		$this->init=true;
		}
		return true;
	}
	/**
	 * will destroye the class
	 * @access public
	 * @version 1.0.36
	 * @return boolean if success
	 */
	public function __destruct() {
		/*
		if (count($this->errors)>0) {
			echo '<pre>';
			foreach ($this->errors as $err) {
				echo $err['file'].':'.$err['line'].'#'.$err['number'].' '.$err['string'].chr(13).chr(10);
			}
			echo '</pre>';
		}
		*/
		return true;
	}
	/**
	 * Adds database to list of databases, will replace existing ones
	 * @access public
	 * @version 1.0.40
	 * @param string $name name of the configuration
	 * @param string $host hostname of the database
	 * @param string $user username of the database
	 * @param string $pass password of the database
	 * @param string $database database name
	 * @param string $prefix prefix to queries
	 * @param string $charset charset to be used
	 * @param bool $persistent if the connection should be persistent
	 * @param integer $retries if connection is lost number of reconnection retries
	 * @param integer $wait wait in seconds between $retries
	 * @return bool return true if success
	 */
	public function db_add($name,$host,$user,$pass,$database,$prefix='',$charset='UTF8',$persistent=false,$retries=1,$wait=0) {
		$this->db[$name]['host'] = $host;
		$this->db[$name]['user'] = $user;
		$this->db[$name]['pass'] = $pass;
		$this->db[$name]['database'] = $database;
		$this->db[$name]['prefix'] = $prefix;
		$this->db[$name]['charset'] = $charset;
		$this->db[$name]['persistent'] = $persistent;
		$this->db[$name]['retries'] = $retries;
		$this->db[$name]['wait'] = $wait;
		$this->db[$name]['connected'] = false;
		$this->db[$name]['queries'] = 0;
		return true;
	}
	/**
	 * This script calls home to mantain an index of the NuCoKe installations
	 * @access public
	 * @version 1.0.1
	 * @return bool return true if success
	 */
	public function call_home() {
		if ($this->gvar('call_home')!=date('Y-m-d')) {
			
		}
		return true;
	}
	/**
	 * Handles errors
	 * @access public
	 * @version 1.0.14
	 * @return bool return true if success
	 */
	public function error_handler($errno,$errstr,$errfile,$errline) {
		$this->errors[] = array(
						'file'	=>	$errfile,
						'line'	=>	$errline,
						'number'	=>	$errno,
						'string'	=>	$errstr
						);
		echo '<br />';
		echo $errfile.':'.$errline.'#'.$errno.' '.$errstr.chr(13).chr(10);
		flush();
		return true;
	}
	/**
	 * get remote address user agent if available
	 * @access public
	 * @version 1.0.1
	 * @return string remote address
	 */
	public function get_agent() {
		if (php_sapi_name()=='cli') {
			$agent = '';
			if (isset($_SERVER['USER'])) { $agent .= $_SERVER['USER'].'@'; } else { $agent .= 'unknown@'; }
			if (isset($_SERVER['HOSTNAME'])) { $agent .= $_SERVER['HOSTNAME'].' ('; } else { $agent .= '127.0.0.1 ('; }
			if (isset($_SERVER['SSH_TTY'])) { $agent .= $_SERVER['SSH_TTY'].';'; } else { $agent .= 'unknowntty;'; }
			if (isset($_SERVER['SSH_CONNECTION'])) { $agent .= $_SERVER['SSH_CONNECTION'].')'; } else { $agent .= 'unknown)'; }
			return $agent;
		} else {
			if (isset($_SERVER['HTTP_USER_AGENT'])) {
				return $_SERVER['HTTP_USER_AGENT'];
			} else {
				return 'unknown (unknown)';
			}
		}
		return true;
	}
	/**
	 * get remote address if available, localhost on fail
	 * @access public
	 * @version 1.0.1
	 * @return string remote address
	 */
	public function get_ip() {
		if (php_sapi_name()=='cli') {
			if (isset($_SERVER['SSH_CLIENT'])) {
				$ip = explode(' ',$_SERVER['SSH_CLIENT']);
				$ip = $ip[0];
			} else {
				$ip = '127.0.0.1';
			}
		} else {
			if (isset($_SERVER['REMOTE_ADDR'])) {
				$ip = $_SERVER['REMOTE_ADDR'];
			} else {
				$ip = '127.0.0.1';
			}
		}
		return $ip;
	}
	/**
	 * returns the path value
	 * @access public
	 * @version 1.0.4
	 * @return string return the actual path value
	 */
	public function get_path() {
		return $this->config['path'];
	}
	/**
	 * returns value of the variable
	 * @access public
	 * @version 1.0.24
	 * @param $variable string Variable Name
	 * @param $value string Variable value (if setting variable)
	 * @return string variable value
	 */
	public function gvar($variable,$value=null) {
		if (!$this->config['nucoke_var']) { return false; }
		$sql = 'SELECT * FROM `'.$this->config['nucoke_var'].'` WHERE `var` = 0x'.bin2hex($variable);
		$var = $this->sql($sql,$this->config['nucoke_db']);
		if (count($var)>0) {
			$var = $var[0];
			if ($value!==null) {
				$sql = 'UPDATE `'.$this->config['nucoke_var'].'` SET `val` = 0x'.bin2hex(serialize($value)).' WHERE `var` = 0x'.bin2hex($var['var']).' LIMIT 1';
				$this->sql($sql,$this->config['nucoke_db']);
				$sql = 'UPDATE `'.$this->config['nucoke_var'].'` SET `write` = (`write`+1) WHERE `var` = 0x'.bin2hex($var['var']).' LIMIT 1';
				$this->sql($sql,$this->config['nucoke_db']);
				return $value;
			} else {
				$sql = 'UPDATE `'.$this->config['nucoke_var'].'` SET `read` = (`read`+1) WHERE `var` = 0x'.bin2hex($var['var']).' LIMIT 1';
				$this->sql($sql,$this->config['nucoke_db']);
				return unserialize($var['val']);
			}
		} else {
			if ($value===false) {
				return false;
			}
			$sql = 'INSERT INTO `'.$this->config['nucoke_var'].'` (`var`,`val`,`write`) VALUES (0x'.bin2hex($variable).',0x'.bin2hex(serialize($value)).',0)';
			$this->sql($sql,$this->config['nucoke_db']);
			return $value;
		}
	}
	/**
	 * will set a cookie, returns false if headers have been sent
	 * @access public
	 * @version 1.0.2
	 * @param string $name name of the cookie
	 * @param string $value value of the cookie
	 * @param string $expires expiration of the cookie in seconds
	 * @param string $path path to set the cookie
	 * @param string $domain domain to set the cookie for
	 * @return bool return true if headers haven't been sent already
	 */
	public function http_cookie($name,$value,$expires=86400,$path=false,$domain=false) {
		if (!headers_sent()) {
			$this->http_cookies[$name] = array('name'	=>	$name,
										'value'	=>	$value,
										'expires'	=>	$expires,
										'path'	=>	$path,
										'domain'	=>	$domain
										);
			return true;
		} else {
			return false;
		}
	}
	/**
	 * will set a header, return false if the headers have been already sent
	 * @access public
	 * @version 1.0.3
	 * @param string $header the name of the header
	 * @param string $value value of the header
	 * @return bool return true if headers haven't been sent already
	 */
	public function http_header($header,$value) {
		if (!headers_sent()) {
			$this->http_headers[$header] = $value;
			return true;
		} else {
			return false;
		}
	}
	/**
	 * will proceed to the set of HTTP headers
	 * @access public
	 * @version 1.0.24
	 * @return bool return true if headers have been sent
	 */
	public function http_set_headers() {
		if (!headers_sent()) {
			switch ($this->http_code) {
				case 200:
					header('HTTP/1.1 200 OK',true,200); header('status: 200 OK',true,200); break;
				case 206:
					header('HTTP/1.1 206 Partial content',true,206); header('status: 206 Partial content',true,206); break;
				case 302:
					header('HTTP/1.1 302 Found',true,302); header('status: 302 Found',true,302); break;
				case 304:
					header('HTTP/1.1 304 Not Modified',true,304); header('status: 304 Not Modified',true,304); break;
				case 401:
					header('HTTP/1.1 401 Unauthorized',true,401); header('status: 401 Unauthorized',true,401); break;
				case 403:
					header('HTTP/1.1 403 Forbidden',true,403); header('status: 403 Forbidden',true,403); break;
				case 404:
					header('HTTP/1.1 404 Not Found',true,404); header('status: 404 Not Found',true,404); break;
				case 405:
					header('HTTP/1.1 405 Method Not Allowed',true,405); header('status: 405 Method Not Allowed',true,405); break;
				default:
					header('HTTP/1.1 200 OK',true,200); header('status: 200 OK',true,200); $this->http_code = 200; break;
			}
			foreach ($this->http_headers as $header => $value) {
				header($header.': '.$value,true,$this->http_code);
			}
			foreach ($this->http_cookies as $cookie => $value) {
				$header = 'Set-Cookie: ';
				$header .= $value['name'];
				$header .= '=';
				$header .= $value['value'];
				$header .= '; ';
				$header .= 'expires='.date(DATE_RFC822,(time()+$value['expires']));
				$header .= ';';
				if (strlen($value['path'])>0) {
					$header .= ' path='.$value['path'].';';
				}
				if (strlen($value['domain'])>0) {
					$header .= ' domain='.$value['domain'].';';
				}
				header($header,false);
			}
			return true;
		} else {
			return false;
		}
	}
	/**
	 * will return all neccesary values to be a inherited NuCoKe class
	 * @access public
	 * @version 1.0.40
	 * @return array values to inherit
	 */
	public function inherit() {
		$return['db'] = $this->db;
		$return['database'] = $this->database;
		$return['config'] = $this->config;
		$return['http_code'] = $this->http_code;
		$return['http_headers'] = $this->http_headers;
		$return['init'] = $this->init;
		$return['url'] = $this->url;
		$return['user_agent'] = $this->user_agent;
		return $return;
	}
	/**
	 * will decode a 4-byte binary ip into normal string
	 * @access public
	 * @version 1.0.18
	 * @param binary $ip 4-byte IP
	 * @return string return full decoded ip x.x.x.x format
	 */
	public function ip_decode($ip) {
		$ip_a = ord(substr($ip,0,1));
		$ip_b = ord(substr($ip,1,1));
		$ip_c = ord(substr($ip,2,1));
		$ip_d = ord(substr($ip,3,1));
		return $ip_a.'.'.$ip_b.'.'.$ip_c.'.'.$ip_d;
	}
	/**
	 * will encode a string IP into a hexadecimal string
	 * @access public
	 * @version 1.0.5
	 * @param string $ip normal x.x.x.x ip
	 * @return string return 8 0 to F hexadecimal string
	 */
	public function ip_encode($ip) {
		$ip_exploded = explode('.', $ip);
		$ip_a = dechex($ip_exploded[0]);
		while (strlen($ip_a)<2) { $ip_a = '0'.$ip_a; }
		$ip_b = dechex($ip_exploded[1]);
		while (strlen($ip_b)<2) { $ip_b = '0'.$ip_b; }
		$ip_c = dechex($ip_exploded[2]);
		while (strlen($ip_c)<2) { $ip_c = '0'.$ip_c; }
		$ip_d = dechex($ip_exploded[3]);
		while (strlen($ip_d)<2) { $ip_d = '0'.$ip_d; }
		return $ip_a.$ip_b.$ip_c.$ip_d;
	}
	/**
	 * returns the path value
	 * @access public
	 * @version 1.0.4
	 * @return string return the actual path value
	 */
	public function path_get() {
		return $this->config['path'];
	}
	/**
	 * will stop output and returns normal HTML output to redirect user requested URL
	 * @access public
	 * @version 1.0.53
	 * @param string $url url to redirect to
	 * @return string return HTML to redirect
	 */
	public function redirect($url) {
		if (substr_count($url, '://') == 0) {
			if (substr($url,0,1)!='/') { $url = '/'.$url; }
			if (substr($_SERVER['HTTP_HOST'], 0, 3) == 'ssl') {
				$goto = 'https://'.$_SERVER['HTTP_HOST'].$url;
			}
			else {
				$goto = 'http://'.$_SERVER['HTTP_HOST'].$url;
			}
		}
		else { $goto = $url; }
		header('location: '.$goto,true,302);
		$html = 	'<h1>'.$_SERVER['SERVER_PROTOCOL'].' 302 Found</h1>'.chr(13).chr(10).
				'<p>The page you have requested has been found: '.$_SERVER['SERVER_PROTOCOL'].' (302)</p>'.chr(13).chr(10).
				'<script type="text/javascript">document.location.href="'.$goto.'"</script>'.chr(13).chr(10).
				'<p>if you can see this message please accept our apologies and click next link: <a href="'.$goto.'">'.$goto.'</a></p>';
		$this->http_code=302;
		ob_clean();
		echo $html;
		die();
	}
	/**
	 * will force page to refresh
	 * @access public
	 * @version 1.0.18
	 * @return bool success
	 */
	public function refresh() {
		global $_SERVER;
		$url = $_SERVER['REQUEST_URI'];
		if (substr_count($url, '://') == 0) {
			if (substr($url,0,1)!='/') { $url = '/'.$url; }
			if (substr($_SERVER['HTTP_HOST'], 0, 3) == 'ssl') {
				$goto = 'https://'.$_SERVER['HTTP_HOST'].$url;
			}
			else {
				$goto = 'http://'.$_SERVER['HTTP_HOST'].$url;
			}
		}
		else { $goto = $url; }
		header('Pragma: no-cache');
		header('cache-Control: no-cache, must-revalidate');
		header('Expires: Sat, 1 Jan 2000 00:00:00 GMT');
		header('location: '.$goto,true,302);
		$html = 	'<h1>'.$_SERVER['SERVER_PROTOCOL'].' 302 Found</h1>'.chr(13).chr(10).
				'<p>The page you have requested has been found: '.$_SERVER['SERVER_PROTOCOL'].' (302)</p>'.chr(13).chr(10).
				'<script type="text/javascript">document.location.href="'.$goto.'"</script>'.chr(13).chr(10).
				'<p>if you can see this message please accept our apologies and click next link: <a href="'.$goto.'">'.$goto.'</a></p>';
		$this->http_code=302;
		echo chr(13).chr(10).$html;
		die(); 
	}
	/**
	 * will convert a decimal number to a hexadecimal representation for SQL insertion
	 * @access public
	 * @version 1.0.1
	 * @param string $string representation of the string
	 * @return string with hexadecimal representation
	 */
	public function sql_dechex($value) {
		return '0x'.dechex(intval($value));
	}
	/**
	 * will $query the $database
	 * @access public
	 * @version 1.0.42
	 * @param string $query query to execute
	 * @param string $database name of database to use
	 * @return array with the result of the query
	 */
	public function sql($query,$database=null) {
		/* if $database is empty set to default */
		if (strlen($database)<1) { $database=$this->config['nucoke_db_default']; }
		/* is the database name defined in the configuration? */
		if (!$this->db[$database]) {
			/* return error of no database defined */
			trigger_error('The database \''.$database.'\' is not configured',512);
			return false;
		} else {
			/* if the connection is suposed to be active we ping it */
			if ($this->db[$database]['connected']) {
				if (!mysql_ping($this->database[$database])) {
					/* the connection has been lost */
					$this->db[$database]['connected'] = false;
				}
			}
			/* how many retries we have? */
			$retry = 0;
			/* if the connection is not active */
			while (!$this->db[$database]['connected'] && $retry < $this->db[$database]['retries']) {
				if ($this->db[$database]['persistent']) {
					$this->database[$database] = mysql_pconnect($this->db[$database]['host'], $this->db[$database]['user'], $this->db[$database]['pass']);
				} else {
					$this->database[$database] = mysql_connect($this->db[$database]['host'], $this->db[$database]['user'], $this->db[$database]['pass']);
				}
				if ($this->database[$database]) {
					$selectresult = mysql_selectdb($this->db[$database]['database'],$this->database[$database]);
					if ($selectresult) {
						$setcharsetresult = mysql_set_charset($this->db[$database]['charset'],$this->database[$database]);
						if ($setcharsetresult) {
							mysql_query('SET SESSION character_set_results = \''.$this->db[$database]['charset'].'\'',$this->database[$database]);
							mysql_query('SET SESSION character_set_client = \''.$this->db[$database]['charset'].'\'',$this->database[$database]);
							$this->db[$database]['connected'] = true;
							/* the connection was successful */
						} else {
							// unknown error setting the charset
							trigger_error('NuCoKe: Unknown error setting charset \''.$this->db[$database]['charset'].'\' ('.$database.':'.$this->db[$database]['user'].'@'.$this->db[$database]['host'].')',E_USER_NOTICE);
							sleep($this->db[$database]['wait']);
						}
					} else {
						// unknown error selecting the database
						trigger_error('NuCoKe: Unknown error selecting database \''.$this->database[$database].'\' ('.$database.':'.$this->db[$database]['user'].'@'.$this->db[$database]['host'].')',E_USER_NOTICE);
						sleep($this->db[$database]['wait']);
					}
				} else {
					// unknown error creating the connection
					trigger_error('NuCoKe: error connecting database ('.$database.':'.$this->db[$database]['user'].'@'.$this->db[$database]['host'].')',E_USER_NOTICE);
					sleep($this->db[$database]['wait']);
				}
				$retry++;
			}
			/* if the connection active */
			if ($this->db[$database]['connected']) {
				$queryresult = mysql_query($query,$this->database[$database]);
				$this->db[$database]['queries']++;
				if ($queryresult) {
					$result = array();
					if (substr($query,0,6)!='UPDATE' && substr($query,0,6)!='INSERT' && substr($query,0,7)!='REPLACE' && substr($query,0,6)!='CREATE' && substr($query,0,6)!='DELETE') {
						while ($row = mysql_fetch_assoc($queryresult)) {
							$result[] = $row;
						}
					}
					if (substr($query,0,6)=='CREATE') {
						var_dump(mysql_info($this->database[$database]));
					}
					if (substr($query,0,6)=='INSERT'||substr($query,0,7)=='REPLACE') {
						$result = mysql_insert_id($this->database[$database]);
					}
					return $result;
				} else {
					/* malformed query */
					trigger_error('NuCoKe->SQL: '.mysql_error($this->database[$database]),E_USER_NOTICE);
					return false;
				}
			} else {
				/* if the connection is not active */
				return false;
			}
		}
	}
	/**
	 * will convert a text to a hexadecimal representation for SQL insertion
	 * @access public
	 * @version 1.0.1
	 * @param string $string representation of the string
	 * @return string with hexadecimal representation or null if empty
	 */
	public function sql_texthex($string) {
		if (strlen($string)>0) {
			return '0x'.bin2hex($string);
		} else {
			return 'NULL';
		}
	}
	/**
	 * will kill anything that can destroy our precious SQL sentences
	 * @access public
	 * @version 1.0.4
	 * @param string $string part of the query to vaccine
	 * @return string with vaccioned string
	 */
	public function sql_vaccine($string) {
		$end = str_replace(chr(92).chr(39),chr(92).chr(92).chr(39),$string);
		$end = str_replace(chr(39),chr(92).chr(39),$end);
		return $end;
	}
	/**
	 * checks table and create it if does n ot exists, also modifies it into the desired configuration DEPRECEATED
	 * @access public
	 * @version 1.0.23
	 * @param string $table name of the table to check
	 * @param string $dbname name of the database to check on
	 * @return bool if success
	 */
	protected function table($table,$dbname) {
		$result = $this->sql('SHOW TABLES',$dbname);
		$found = false;
		foreach ($result as $tables) {
			foreach ($tables as $tabl) {
				if ($tabl == $table) {
					$found = true;
				}
			}
		}
	}
	/**
	 * returns user agent string
	 * @access public
	 * @version 2.0.56
	 * @return string user agent
	 */
	public function user_agent() {
		$agent = $this->config['name'].' (';
		$ya = false;
		foreach ($this->user_agent as $string) {
			if ($ya) { $agent .= '; '; }
			$agent .= $string;
			$ya = true;
		}
		$agent .= ')';
		return $agent;
	}
	/**
	 * will add an app to the user agent
	 * @access protected
	 * @version 2.0.0
	 * @param string $text text to add to the user agent string
	 * @return bool if added correctly
	 */
	protected function user_agent_add($text) {
		$toadd = str_replace('(',null,$text);
		$toadd = str_replace(')',null,$toadd);
		$toadd = str_replace(';',null,$toadd);
		$this->user_agent[] = $toadd;
		return true;
	}
	/**
	 * uuid verification (RFC 4211)
	 * @param	uuid $uuid the UUID
	 * @version 1.0.0
	 */
	public function uuid_valid($uuid) {
		return preg_match('/^\{?[0-9a-f]{8}\-?[0-9a-f]{4}\-?[0-9a-f]{4}\-?[0-9a-f]{4}\-?[0-9a-f]{12}\}?$/i', $uuid)===1;
	}
	/**
	 * uuid v3 generator (RFC 4211)
	 * @param	uuid $namespace a valid UUID
	 * @param	string $name name to get UUID from
	 * @version 1.0.0
	 */
	public function uuid_v3($namespace,$name) {
		if (!$this->uuid_valid($namespace)) { return false; }
		$namespace_hex = str_replace(array('-','{','}'), '', $namespace);
		$namespace_bin = '';
		for ($i=0;$i<strlen($namespace_hex);$i+=2) {
			$namespace_bin .= chr(hexdec($namespace_hex[$i].$namespace_hex[$i+1]));
		}
		$hash = md5($namespace_bin.$name);
		$uuid = sprintf('%08s-%04s-%04x-%04x-%12s',substr($hash,0,8),substr($hash,8,4),(hexdec(substr($hash,12,4))&0x0fff)|0x3000,(hexdec(substr($hash,16,4))&0x3fff)|0x8000,substr($hash,20,12));
		return $uuid;
	}
	/**
	 * uuid v4 generator (RFC 4211)
	 * @param	uuid $namespace a valid UUID
	 * @param	string $name name to get UUID from
	 * @version 1.0.4
	 */
	public function uuid_v4($namespace,$name) {
		return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',mt_rand(0,0xffff),mt_rand(0,0xffff),mt_rand(0,0xffff),mt_rand(0,0x0fff)|0x4000,mt_rand(0,0x3fff)|0x8000,mt_rand(0,0xffff),mt_rand(0,0xffff),mt_rand(0,0xffff));
	}
	/**
	 * uuid v5 generator (RFC 4211)
	 * @param	uuid $namespace a valid UUID
	 * @param	string $name name to get UUID from
	 * @version 1.0.3
	 */
	public function uuid_v5($namespace,$name) {
		if (!$this->uuid_valid($namespace)) { return false; }
		$namespace_hex = str_replace(array('-','{','}'), '', $namespace);
		$namespace_bin = '';
		for ($i=0;$i<strlen($namespace_hex);$i+=2) {
			$namespace_bin .= chr(hexdec($namespace_hex[$i].$namespace_hex[$i+1]));
		}
		$hash = sha1($namespace_bin.$name);
		$uuid = sprintf('%08s-%04s-%04x-%04x-%12s',substr($hash,0,8),substr($hash,8,4),(hexdec(substr($hash,12,4))&0x0fff)|0x5000,(hexdec(substr($hash,16,4))&0x3fff)|0x8000,substr($hash,20,12));
		return $uuid;
	}
	/**
	 * will return the version of the class in Mayor, Minor and Release
	 * @access public
	 * @version 1.0.85
	 * @return array ( main, minor, release )
	 */
	public function version() {
		return array( 2, 0, 1763 );
	}
	/**
	 * this function is capable of reading a file, determine the version of the functions inside it
	 * and assign versions, general recommendation is having the file well commented and only functions on it
	 * tested only on the NuCoKe cores, in simple mode the script replaces only the first @version it encounters
	 * @access public
	 * @version 1.0.22
	 * @param string path to the file to check version
	 * @param bool if we should versionize only for the global file
	 * @param bool if we should write version info into the file
	 * @return true if success
	 */
	public function versionize($file,$simple=true,$write=false) {
		if (!is_file($this->get_path().$file)) {
			trigger_error('File does not Exist: '.$file,E_USER_WARNING);
			return false;
		}
		if ($this->config['nucoke_versionize']!=null) {
			$sql = 'SELECT * FROM `'.$this->config['nucoke_versionize'].'` WHERE `file` = '.$this->sql_texthex($file);
			$version = $this->sql($sql);
			if (count($version)>0) {
				$version = unserialize($version[0]['version']);
			} else {
				$version = array();
			}
		}
		else {
			if (!is_file($this->get_path().$file.'.version')) {
				$version = array();
			} else {
				$version = unserialize(file_get_contents($this->get_path().$file.'.version'));
			}
		}
		$file_check = file_get_contents($this->get_path().$file);
		if ($simple) {
			$process = $file_check;
			$process = explode(chr(10),$process);
			$continuar = true;
			$found = false;
			$f_version = false;
			$f_version_line = 0;
			foreach ($process as $number => $line) {
				if ($continuar) {
					if (!$found) {
						$search = strpos($process[$number],'/*');
						if ($search!==false) {
							$found = true;
						}
					}
					if ($found) {
						$search = strpos($process[$number],'*/');
						if ($search!==false) { $continuar = false; }
						$search = strpos($process[$number],'@version');
						if ($search!==false) {
							$f_version = substr($process[$number],($search+9));
							$f_version = explode('.',$f_version);
							$f_version[0] = intval($f_version[0]); $f_version[1] = intval($f_version[1]); $f_version[2] = intval($f_version[2]);
							$f_version_line = $number;
							$continua = false;
						}
					}
				}
			}
			if (!isset($version['version'])) {
				if ($f_version) {
					$version['version'] = $f_version;
				} else {
					$version['version'] = array(1,0,0);
				}
				$version['sha1'] = 'INITIALIZED';
			}
			if ($version['sha1'] != sha1($file_check)) {
				$version['version'][2]++;
				$process[$f_version_line] = str_replace($f_version[0].'.'.$f_version[1].'.'.$f_version[2],$version['version'][0].'.'.$version['version'][1].'.'.$version['version'][2],$process[$f_version_line]);
				$version['sha1'] = sha1($file_check);
				if ($write) {
					$file_check = implode(chr(10),$process);
					$version['sha1'] = sha1($file_check);
					file_put_contents($this->get_path().$file, $file_check);
				}
			}
		} else {
			if (!isset($version['version'])) {
				$process = $file_check;
				$search = strpos($process,'function version');
				$process = substr($process,$search);
				$search = strpos($process,'array(');
				$process = substr($process,($search)+6);
				$search = strpos($process,')');
				$process = substr($process,0,$search);
				$process = str_replace(chr(32),null,$process);
				$process = explode(',',$process);
				$version['version'] = $process;
				if (count($version['version'])!=3) {
					$version['version'] = array(1,0,0);
				}
				$version['version'][0] = intval($version['version'][0]);
				$version['version'][1] = intval($version['version'][1]);
				$version['version'][2] = intval($version['version'][2]);
				$version['sha1'] = 'INITIALIZED';
			}
			if ($version['sha1'] != sha1($file_check)) {
				$process = $file_check;
				$process = explode(chr(10),$process);
				foreach ($process as $number => $line) {
					$search = strpos($line,'function');
					if ($search!==false) {
						$resta = 1;
						$search = strpos($process[($number-$resta)],'*/');
						if ($search!==false) {
							$continua = true;
							$f_version = false;
							$f_version_line = 0;
							$limite=5000;
							while ($continua) {
								$search = strpos($process[($number-$resta)],'/*');
								if ($search!==false) { $continua = false; }
								$search = strpos($process[($number-$resta)],'@version');
								if ($search!==false) {
									$f_version = substr($process[($number-$resta)],($search+9));
									$f_version = explode('.',$f_version);
									$f_version_line = ($number-$resta);
									$f_version[0] = intval($f_version[0]); $f_version[1] = intval($f_version[1]); $f_version[2] = intval($f_version[2]);
									$continua = false;
								}
								$resta++;
								$limite--;
								if ($limite<1) {$continua=false;}
							}
							if ($f_version) {
								$continua = true;
								$funcion = 0;
								$brackets = 0;
								$sha1 = '';
								$limite=5000;
								while ($continua) {
									$sha1 .= $process[($number+$funcion)].chr(10);
									$procesa = $process[($number+$funcion)];
									while (strlen($procesa)>0) {
										if (ord(substr($procesa,0,1))==123) { $brackets++; }
										if (ord(substr($procesa,0,1))==125) { $brackets--; }
										$procesa = substr($procesa,1);
									}
									if ($brackets<1) {$continua=false;}
									$limite--;
									if ($limite<1) {$continua=false;}
									$funcion++;
								}
								$name = substr($process[($number)],(strpos($process[($number)],'function')+9));
								$name = substr($name,0,strpos($name,'('));
								$name = 'f_'.$name;
								if (isset($version[$name])) {
									if ($version[$name]['sha1'] != sha1($sha1)) {
										$version[$name]['version'][2]++;
										$process[$f_version_line] = str_replace($f_version[0].'.'.$f_version[1].'.'.$f_version[2],$version[$name]['version'][0].'.'.$version[$name]['version'][1].'.'.$version[$name]['version'][2],$process[$f_version_line]);
									}
								} else {
									$version[$name]['version'] = $f_version;
									$version[$name]['sha1'] = sha1($sha1);
								}
							}
						}
					}
				}
				$version['version'][2]++;
				$version['sha1'] = sha1($file_check);
				if ($write) {
					$file_check = implode(chr(10),$process);
					$process = $file_check;
					$search = strpos($process,'function version');
					$process = substr($process,$search);
					$search = strpos($process,'array(');
					$process = substr($process,($search)+6);
					$search = strpos($process,')');
					$process = substr($process,0,$search);
					$process = str_replace(chr(32),null,$process);
					$process = explode(',',$process);
					$file_check = str_replace($process[0].', '.$process[1].', '.$process[2],$version['version'][0].', '.$version['version'][1].', '.$version['version'][2],$file_check);
					$file_check = str_replace($process[0].'.'.$process[1].'.'.$process[2],$version['version'][0].'.'.$version['version'][1].'.'.$version['version'][2],$file_check);
					$version['sha1'] = sha1($file_check);
					file_put_contents($this->get_path().$file, $file_check);
				}
			}
		}
		if ($this->config['nucoke_versionize']!=null) {
			$sql = 'REPLACE INTO `'.$this->config['nucoke_versionize'].'` (`file`,`version`) VALUES ('.$this->sql_texthex($file).','.$this->sql_texthex(serialize($version)).')';
			$this->sql($sql);
		}
		else {
			file_put_contents($this->get_path().$file.'.version',serialize($version));
		}
	}
}
?>
