<?php 


/** 
***************************************************
*欢迎使用免费版SiteTeam企业建站软件！
*这是一个专业为搜索引擎营销而设计的，极稳定、极易维护的建站软件！
*官方客服：help@php.net.cn
*官方下载网址：http://www.SiteTeam.cn 
***************************************************
**/




 class txtSQL { var $_STRICT = TRUE; var $_LIBPATH = NULL; var $_USER = NULL; var $_PASS = NULL; var $_CACHE = array(); var $_SELECTEDDB = NULL; var $_QUERYCOUNT = 0; function txtSQL ($path='./data') { $this->_LIBPATH = $path; return TRUE; } function connect ($user, $pass) { if ( !is_dir($this->_LIBPATH) ) { $this->_error(E_USER_ERROR, 'Invalid data directory specified'); } $this->_query = new txtSQLCore; $this->_query->_LIBPATH = $this->_LIBPATH; if ( ($DATA = $this->_readFile("$this->_LIBPATH/txtsql/txtsql.MYI")) === FALSE ) { $this->_error(E_USER_WARNING, 'Database file is corrupted!'); return FALSE; } $this->_data = $DATA; if ( !isset($DATA[strtolower($user)]) || $DATA[strtolower($user)] != md5($pass) ) { $this->_error(E_USER_NOTICE, 'Access denied for user \''.$user.'\' (using password: '.(!empty($pass)?'yes':'no').')'); return FALSE; } $this->_USER = $user; $this->_PASS = $pass; return TRUE; } function disconnect () { if( !$this->_isconnected() ) { $this->_error(E_USER_NOTICE, 'Can only disconnect when connected!'); return FALSE; } unset($this->_USER, $this->_PASS, $this->_query); return TRUE; } function select ($arguments) { $this->_validate($arguments); $this->_QUERYCOUNT++; return $this->_query->select($arguments); } function insert ($arguments) { $this->_validate($arguments); $this->_QUERYCOUNT++; return $this->_query->insert($arguments); } function update ($arguments) { $this->_validate($arguments); $this->_QUERYCOUNT++; return $this->_query->update($arguments); } function delete ($arguments) { $this->_validate($arguments); $this->_QUERYCOUNT++; return $this->_query->delete($arguments); } function showdbs () { $this->_validate(array()); $this->_QUERYCOUNT++; return $this->_query->showdatabases(); } function createdb ($arguments) { $this->_validate($arguments); $this->_QUERYCOUNT++; return $this->_query->createdatabase($arguments); } function dropdb ($arguments) { $this->_validate($arguments); $this->_QUERYCOUNT++; return $this->_query->dropdatabase($arguments); } function renamedb ($arguments) { $this->_validate($arguments); $this->_QUERYCOUNT++; return $this->_query->renamedatabase($arguments); } function showtables ($arguments) { $this->_validate($arguments); $this->_QUERYCOUNT++; return $this->_query->showtables($arguments); } function createtable ($arguments) { $this->_validate($arguments); $this->_QUERYCOUNT++; return $this->_query->createtable($arguments); } function droptable ($arguments) { $this->_validate($arguments); $this->_QUERYCOUNT++; return $this->_query->droptable($arguments); } function altertable ($arguments) { $this->_validate($arguments); $this->_QUERYCOUNT++; return $this->_query->altertable($arguments); } function describe ($arguments) { $this->_validate($arguments); $this->_QUERYCOUNT++; return $this->_query->describe($arguments); } function _validate ($arguments) { if ( !$this->_isconnected() ) { $this->_error(E_USER_NOTICE, 'Can only perform queries when connected!'); return FALSE; } if ( !empty($arguments) && !is_array($arguments) ) { $this->_error(E_USER_ERROR, 'txtSQL can only accept arguments in an array'); } return TRUE; } function execute ($action, $arguments = NULL) { if ( !$this->_isconnected() ) { $this->_error(E_USER_NOTICE, 'Can only perform queries when connected!'); return FALSE; } if ( empty($action) ) { $this->_error(E_USER_NOTICE, 'You have an error in your txtSQL query'); return FALSE; } if ( !empty($arguments) && !is_array($arguments) ) { $this->_error(E_USER_ERROR, 'txtSQL Can only accept arguments in an array'); } switch ( strtolower($action) ) { case 'show databases': $results = $this->_query->showdatabases(); break; case 'create database': $results = $this->_query->createdatabase($arguments); break; case 'drop database': $results = $this->_query->dropdatabase($arguments); break; case 'rename database': $results = $this->_query->renamedatabase($arguments); break; case 'show tables': $results = $this->_query->showtables($arguments); break; case 'create table': $results = $this->_query->createtable($arguments); break; case 'drop table': $results = $this->_query->droptable($arguments); break; case 'alter table': $results = $this->_query->altertable($arguments); break; case 'describe': $results = $this->_query->describe($arguments); break; case 'select': $results = $this->_query->select($arguments); break; case 'insert': $results = $this->_query->insert($arguments); break; case 'update': $results = $this->_query->update($arguments); break; case 'delete': $results = $this->_query->delete($arguments); break; default: $this->_error(E_USER_NOTICE, 'Unknown action: '.$action); return FALSE; } $this->_QUERYCOUNT++; return isset($results) ? $results : ''; } function strict ($strict = FALSE) { $strict = (bool) $strict; $this->_STRICT = $strict; if ( $this->_isconnected() ) { $this->_query->strict($strict); } return TRUE; } function grant_permissions($action, $user, $pass = NULL, $pass1 = NULL) { if ( !$this->_isconnected() ) { $this->_error(E_USER_NOTICE, 'Not connected'); return FALSE; } if ( !is_string($action) || !is_string($user) || (!empty($pass) && !is_string($pass)) || (!empty($pass1) && !is_string($pass1)) ) { $this->_error(E_USER_NOTICE, 'The arguments must be a string'); return FALSE; } if ( ($DATA = $this->_readFile("$this->_LIBPATH/txtsql/txtsql.MYI")) === FALSE ) { $this->_error(E_USER_WARNING, 'Database file is corrupted!'); return FALSE; } if ( empty($user) ) { $this->_error(E_USER_NOTICE, 'Forgot to input username'); return FALSE; } switch ( strtolower($action) ) { case 'add': if ( isset($DATA[strtolower($user)]) ) { $this->_error(E_USER_NOTICE, 'User already exists'); return FALSE; } $DATA[strtolower($user)] = md5($pass); break; case 'drop': if ( strtolower($user) == strtolower($this->_USER) ) { $this->_error(E_USER_NOTICE, 'Can\'t drop yourself'); return FALSE; } elseif ( strtolower($user) == 'root' ) { $this->_error(E_USER_NOTICE, 'Can\'t drop user root'); return FALSE; } elseif ( !isset($DATA[strtolower($user)]) ) { $this->_error(E_USER_NOTICE, 'User doesn\'t exist'); return FALSE; } elseif ( md5($pass) != $DATA[strtolower($user)] ) { $this->_error(E_USER_NOTICE, 'Incorrect password'); return FALSE; } unset($DATA[strtolower($user)]); break; case 'edit': if ( !isset($DATA[strtolower($user)]) ) { $this->_error(E_USER_NOTICE, 'User doesn\'t exist'); return FALSE; } if ( md5($pass) != $DATA[strtolower($user)] ) { $this->_error(E_USER_NOTICE, 'Incorrect password'); return FALSE; } $DATA[strtolower($user)] = md5($pass1); break; default: $this->_error(E_USER_NOTICE, 'Invalid action specified'); return FALSE; } $fp = @fopen("$this->_LIBPATH/txtsql/txtsql.MYI", 'w') or $this->_error(E_USER_FATAL, "Couldn't open $this->_LIBPATH/txtsql/txtsql.MYI for writing"); @flock($fp, LOCK_EX); @fwrite($fp, serialize($DATA)) or $this->_error(E_USER_FATAL, "Couldn't write to $this->_LIBPATH/txtsql/txtsql.MYI"); @flock($fp, LOCK_UN); @fclose($fp) or $this->_error(E_USER_NOTICE, "Error closing $this->_LIBPATH/txtsql/txtsql.MYI"); $this->_CACHE["$this->_LIBPATH/txtsql/txtsql.MYI"] = $DATA; return TRUE; } function getUsers () { if ( !$this->_isconnected() ) { $this->_error(E_USER_NOTICE, 'Not connected'); return FALSE; } if ( ($DATA = $this->_readFile("$this->_LIBPATH/txtsql/txtsql.MYI")) === FALSE ) { $this->_error(E_USER_WARNING, 'Database file is corrupted!'); return FALSE; } $users = array(); foreach ( $DATA as $key => $value ) { $users[] = $key; } return $users; } function isLocked ($db) { if ( !$this->_dbexist($db) ) { $this->_error(E_USER_NOTICE, 'Database '.$db.' doesn\'t exist'); return FALSE; } return is_file("$this->_LIBPATH/$db/txtsql.lock") ? TRUE : FALSE; } function lockdb ($db) { if ( !$this->_isConnected() ) { $this->_error(E_USER_NOTICE, 'You must be connected'); return FALSE; } elseif ( $this->isLocked($db) ) { $this->_error(E_USER_NOTICE, 'Lock for database '.$db.' already exists'); return FALSE; } $fp = fopen("$this->_LIBPATH/$db/txtsql.lock", 'a') or $this->_error(E_USER_ERROR, 'Err1or creating a lock for database '.$db); fclose($fp) or $this->_error(E_USER_ERROR, 'Error creating a lock for database '.$db); return TRUE; } function unlockdb ($db) { if ( !$this->_isConnected() ) { $this->_error(E_USER_NOTICE, 'You must be connected'); return FALSE; } elseif ( !$this->isLocked($db) ) { $this->_error(E_USER_NOTICE, 'Lock for database '.$db.' doesn\'t exist'); return FALSE; } if ( !@unlink("$this->_LIBPATH/$db/txtsql.lock") ) { $this->_error(E_USER_ERROR, 'Error removing lock for database '.$db); } return TRUE; } function selectdb ($db) { if ( empty($db) ) { $this->_error(E_USER_NOTICE, 'Cannot select database '.$db); return FALSE; } if ( !$this->_dbexist($db) ) { $this->_error(E_USER_NOTICE, 'Database '.$db.' doesn\'t exist'); return FALSE; } $this->_SELECTEDDB = $db; @$this->_query->_SELECTEDDB = $db; return TRUE; } function table_exists ($table, $db) { return $this->_tableexist($table, $db); } function db_exists ($db) { return $this->_dbexist($db); } function table_count ($table, $database=NULL) { if ( !empty($database) ) { if ( !$this->selectdb($database) ) { return FALSE; } } if ( empty($this->_SELECTEDDB) || empty($table) ) { $this->_error(E_USER_NOTICE, 'No database selected'); return FALSE; } $filename = "$this->_LIBPATH/$this->_SELECTEDDB/$table"; if ( !is_file($filename.'.MYD') || !is_file($filename.'.FRM') ) { $this->_error(E_USER_NOTICE, 'Table '.$table.' doesn\'t exist'); return FALSE; } if ( ($rows = @file($filename.'.MYD')) === FALSE ) { $this->_error(E_USER_NOTICE, 'Table '.$table.' doesn\'t exist'); return FALSE; } $count = substr($rows[0], 2, strpos($rows[0], '{') - 3); return $count; } function last_insert_id( $table, $db = '', $column = '' ) { if ( !empty($db) ) { if ( !$this->selectdb($db) ) { return FALSE; } } if ( empty($this->_SELECTEDDB) ) { $this->_error(E_USER_NOTICE, 'No database selected'); return FALSE; } if ( ( $cols = $this->_readFile("$this->_LIBPATH/$this->_SELECTEDDB/$table.FRM") ) === FALSE ) { $this->_error(E_USER_NOTICE, 'Table "'.$table.'" doesn\'t exist'); return FALSE; } if ( !empty($column) ) { if ( $this->_getColPos($column, $cols) === FALSE ) { $this->_error(E_USER_NOTICE, 'Column '.$column.' doesn\'t exist'); return FALSE; } elseif ( $cols[$column]['auto_increment'] != 1 ) { $this->_error(E_USER_NOTICE, 'Column '.$column.' is not an auto_increment field'); return FALSE; } $cols['primary'] = $column; } elseif ( empty($cols['primary']) && empty($column) ) { $this->_error(E_USER_NOTICE, 'There is no primary key defined for table "'.$table.'"'); return FALSE; } return $cols[$cols['primary']]['autocount']; } function query_count() { return $this->_QUERYCOUNT; } function last_error() { if ( !empty($this->_query->_ERRORS) ) { print '<pre>'.$this->_query->_ERRORSPLAIN[count($this->_query->_ERRORS)-1].'</pre>'; } elseif ( !empty($this->_ERRORS) ) { print '<pre>'.$this->_ERRORSPLAIN[count($this->_ERRORS)-1].'</pre>'; } } function get_last_error() { if ( !empty($this->_query->_ERRORS) ) { return $this->_query->_ERRORSPLAIN[count($this->_query->_ERRORS)-1]; } elseif ( !empty($this->_ERRORS) ) { return $this->_ERRORSPLAIN[count($this->_ERRORS)-1]; } } function errordump() { if ( empty($this->_ERRORS) && empty($this->_query->_ERRORS) ) { echo 'No errors occurred during script execution'; return TRUE; } if ( !empty($this->_ERRORS) ) { foreach ( $this->_ERRORS as $key => $value ) { echo 'ERROR #['.$key.'] '.$value; } } elseif ( !empty($this->_query->_ERRORS) ) { foreach ( $this->_query->_ERRORS as $key => $value ) { echo 'ERROR #['.$key.'] '.$value; } } return TRUE; } function emptyCache() { $this->_CACHE = array(); return TRUE; } function _error ($errno, $errstr, $errtype=NULL) { $backtrace = array_reverse(@debug_backtrace()); $errfile = $backtrace[0]['file']; $errline = $backtrace[0]['line']; switch ($errno) { case E_USER_ERROR: $type = 'Fatal Error'; break; case E_USER_NOTICE: $type = "Warning"; break; default: $type = "Error"; break; } $type = isset($errtype) ? $errtype : $type; $this->_ERRORSPLAIN[] = $errstr; $errormsg = "<BR />\n<B>txtSQL $type:</B> $errstr in <B>$errfile</B> on line <B>$errline</B>\n<BR /></DIV>"; $this->_ERRORS[] = $errormsg; if ( $this->_STRICT === TRUE ) { echo $errormsg; } if ( $errno == E_USER_ERROR ) { exit; } return TRUE; } function _readFile ( $filename, $useCache = TRUE, $unserialize = TRUE ) { if ( is_file($filename) ) { if ( $useCache === TRUE ) { if ( isset($this->_CACHE[$filename]) ) { return $this->_CACHE[$filename]; } } if ( ( $contents = @implode('', @file($filename)) ) !== FALSE ) { if ( $unserialize === TRUE ) { if ( ( $contents = @unserialize($contents) ) === FALSE ) { return FALSE; } } if ( $useCache === TRUE ) { $this->_CACHE[$filename] = $contents; } return $contents; } } return FALSE; } function _isconnected () { if ( empty($this->_USER) ) { return FALSE; } if ( $this->_data[strtolower($this->_USER)] != md5($this->_PASS) ) { return FALSE; } return TRUE; } function _dbexist ($db) { return is_dir("$this->_LIBPATH/$db") ? TRUE : FALSE; } function _tableexist ($table, $db) { if ( !empty($db) ) { if ( !$this->selectdb($db) ) { $this->_error(E_USER_NOTICE, 'Database, \''.$db.'\', doesn\'t exist'); return FALSE; } } $filename = "$this->_LIBPATH/$this->_SELECTEDDB/$table"; if ( is_file($filename.'.MYD') && is_file($filename.'.FRM') ) { return TRUE; } return FALSE; } function _buildIf ($where, $cols) { if ( !is_array($where) || empty($where) ) { $this->_error(E_USER_NOTICE, 'Where clause must be an array'); return FALSE; } $query = ''; foreach ( $where as $key => $value ) { if ( $key % 2 == 1 ) { $and = strtolower($value) == 'and'; $or = strtolower($value) == 'or'; $xor = strtolower($value) == 'xor'; if ( $and === FALSE && $or === FALSE && $xor === FALSE ) { $this->_error(E_USER_NOTICE, 'Only boolean seperators AND, and OR are allowed'); return FALSE; } $query .= ( $and === TRUE ) ? ' && ' : ( ( $xor === TRUE ) ? ' XOR ' : ' || ' ); continue; } $f1 = '('; $f2 = ') '; switch ( TRUE ) { case strpos($value, '!='): $type = 1; $op = '!='; break; case strpos($value, '!~'): $type = 3; $op = '!~'; break; case strpos($value, '=~'): $type = 3; $op = '=~'; break; case strpos($value, '<='): $type = 2; $op = '<='; break; case strpos($value, '>='): $type = 2; $op = '>='; break; case strpos($value, '=' ): $type = 1; $op = '='; break; case strpos($value, '<>'): $type = 1; $op = '<>'; break; case strpos($value, '<' ): $type = 2; $op = '<'; break; case strpos($value, '>' ): $type = 2; $op = '>'; break; case strpos($value, '!?'): $type = 5; $op = '!?'; break; case strpos($value, '?' ): $type = 5; $op = '?'; break; default: $val = 'TRUE'; if ( substr(trim($value), 0, 1) == '!' ) { $val = 'FALSE'; $value = substr($value, strpos($value, '!')+1); } $function = substr($value, 0, strpos($value, '(')); $col = substr($value, strlen($function) + 1, strlen($value) - strlen($function) - 2 ); if ( $function !== FALSE ) { $type = 4; $op = '==='; switch ( strtolower($function) ) { case 'isnumeric': $f1 = 'is_numeric('; break 2; case 'isstring': $f1 = 'is_string('; break 2; case 'isfile': $f1 = 'is_file('; break 2; case 'isdir': $f1 = 'is_dir('; break 2; case 'iswritable': $f1 = 'is_writable('; break 2; } } $this->_error(E_USER_NOTICE, 'You have an error in your where clause, (operators allowed: =, !=, <>, =~, !~, <, >, <=, >=)'); return FALSE; } if ( !isset($function) ) { list ( $col, $val ) = explode($op, $value, 2); } if ( substr_count($col, '(') == 1 && substr_count($col, ')') == 1 ) { $function = substr($col, 0, strpos($col, '(')); if ( $val != '' && $col{strlen($col)-1}.$val{0} == "  " ) { $col = substr($col, strlen($function) + 1, strlen($col) - strlen($function) - ( ($col{strlen($col)-1} != " " ) ? 2 : 3 ) )." "; $val = $val; } else { $col = substr($col, strlen($function) + 1, strlen($col) - strlen($function) - ( ($col{strlen($col)-1} != " " ) ? 2 : 3 ) ); } switch ( strtolower($function) ) { case 'strlower': $f1 = 'strtolower('; break; case 'strupper': $f1 = 'strtoupper('; break; case 'chop': case 'rtrim': $f1 = 'rtrim('; break; case 'ltrim': $f1 = 'ltrim('; break; case 'trim': $f1 = 'trim('; break; case 'md5': $f1 = 'md5('; break; case 'stripslash': $f1 = 'stripslashes('; break; case 'strlength': $f1 = 'strlen('; break; case 'strreverse': $f1 = 'strrev('; break; case 'ucfirst': $f1 = 'ucfirst('; break; case 'ucwords': $f1 = 'ucwords('; break; case 'bin2hex': $f1 = 'bin2hex('; break; case 'entdecode': $f1 = 'html_entity_decode('; break; case 'entencode': $f1 = 'htmlentities('; break; case 'soundex': $f1 = 'soundex('; break; case 'ceil': $f1 = 'ceil('; break; case 'floor': $f1 = 'floor('; break; case 'round': $f1 = 'round('; break; case 'isnumeric': case 'isstring': case 'isfile': case 'isdir': $this->_error(E_USER_NOTICE, 'Function, '.$function.', requires that NO operator be present in the clause'); return FALSE; default: $this->_error(E_USER_NOTICE, 'Function, '.$function.', hasn\'t been implemented'); return FALSE; } } if ( strtolower(trim($col)) == 'primary' ) { if ( empty($cols['primary']) ) { $this->_error(E_USER_NOTICE, 'No primary key has been assigned to this table'); return FALSE; } $col = $cols['primary']; } if ( ( $position = $this->_getColPos(rtrim($col), $cols) ) === FALSE ) { $this->_error(E_USER_NOTICE, 'Column \''.rtrim($col).'\' doesn\'t exist'); return FALSE; } $val = str_replace("\'", "'", addslashes($val)); $val = ( $col{strlen($col)-1}.$val{0} == "  " ) ? substr($val, 1) : $val; if ( empty($val) && ( $type == '5' || $f1 != '(' ) ) { $this->_error(E_USER_NOTICE, 'Forgot to specify a value to match in your where clause'); return FALSE; } switch ( $type ) { case 1: case 2: $quotes = ( !is_numeric($val) || $cols[rtrim($col)]['type'] != 'int' ) ? '"' : ''; $query .= ' ( '.$f1.'$value['.$position.']'.$f2.' '.( $op == '=' ? '==' : $op ).' '.$quotes.$val.$quotes.' ) '; break; case 3: $val = str_replace(array('(', ')', '{', '}', '.', '$', '/', '\%', '*', '%', '$$PERC$$'), array('\(', '\)', '\{', '\}', '\.', '\$', '\/', '$$PERC$$', '\*', '(.+)?', '%'), $val); $query .= ' ( '.($op == '!~' ? '!' : '').'preg_match("/^'.$val.'$/iU", '.$f1.'$value['.$position.']'.$f2.') ) '; break; case 4: $query .= ' ( '.$f1.'$value['.$position.']'.$f2.' === '.$val.' ) '; break; case 5: $query .= ' ( strpos('.$f1.'\' \'.$value['.$position.']), \''.$val.'\') '.(($op == '!?') ? '=' : '!' ).'== FALSE ) '; } unset($function, $f1, $f2, $quotes, $position, $val, $col, $op); } $andor = substr($query, -3, -1); if ( $andor == '&&' || $andor == '||' || $andor == 'OR' ) { $this->_error(E_USER_NOTICE, 'You have an error in your where clause, cannot end statement with an AND, OR, or XOR'); return FALSE; } return $query; } function _getColPos ($colname, $cols) { if ( empty($cols) || !is_array($cols) || !array_key_exists($colname, $cols) ) { return FALSE; } unset($cols['primary']); if ( ( $position = array_search($colname, array_keys($cols)) ) === FALSE ) { return FALSE; } return $position; } function _qsort($array, $num = 0, $order = "ASC", $left = 0, $right = -1) { if ( count($array) >= 1 ) { if ( $right == -1 ) { $right = count($array) - 1; } $links = $left; $rechts = $right; $mitte = $array[($left + $right) / 2][$num]; if ( $rechts > $links ) { do { if ( strtolower($order) == 'asc' ) { while ( $array[$links][$num] < $mitte ) { $links++; } while ( $array[$rechts][$num] > $mitte ) { $rechts--; } } else { while ( $array[$links][$num] > $mitte ) { $links++; } while ( $array[$rechts][$num] < $mitte) { $rechts--; } } if ( $links <= $rechts ) { $tmp = $array[$links]; $array[$links++] = $array[$rechts]; $array[$rechts--] = $tmp; } } while ( $links <= $rechts ); if ( $left < $rechts ) { $array = $this->_qsort($array,$num,$order,$left, $rechts); } if ( $links < $right ) { $array = $this->_qsort($array,$num,$order,$links,$right); } } return $array; } return FALSE; } function unique_multi_array ( $array, $sub_key ) { $target = array(); $existing_sub_key_values = array(); foreach ( $array as $key => $sub_array ) { if ( !in_array($sub_array[$sub_key], $existing_sub_key_values) ) { $existing_sub_key_values[] = $sub_array[$sub_key]; $target[$key] = $sub_array; } } return $target; } function version() { return '2.2 Final'; } } class txtSQLCore extends txtSQL { function select ($arg) { if ( !empty($arg['db']) ) { if ( !$this->selectdb($arg['db']) ) { return FALSE; } } if ( empty($this->_SELECTEDDB) ) { $this->_error(E_USER_NOTICE, 'No database selected'); return FALSE; } elseif ( empty($arg['table']) ) { $this->_error(E_USER_NOTICE, 'No table specified'); return FALSE; } elseif ( empty($arg['select']) ) { $arg['select'] = array('*'); } $filename = "$this->_LIBPATH/$this->_SELECTEDDB/{$arg['table']}"; if ( ($rows = $this->_readFile($filename.'.MYD')) === FALSE || ($cols = $this->_readFile($filename.'.FRM')) === FALSE ) { $this->_error(E_USER_NOTICE, 'Table "'.$arg['table'].'" doesn\'t exist'); return FALSE; } if ( empty($rows) ) { return array(); } $matches = 'TRUE'; if ( isset($arg['where']) ) { if ( ($matches = $this->_buildIf($arg['where'], $cols)) === FALSE ) { return FALSE; } } if ( empty($arg['limit']) || (!empty($arg['limit']) && !is_array($arg['limit'])) ) { $arg['limit']['0'] = 0; $arg['limit']['1'] = count($rows)-1; } elseif ( isset($arg['limit'][0]) && !isset($arg['limit'][1]) ) { $arg['limit'][1] = $arg['limit'][0]; $arg['limit'][0] = 0; } elseif ( !isset($arg['limit'][0]) || !isset($arg['limit'][1]) || $arg['limit'][0] > $arg['limit'][1] ) { $arg['limit']['0'] = 0; $arg['limit']['1'] = count($rows)-1; } $arg['limit'][0] = ( int ) $arg['limit'][0]; $arg['limit'][1] = ( int ) $arg['limit'][1]; if ( $arg['select'][0] == '*' ) { $col = $cols; unset($col['primary']); $arg['select'] = array_keys($col); } foreach ( $arg['select'] as $key => $value ) { if ( strtolower($value) == 'primary' ) { if ( empty($cols['primary']) ) { $this->_error(E_USER_NOTICE, 'No primary key assigned to table '.$arg['table']); return FALSE; } $value = $cols['primary']; } if ( ($colPos = $this->_getColPos($value, $cols)) === FALSE ) { $this->_error(E_USER_NOTICE, 'Column \''.$value.'\' doesn\'t exist'); return FALSE; } $temp[$value] = $colPos; } $arg['select'] = $temp; $found = -1; $added = -1; $selected = array(); $function = '  foreach ( $rows as $key => $value )
				{
					if ( '.$matches.' )
					{
						$found++;
						if ( $found >= $arg[\'limit\'][0] && $found <= $arg[\'limit\'][1] )
						{
							$added++;'; foreach ( $arg['select'] as $key => $value ) { $function .= "\$selected[\$added]['$key'] = \$value[$value];"; } $function .= '				if ( $found >= $arg[\'limit\'][1] )
							{
								break;
							}
						}
					}
				}  '; eval($function); if ( !empty($arg['orderby']) && !empty($selected) && count($selected) > 0 ) { if ( !is_array($arg['orderby']) || count($arg['orderby']) != 2 ) { $this->_error(E_USER_NOTICE, 'Invalid Order By Clause; Must be array, with two values. array(string "column name", [ASC|DESC])'); return FALSE; } if ( !array_key_exists($arg['orderby'][0], $selected[0]) ) { $this->_error(E_USER_NOTICE, 'Cannot sort results by column \''.$arg['orderby'][0].'\'; Column not in result set'); return FALSE; } if ( strtolower($arg['orderby'][1]) != 'asc' && strtolower($arg['orderby'][1]) != 'desc' ) { $this->_error(E_USER_NOTICE, 'Results can only be sorted \'asc\' (ascending) or \'desc\' (descending)'); return FALSE; } $selected = $this->_qsort($selected, $arg['orderby'][0], $arg['orderby'][1]); } if ( !empty($arg['distinct']) ) { if ( $this->_getColPos($arg['distinct'], $cols) === FALSE ) { $this->_error(E_USER_NOTICE, 'Column \''.$arg['distinct'].'\' doesn\'t exist'); return FALSE; } $selected = $this->unique_multi_array($selected, $arg['distinct']); } $this->_CACHE[$filename.'.MYD'] = $rows; $this->_CACHE[$filename.'.FRM'] = $cols; return $selected; } function insert ($arg) { if ( !empty($arg['db']) ) { if ( !$this->selectdb($arg['db']) ) { return FALSE; } } if ( empty($this->_SELECTEDDB) ) { $this->_error(E_USER_NOTICE, 'No database selected'); return FALSE; } elseif ( empty($arg['table']) ) { $this->_error(E_USER_NOTICE, 'No table specified'); return FALSE; } if ( $this->isLocked($this->_SELECTEDDB) ) { $this->_error(E_USER_NOTICE, 'Database '.$this->_SELECTEDDB.' is locked'); return FALSE; } $filename = "$this->_LIBPATH/$this->_SELECTEDDB/{$arg['table']}"; if ( ($rows = $this->_readFile($filename.'.MYD')) === FALSE || ($cols = $this->_readFile($filename.'.FRM')) === FALSE ) { $this->_error(E_USER_NOTICE, 'Table '.$arg['table'].' doesn\'t exist'); return FALSE; } $model = array(); foreach ( $cols as $key => $value ) { if ( $key == 'primary' ) continue; if ( $value['auto_increment'] == 1 ) { $model[] = ($cols[$key]['autocount']++)+1; } elseif ( $value['type'] == 'date' ) { $arg['values'][$key] = ''; } else { $model[] = $value['default']; } } $max = count($rows); foreach ( $arg['values'] as $key => $value ) { unset($arg['values'][$key]); if ( strtolower($key) == 'primary' ) { if ( empty($cols['primary']) ) { $this->_error(E_USER_NOTICE, 'No primary key assigned to table '.$arg['table']); return FALSE; } $key = $cols['primary']; } if ( ($colPos = $this->_getColPos($key, $cols)) === FALSE ) { $this->_error(E_USER_NOTICE, 'Column \''.$key.'\' doesn\'t exist'); return FALSE; } $value = array($colPos, $value); if ( $cols[$key]['type'] == 'int' && $cols[$key]['max'] > 0 && $value[1] > $cols[$key]['max'] ) { $this->_error(E_USER_NOTICE, 'Cannot exceed maximum value for column '.$key); return FALSE; } elseif ( $cols[$key]['max'] > 0 && strlen($value[1]) > $cols[$key]['max'] ) { $this->_error(E_USER_NOTICE, 'Cannot exceed maximum value for column '.$key); return FALSE; } if ( empty($value[1]) && !empty($cols[$key]['default']) ) { $value[1] = $cols[$key]['default']; } if ( $cols[$key]['auto_increment'] == 1 ) { $value[1] = $model[$colPos]; } switch ( strtolower($cols[$key]['type']) ) { case 'enum': if ( empty($cols[$key]['enum_val']) ) { $cols[$key]['enum_val'] = serialize(array('')); } $enum_val = unserialize($cols[$key]['enum_val']); foreach ( $enum_val as $key => $value1 ) { if ( strtolower($value[1]) == strtolower($value1) ) { break; } if ( $key == ( count($enum_val) - 1 ) ) { $value[1] = $enum_val[$key]; break; } } case 'text': case 'string': $model[$value[0]] = (string) $value[1]; break; case 'int': $model[$value[0]] = (integer) $value[1]; break; case 'bool': $model[$value[0]] = (boolean) $value[1]; break; case 'date': $model[$value[0]] = time(); break; } } $rows[] = $model; $fp = @fopen($filename.".MYD", 'w') or $this->_error(E_USER_ERROR, 'Error opening table '.$arg['table']); @flock($fp, LOCK_EX); @fwrite($fp, serialize($rows)) or $this->_error(E_USER_ERROR, 'Error writing to table '.$arg['table']); @flock($fp, LOCK_UN); @fclose($fp); $fp = @fopen($filename.".FRM", 'w') or $this->_error(E_USER_ERROR, 'Error opening table '.$arg['table']); @flock($fp, LOCK_EX); @fwrite($fp, serialize($cols)) or $this->_error(E_USER_ERROR, 'Error writing to table '.$arg['table']); @flock($fp, LOCK_UN); @fclose($fp); $this->_CACHE[$filename.'.MYD'] = $rows; $this->_CACHE[$filename.'.FRM'] = $cols; return TRUE; } function delete ($arg) { if ( !empty($arg['db']) ) { if ( !$this->selectdb($arg['db']) ) { return FALSE; } } if ( empty($this->_SELECTEDDB) ) { $this->_error(E_USER_NOTICE, 'No database selected'); return FALSE; } elseif ( empty($arg['table']) ) { $this->_error(E_USER_NOTICE, 'No table specified'); return FALSE; } if ( $this->isLocked($this->_SELECTEDDB) ) { $this->_error(E_USER_NOTICE, 'Database '.$this->_SELECTEDDB.' is locked'); return FALSE; } $filename = "$this->_LIBPATH/$this->_SELECTEDDB/{$arg['table']}"; if ( ($rows = $this->_readFile($filename.'.MYD')) === FALSE || ($cols = $this->_readFile($filename.'.FRM')) === FALSE ) { $this->_error(E_USER_NOTICE, 'Table '.$arg['table'].' doesn\'t exist'); return FALSE; } if ( isset($arg['where']) ) { if ( ($matches = $this->_buildIf($arg['where'], $cols)) === FALSE ) { return FALSE; } } else { $rows = array(); } if ( !isset($arg['limit']) || empty($arg['limit']) || !is_numeric($arg['limit'][0]) ) { $arg['limit']['0'] = count($rows); } $found = 0; $deleted = 0; $function = '
		foreach ( $rows as $key => $value )
		{
			if ( '.( isset($matches) ? $matches : 'TRUE' ).' )
			{
				$found++;
				if ( $found <= $arg[\'limit\'][0] )
				{
					$deleted++;
					unset($rows[$key]);
					if ( $found >= $arg[\'limit\'][0] )
					{
						break;
					}
					continue;
				}
				break;
			}
		}'; eval($function); $fp = @fopen($filename.".MYD", 'w') or $this->_error(E_USER_ERROR, 'Error opening table '.$arg['table']); @flock($fp, LOCK_EX); @fwrite($fp, serialize($rows)) or $this->_error(E_USER_ERROR, 'Error writing to table '.$arg['table']); @flock($fp, LOCK_UN); @fclose($fp); $this->_CACHE[$filename.'.MYD'] = $rows; $this->_CACHE[$filename.'.FRM'] = $cols; return $deleted; } function update ($arg) { if ( !empty($arg['db']) ) { if ( !$this->selectdb($arg['db']) ) { return FALSE; } } if ( empty($this->_SELECTEDDB) ) { $this->_error(E_USER_NOTICE, 'No database selected'); return FALSE; } elseif ( empty($arg['table']) ) { $this->_error(E_USER_NOTICE, 'No table specified'); return FALSE; } if ( $this->isLocked($this->_SELECTEDDB) ) { $this->_error(E_USER_NOTICE, 'Database '.$this->_SELECTEDDB.' is locked'); return FALSE; } $filename = "$this->_LIBPATH/$this->_SELECTEDDB/{$arg['table']}"; if ( ($rows = $this->_readFile($filename.'.MYD')) === FALSE || ($cols = $this->_readFile($filename.'.FRM')) === FALSE ) { $this->_error(E_USER_NOTICE, 'Table '.$arg['table'].' doesn\'t exist'); return FALSE; } if ( !isset($arg['where']) ) { $this->_error(E_USER_NOTICE, 'Must specify a where clause'); return FALSE; } elseif ( ($matches = $this->_buildIf($arg['where'], $cols)) === FALSE ) { return FALSE; } elseif ( !isset($arg['values']) || empty($arg['values']) ) { $this->_error(E_USER_NOTICE, 'Must specify values to update'); return FALSE; } if ( empty($arg['limit']) ) { $arg['limit']['0'] = count($rows); } elseif ( !is_array($arg['limit']) || !is_numeric($arg['limit'][0]) || $arg['limit'][0] <= 0 ) { $arg['limit']['0'] = count($rows); } foreach ( $arg['values'] as $key => $value ) { if ( strtolower($key) == 'primary' ) { if ( empty($cols['primary']) ) { $this->_error(E_USER_NOTICE, 'No primary key assigned to table '.$arg['table']); return FALSE; } $key = $cols['primary']; } if ( ($colPos = $this->_getColPos($key, $cols)) === FALSE ) { $this->_error(E_USER_NOTICE, 'Column \''.$key.'\' doesn\'t exist'); return FALSE; } if ( $cols[$key]['permanent'] == 1 ) { $this->_error(E_USER_NOTICE, 'Column '.$key.' is set to permanent'); unset($arg['values'][$key]); continue; } if ( $cols[$key]['type'] == 'int' && $cols[$key]['max'] > 0 && $value > $cols[$key]['max'] ) { $this->_error(E_USER_NOTICE, 'Cannot exceed maximum value for column '.$key); return FALSE; } elseif ( $cols[$key]['max'] > 0 && strlen($value) > $cols[$key]['max'] ) { $this->_error(E_USER_NOTICE, 'Cannot exceed maximum value for column '.$key); return FALSE; } $arg['values'][$key] = array($colPos, $value); unset($key, $value); } $found = 0; $updated = 0; $function = '	foreach ( $rows as $key => $value )
				{
					if ( '.$matches.' )
					{
						$found++;
						if ( $found <= $arg[\'limit\'][0] )
						{
							$updated++;'; foreach ( $arg['values'] as $key1 => $value1 ) { switch ( strtolower($cols[$key1]['type']) ) { case 'enum': if ( empty($cols[$key1]['enum_val']) ) { $cols[$key1]['enum_val'] = serialize(array('')); } $enum_val = unserialize($cols[$key1]['enum_val']); foreach ( $enum_val as $key2 => $value2 ) { if ( strtolower($arg['values'][$key1][1]) == strtolower($value2) ) { break; } if ( $key2 == ( count($enum_val) - 1 ) ) { $arg['values'][$key1][1] = $enum_val[$key2]; break; } } case 'text': case 'string': $type = "string"; break; case 'int': $type = "integer"; break; case 'bool': $type = "boolean"; break; default: $type = "string"; } $function .= "\$rows[\$key][$value1[0]] = ( $type ) \$arg['values']['$key1'][1];"; } $function .= '				continue;
						}
						break;
					}
				}
		'; eval($function); $fp = @fopen($filename.".FRM", 'w') or $this->_error(E_USER_ERROR, 'Error opening table '.$arg['table']); @flock($fp, LOCK_EX); @fwrite($fp, serialize($cols)) or $this->_error(E_USER_ERROR, 'Error writing to table '.$arg['table']); @flock($fp, LOCK_UN); @fclose($fp); $fp = @fopen($filename.".MYD", 'w') or $this->_error(E_USER_ERROR, 'Error opening table '.$arg['table']); @flock($fp, LOCK_EX); @fwrite($fp, serialize($rows)) or $this->_error(E_USER_ERROR, 'Error writing to table '.$arg['table']); @flock($fp, LOCK_UN); @fclose($fp); $this->_CACHE[$filename.'.MYD'] = $rows; $this->_CACHE[$filename.'.FRM'] = $cols; return $updated; } function showtables ($arg = NULL) { if ( !empty($arg['db']) ) { if ( !$this->selectdb($arg['db']) ) { return FALSE; } } if ( empty($this->_SELECTEDDB) ) { $this->_error(E_USER_NOTICE, 'No database selected'); return FALSE; } if ( ($fp = @opendir("$this->_LIBPATH/$this->_SELECTEDDB")) === FALSE ) { $this->_error(E_USER_ERROR, 'Could not open directory, '.$this->_LIBPATH.'/'.$this->_SELECTEDDB.', for reading'); } $table = array(); while ( ($file = @readdir($fp)) !== FALSE ) { if ( $file != "." && $file != ".." && $file != 'txtsql.MYI') { $extension = substr($file, strrpos($file, '.')+1); if ( ($extension == 'MYD' || $extension == 'FRM') && is_file("$this->_LIBPATH/$this->_SELECTEDDB/$file") ) { $table[] = substr($file, 0, strrpos($file, '.')); } } } @closedir($fp); $tables = array(); foreach ( $table as $key => $value ) { if ( isset($temp[$value]) ) { $tables[] = $value; } else { $temp[$value] = TRUE; } } return !empty($tables) ? $tables : array(); } function createtable ($arg=NULL) { if ( !empty($arg['db']) ) { if ( !$this->selectdb($arg['db']) ) { return FALSE; } } if ( empty($this->_SELECTEDDB) ) { $this->_error(E_USER_NOTICE, 'No database selected'); return FALSE; } if ( $this->isLocked($this->_SELECTEDDB) ) { $this->_error(E_USER_NOTICE, 'Database '.$this->_SELECTEDDB.' is locked'); return FALSE; } if ( empty($arg['table']) || !preg_match('/^[A-Za-z0-9_]+$/', $arg['table']) ) { $this->_error(E_USER_NOTICE, 'Table name can only contain letters, and numbers'); return FALSE; } if ( empty($arg['columns']) || !is_array($arg['columns']) ) { $this->_error(E_USER_NOTICE, 'Invalid columns for table '.$arg['table']); return FALSE; } $cols = array('primary' => ''); $primaryset = FALSE; foreach ( $arg['columns'] as $key => $value ) { $model = array('permanent' => 0, 'auto_increment' => 0, 'max' => 0, 'type' => 'string', 'default' => '', 'autocount' => (int) 0, 'enum_val' => ''); if ( $key == 'primary' ) { $this->_error(E_USER_NOTICE, 'Use of reserved word [primary]'); return FALSE; } if ( (!empty($value) && !is_array($value)) || empty($key) ) { $this->_error(E_USER_NOTICE, 'Invalid columns for table '.$arg['table']); return FALSE; } foreach ( $value as $key1 => $value1 ) { switch ( strtolower($key1) ) { case 'auto_increment': $value1 = (int) $value1; if ( $value1 < 0 || $value1 > 1 ) { $this->_error(E_USER_NOTICE, 'Auto_increment must be a boolean 1 or 0'); return FALSE; } if ( isset($value['type']) && $value['type'] != 'int' && $value1 == 1 ) { $this->_error(E_USER_NOTICE, 'auto_increment must be an integer type'); return FALSE; } $model['auto_increment'] = $value1; break; case 'permanent': $value1 = (int) $value1; if ( $value1 < 0 || $value1 > 1 ) { $this->_error(E_USER_NOTICE, 'Permanent must be a boolean 1 or 0'); return FALSE; } $model['permanent'] = $value1; break; case 'max': $value1 = (int) $value1; if ( $value1 < 0 || $value1 > 1000000 ) { $this->_error(E_USER_NOTICE, 'Max must be less than 1,000,000 and greater than -1'); return FALSE; } $model['max'] = $value1; break; case 'type': switch ( strtolower($value1) ) { case 'text': $model['type'] = 'text'; break; case 'string': $model['type'] = 'string'; break; case 'int': $model['type'] = 'int'; break; case 'bool': $model['type'] = 'bool'; break; case 'enum': if ( !isset($value['enum_val']) || !is_array($value['enum_val']) || empty($value['enum_val']) ) { $this->_error(E_USER_NOTICE, 'Missing enum\'s list of values or invalid list inputted'); return FALSE; } $model['type'] = 'enum'; $model['enum_val'] = serialize($value['enum_val']); break; case 'date': $model['type'] = 'date'; break; default: $this->_error(E_USER_NOTICE, 'Invalid column type, can only accept integers, strings, and booleans'); return FALSE; } break; case 'default': $model['default'] = $value1; break; case 'primary': $value1 = (int) $value1; if ( $value1 < 0 || $value1 > 1 ) { $this->_error(E_USER_NOTICE, 'Primary must be a boolean 1 or 0'); return FALSE; } if ( $primaryset === TRUE && $value1 == 1 ) { $this->_error(E_USER_NOTICE, 'Only one primary column can be set'); return FALSE; } if ( $value1 == 1 ) { $value['auto_increment'] = isset($value['auto_increment']) ? $value['auto_increment'] : 0; $value['type'] = isset($value['type']) ? $value['type'] : 0; if ( $value['auto_increment'] != 1 || $value['type'] != 'int' ) { $this->_error(E_USER_NOTICE, 'Primary keys must be of type \'integer\' and auto_increment'); return FALSE; } $cols['primary'] = $key; } break; case 'enum_val': break; default: $this->_error(E_USER_NOTICE, 'Invalid column definition, ["'.$key1.'"], specified'); return FALSE; break; } } $cols[$key] = $model; } $filename = "$this->_LIBPATH/$this->_SELECTEDDB/$arg[table]"; if ( is_file($filename.".MYD") || is_file($filename.".FRM") ) { $this->_error(E_USER_NOTICE, 'Table '.$arg['table'].' already exists'); return FALSE; } $fp = @fopen($filename.".MYD", 'w') or $this->_error(E_USER_ERROR, 'Error creating table '.$arg['table']); @flock($fp, LOCK_EX); @fwrite($fp, 'a:0:{}') or $this->_error(E_USER_ERROR, 'Error writing to table '.$arg['table'].' while creating it'); @flock($fp, LOCK_UN); @fclose($fp); @chmod($filename.".MYD", 0777); $fp = @fopen($filename.".FRM", 'w') or $this->_error(E_USER_ERROR, 'Error creating table '.$arg['table']); @flock($fp, LOCK_EX); @fwrite($fp, serialize($cols)) or $this->_error(E_USER_ERROR, 'Error creating table '.$arg['table']); @flock($fp, LOCK_UN); @chmod($filename.".FRM", 0777); @fclose($fp); $this->_CACHE[$filename.'.FRM'] = $cols; return TRUE; } function droptable ($arg=NULL) { if ( empty($arg['table']) || !preg_match('/^[A-Za-z0-9_]+$/', $arg['table']) ) { $this->_error(E_USER_NOTICE, 'Database name can only contain letters, and numbers'); return FALSE; } if ( !empty($arg['db']) ) { if ( !$this->selectdb($arg['db']) ) { return FALSE; } } if ( empty($this->_SELECTEDDB) ) { $this->_error(E_USER_NOTICE, 'No database selected'); return FALSE; } if ( $this->isLocked($this->_SELECTEDDB) ) { $this->_error(E_USER_NOTICE, 'Database '.$this->_SELECTEDDB.' is locked'); return FALSE; } $filename = "$this->_LIBPATH/$this->_SELECTEDDB/$arg[table]"; if ( !is_file($filename.'.MYD') || !is_file($filename.'.FRM') ) { $this->_error(E_USER_NOTICE, 'Table '.$arg['table'].' doesn\'t exist'); return FALSE; } if ( !@unlink($filename.'.MYD') || !@unlink($filename.'.FRM') ) { $this->_error(E_USER_ERROR, 'Could not delete table '.$arg['table']); } return TRUE; } function altertable ($arg=NULL) { if ( !empty($arg['db']) ) { if ( !$this->selectdb($arg['db']) ) { return FALSE; } } if ( empty($this->_SELECTEDDB) ) { $this->_error(E_USER_NOTICE, 'No database selected'); return FALSE; } if ( $this->isLocked($this->_SELECTEDDB) ) { $this->_error(E_USER_NOTICE, 'Database '.$this->_SELECTEDDB.' is locked'); return FALSE; } if ( !empty($arg['name']) && !preg_match('/^[A-Za-z0-9_]+$/', $arg['name']) ) { $this->_error(E_USER_NOTICE, 'Names can only contain letters, numbers, and underscored'); return FALSE; } elseif ( empty($arg['action']) ) { $this->_error(E_USER_NOTICE, 'No action specified in alter table query'); return FALSE; } $filename = "$this->_LIBPATH/$this->_SELECTEDDB/$arg[table]"; if ( !is_file($filename.'.MYD') || !is_file($filename.'.FRM') ) { $this->_error(E_USER_NOTICE, 'Table '.$arg['table'].' doesn\'t exist'); return FALSE; } if ( ($rows = $this->_readFile($filename.'.MYD')) === FALSE || ($cols = $this->_readFile($filename.'.FRM')) === FALSE ) { $this->_error(E_USER_NOTICE, 'Table "'.$arg['table'].'" doesn\'t exist'); return FALSE; } $primaryset = !empty($cols['primary']) ? TRUE : FALSE; $action = strtolower($arg['action']); switch (strtolower($arg['action'])) { case 'insert': if ( empty($arg['name']) ) { $this->_error(E_USER_NOTICE, 'Forgot to input new column\'s name'); return FALSE; } if ( $arg['name'] == 'primary' ) { $this->_error(E_USER_NOTICE, 'Cannot name column primary (use of reserved words)'); return FALSE; } elseif ( isset($cols[$arg['name']]) ) { $this->_error(E_USER_NOTICE, 'Column '.$arg['name'].' already exists'); return FALSE; } if ( empty($arg['after']) ) { $colNames = array_keys($cols); $arg['after'] = $colNames[count($cols)-1]; } $model = array('permanent' => 0, 'auto_increment' => 0, 'max' => 0, 'type' => 'int', 'default' => '', 'autocount' => 0, 'enum_val' => ''); foreach ( $arg['values'] as $key => $value ) { switch (strtolower($key)) { case 'auto_increment': $value = (int) $value; if ( $value < 0 || $value > 1 ) { $this->_error(E_USER_NOTICE, 'Auto_increment must be a boolean 1 or 0'); return FALSE; } if ( isset($arg['values']['type']) && $arg['values']['type'] != 'int' && $value == 1 ) { $this->_error(E_USER_NOTICE, 'auto_increment must be an integer type'); return FALSE; } $model['auto_increment'] = $value; break; case 'permanent': $value = (int) $value; if ( $value < 0 || $value > 1 ) { $this->_error(E_USER_NOTICE, 'Permanent must be a boolean 1 or 0'); return FALSE; } $model['permanent'] = $value; break; case 'max': $value = (int) $value; if ( $value < 0 || $value > 1000000 ) { $this->_error(E_USER_NOTICE, 'Max must be less than 1,000,000 and greater than -1'); return FALSE; } $model['max'] = $value; break; case 'type': switch ( strtolower($value) ) { case 'text': $model['type'] = 'text'; break; case 'string': $model['type'] = 'string'; break; case 'int': $model['type'] = 'int'; break; case 'bool': $model['type'] = 'bool'; break; case 'enum': if ( !isset($arg['values']['enum_val']) || !is_array($arg['values']['enum_val']) || empty($arg['values']['enum_val']) ) { $this->_error(E_USER_NOTICE, 'Missing enum\'s list of values or invalid list inputted'); return FALSE; } $model['type'] = 'enum'; $model['enum_val'] = serialize($arg['values']['enum_val']); break; case 'date': $model['type'] = 'date'; break; default: $this->_error(E_USER_NOTICE, 'Invalid column type, can only accept integers, strings, and booleans'); return FALSE; } break; case 'default': $model['default'] = $value; break; case 'primary': $value = (int) $value; if ( $value < 0 || $value > 1 ) { $this->_error(E_USER_NOTICE, 'Primary must be a boolean 1 or 0'); return FALSE; } if ( $primaryset === TRUE && $value == 1 ) { $this->_error(E_USER_NOTICE, 'Only one primary column can be set'); return FALSE; } if ( $value == 1 ) { $cols['primary'] = $arg['name']; } break; case 'enum_val': break; default: $this->_error(E_USER_NOTICE, 'Invalid column definition, ["'.$key.'"], specified'); return FALSE; } } if ( $arg['after'] == 'primary' ) { $afterColPos = 1; } else { if ( ($afterColPos = $this->_getColPos($arg['after'], $cols)+2) === FALSE ) { $this->_error(E_USER_NOTICE, 'Column \''.$arg['after'].'\' doesn\'t exist'); return FALSE; } } $i = 0; foreach ( $cols as $key => $value ) { $temp[$key] = $value; $i++; if ( $i == $afterColPos ) { $temp[$arg['name']] = $model; } } $cols = $temp; if ( !empty($rows) ) { foreach ( $rows as $key => $value ) { $i = 0; foreach ( $value as $key1 => $value1 ) { if ( $i < $afterColPos-1 ) { $temp1[$key][$key1] = $value1; } if ( $i == $afterColPos - 1 || ( $i == count($value) - 1 && $i == $afterColPos - 2 ) ) { $temp1[$key][ ( ( $i == count($value) - 1 && $i == $afterColPos - 2) ? $key1 + 1 : $key1 ) ] = ''; $i++; } if ( $i > $afterColPos-1 ) { $temp1[$key][$key1+1] = $value1; } $i++; } } $rows = $temp1; } $fp = @fopen($filename.'.FRM', w) or $this->_error(E_USER_ERROR, 'Could not open '.$filename.'.FRM for writing'); @flock($fp, LOCK_EX); @fwrite($fp, serialize($cols)) or $this->_error(E_USER_ERROR, 'Could not write to file '.$filename.'.FRM'); @flock($fp, LOCK_UN); @fclose($fp) or $this->_error(E_USER_ERROR, 'Could not close '.$filename.'.FRM'); $fp = @fopen($filename.'.MYD', w) or $this->_error(E_USER_ERROR, 'Could not open '.$filename.'.MYD for writing'); @flock($fp, LOCK_EX); @fwrite($fp, serialize($rows)) or $this->_error(E_USER_ERROR, 'Could not write to file '.$filename.'.MYD'); @flock($fp, LOCK_UN); @fclose($fp) or $this->_error(E_USER_ERROR, 'Could not close '.$filename.'.MYD'); $this->_CACHE[$filename.'.MYD'] = $rows; $this->_CACHE[$filename.'.FRM'] = $cols; return TRUE; break; case 'modify': if ( $arg['name'] == 'primary' ) { $this->_error(E_USER_NOTICE, 'Column primary doesn\'t exist'); return FALSE; } elseif ( !isset($cols[$arg['name']]) ) { $this->_error(E_USER_NOTICE, 'Column '.$arg['name'].' doesn\'t exist'); return FALSE; } elseif ( empty($arg['values']) ) { $this->_error(E_USER_NOTICE, 'Empty column set given'); return FALSE; } $model = array('permanent' => $cols[$arg['name']]['permanent'], 'auto_increment' => $cols[$arg['name']]['auto_increment'], 'max' => $cols[$arg['name']]['max'], 'type' => $cols[$arg['name']]['type'], 'default' => $cols[$arg['name']]['default'], 'autocount' => $cols[$arg['name']]['autocount'], 'enum_val' => $cols[$arg['name']]['enum_val']); foreach ( $arg['values'] as $key => $value ) { switch (strtolower($key)) { case 'auto_increment': $value = (int) $value; if ( $value < 0 || $value > 1 ) { $this->_error(E_USER_NOTICE, 'Auto_increment must be a boolean 1 or 0'); return FALSE; } if ( isset($arg['values']['type']) && $arg['values']['type'] != 'int' && $value == 1 ) { $this->_error(E_USER_NOTICE, 'auto_increment must be an integer type'); return FALSE; } $model['auto_increment'] = $value; break; case 'permanent': $value = (int) $value; if ( $value < 0 || $value > 1 ) { $this->_error(E_USER_NOTICE, 'Permanent must be a boolean 1 or 0'); return FALSE; } $model['permanent'] = $value; break; case 'max': $value = (int) $value; if ( $value < 0 || $value > 1000000 ) { $this->_error(E_USER_NOTICE, 'Max must be less than 1,000,000 and greater than -1'); return FALSE; } $model['max'] = $value; break; case 'type': switch ( strtolower($value) ) { case 'text': $model['type'] = 'text'; break; case 'string': $model['type'] = 'string'; break; case 'int': $model['type'] = 'int'; break; case 'bool': $model['type'] = 'bool'; break; case 'enum': if ( !isset($arg['values']['enum_val']) || !is_array($arg['values']['enum_val']) || empty($arg['values']['enum_val']) ) { $this->_error(E_USER_NOTICE, 'Missing enum\'s list of values or invalid list inputted'); return FALSE; } $model['type'] = 'enum'; $model['enum_val'] = serialize($arg['values']['enum_val']); break; case 'date': $model['type'] = 'date'; break; default: $this->_error(E_USER_NOTICE, 'Invalid column type, can only accept integers, strings, and booleans'); return FALSE; } break; case 'default': $model['default'] = $value; break; case 'primary': $value = (int) $value; if ( $value < 0 || $value > 1 ) { $this->_error(E_USER_NOTICE, 'Primary must be a boolean 1 or 0'); return FALSE; } if ( $primaryset === TRUE && $value == 1 ) { $this->_error(E_USER_NOTICE, 'Only one primary column can be set'); return FALSE; } if ( $value == 1 ) { $cols['primary'] = $arg['name']; } break; case 'enum_val': break; default: $this->_error(E_USER_NOTICE, 'Invalid column definition, ["'.$key.'"], specified'); return FALSE; } } if ( ( $model['type'] != 'int' || $model['auto_increment'] != 1 ) && strtolower($cols['primary']) == strtolower($arg['name']) ) { $cols['primary'] = ''; $this->_error(E_USER_NOTICE, 'The primary key has been dropped, column must be auto_increment, and integer'); } $cols[$arg['name']] = $model; $fp = @fopen($filename.'.FRM', w) or $this->_error(E_USER_ERROR, 'Could not open '.$filename.'.FRM for writing'); @flock($fp, LOCK_EX); @fwrite($fp, serialize($cols)) or $this->_error(E_USER_ERROR, 'Could not write to file '.$filename.'.FRM'); @flock($fp, LOCK_UN); @fclose($fp) or $this->_error(E_USER_ERROR, 'Could not close '.$filename.'.FRM'); $this->_CACHE[$filename.'.FRM'] = $cols; return TRUE; break; case 'drop': if ( empty($arg['name']) or !preg_match('/^[A-Za-z0-9_]+$/', $arg['name']) ) { $this->_error(E_USER_NOTICE, 'Column name can only contain letters, numbers, and underscores'); return FALSE; } if ( !isset($cols[$arg['name']]) || $arg['name'] == 'primary' ) { $this->_error(E_USER_NOTICE, 'Column '.$arg['name'].' doesn\'t exist'); return FALSE; } if ( count($cols) - 2 <= 0 ) { $this->_error(E_USER_NOTICE, 'Cannot drop column; There has to be at-least ONE column present'); return false; } $i = -1; foreach ( $cols as $key => $value ) { if ( $key == $arg['name'] && $i > -1 ) { $position = $i; break; } $i++; } if ( $cols['primary'] == $arg['name'] ) { $cols['primary'] = ''; } unset($cols[$arg['name']]); if ( is_array($rows) && count($rows) > 0 ) { foreach ( $rows as $key => $value ) { unset($rows[$key][$position]); $rows[$key] = array_splice($rows[$key], 0); } } $fp = @fopen($filename.'.FRM', w) or $this->_error(E_USER_ERROR, 'Could not open '.$filename.'.FRM for writing'); @flock($fp, LOCK_EX); @fwrite($fp, serialize($cols)) or $this->_error(E_USER_ERROR, 'Could not write to file '.$filename.'.FRM'); @flock($fp, LOCK_UN); @fclose($fp) or $this->_error(E_USER_ERROR, 'Could not close '.$filename.'.FRM'); $fp = @fopen($filename.'.MYD', w) or $this->_error(E_USER_ERROR, 'Could not open '.$filename.'.MYD for writing'); @flock($fp, LOCK_EX); @fwrite($fp, serialize($rows)) or $this->_error(E_USER_ERROR, 'Could not write to file '.$filename.'.MYD'); @flock($fp, LOCK_UN); @fclose($fp) or $this->_error(E_USER_ERROR, 'Could not close '.$filename.'.MYD'); $this->_CACHE[$filename.'.MYD'] = $rows; $this->_CACHE[$filename.'.FRM'] = $cols; return TRUE; break; case 'rename col': if ( empty($arg['name']) || empty($arg['values']['name']) || !preg_match('/^[A-Za-z0-9_]+$/', $arg['values']['name']) ) { $this->_error(E_USER_NOTICE, 'Column names can only contain letters, numbers, and underscores'); return FALSE; } if ( !isset($cols[$arg['name']]) ) { $this->_error(E_USER_NOTICE, 'Column '.$arg['name'].' doesn\'t exist'); return FALSE; } if ( isset($cols[$arg['values']['name']]) && $arg['values']['name'] != $arg['name'] ) { $this->_error(E_USER_NOTICE, 'Column '.$arg['name'].' already exists'); return FALSE; } if ( $cols['primary'] == $arg['name'] ) { $cols['primary'] = $arg['values']['name']; } $tmp = $cols; $cols = array(); foreach ( $tmp as $key => $value ) { if ( $key == $arg['name'] ) { $key = $arg['values']['name']; } $cols[$key] = $value; } $fp = @fopen($filename.'.FRM', w) or $this->_error(E_USER_ERROR, 'Could not open '.$filename.'.FRM for writing'); @flock($fp, LOCK_EX); @fwrite($fp, serialize($cols)) or $this->_error(E_USER_ERROR, 'Could not write to file '.$filename.'.FRM'); @flock($fp, LOCK_UN); @fclose($fp) or $this->_error(E_USER_ERROR, 'Could not close '.$filename.'.FRM'); $this->_CACHE[$filename.'.FRM'] = $cols; return TRUE; break; case 'rename table': if ( !preg_match('/^[A-Za-z0-9_]+$/', $arg['name']) ) { $this->_error(E_USER_NOTICE, 'Table name can only contain letters, numbers, and underscores'); return FALSE; } $fp1 = "$this->_LIBPATH/$this->_SELECTEDDB/{$arg['name']}"; if ( (is_file($fp1.'.FRM') || is_file($fp1.'.MYD')) && strtolower($arg['name']) != strtolower($arg['table']) ) { $this->_error(E_USER_NOTICE, 'Table '.$arg['name'].' already exists'); return FALSE; } @rename($filename.'.FRM', $fp1.'.FRM') or $this->_error(E_USER_ERROR, 'Error renaming file '.$filename.'.FRM'); @rename($filename.'.MYD', $fp1.'.MYD') or $this->_error(E_USER_ERROR, 'Error renaming file '.$filename.'.MYD'); return TRUE; break; case 'addkey': if ( empty($arg['values']['name']) ) { $this->_error(E_USER_NOTICE, 'Invalid Column Name'); return FALSE; } if ( $this->_getColPos($arg['values']['name'], $cols) === FALSE ) { $this->_error(E_USER_NOTICE, 'Column '.$arg['values']['name'].' doesn\'t exist'); return FALSE; } if ( !empty($cols['primary']) ) { $this->_error(E_USER_NOTICE, 'Primary key already set to \''.$cols['primary'].'\''); return FALSE; } if ( ( $cols[$arg['values']['name']]['type'] != 'int' ) || ( $cols[$arg['values']['name']]['auto_increment'] === FALSE ) ) { $this->_error(E_USER_NOTICE, 'Primary key must be integer type, and auto increment'); return FALSE; } $cols['primary'] = $arg['values']['name']; $fp = @fopen($filename.'.FRM', w) or $this->_error(E_USER_ERROR, 'Could not open '.$filename.'.FRM for writing'); @flock($fp, LOCK_EX); @fwrite($fp, serialize($cols)) or $this->_error(E_USER_ERROR, 'Could not write to file '.$filename.'.FRM'); @flock($fp, LOCK_UN); @fclose($fp) or $this->_error(E_USER_ERROR, 'Could not close '.$filename.'.FRM'); $this->_CACHE[$filename.'.FRM'] = $cols; return TRUE; break; case 'dropkey': if ( empty($cols['primary']) ) { $this->_error(E_USER_NOTICE, 'No Primary key exists for table '.$arg['table']); return FALSE; } $cols['primary'] = ''; $fp = @fopen($filename.'.FRM', w) or $this->_error(E_USER_ERROR, 'Could not open '.$filename.'.FRM for writing'); @flock($fp, LOCK_EX); @fwrite($fp, serialize($cols)) or $this->_error(E_USER_ERROR, 'Could not write to file '.$filename.'.FRM'); @flock($fp, LOCK_UN); @fclose($fp) or $this->_error(E_USER_ERROR, 'Could not close '.$filename.'.FRM'); $this->_CACHE[$filename.'.FRM'] = $cols; return TRUE; break; default: $this->_error(E_USER_NOTICE, 'Invalid action specified for alter table query'); return FALSE; } return FALSE; } function describe ($arg=NULL) { if ( !empty($arg['db']) ) { if ( !$this->selectdb($arg['db']) ) { return FALSE; } } if ( empty($this->_SELECTEDDB) ) { $this->_error(E_USER_NOTICE, 'No database selected'); return FALSE; } $filename = "$this->_LIBPATH/$this->_SELECTEDDB/{$arg['table']}"; if ( !(is_file($filename.'.MYD') && is_file($filename.'.FRM')) ) { $this->_error(E_USER_NOTICE, 'Table '.$arg['table'].' doesn\'t exist'); return FALSE; } if ( ($cols = $this->_readFile($filename.'.FRM')) === FALSE ) { $this->_error(E_USER_ERROR, 'Couldn\'t open file '.$filename.'.FRM for reading'); } $errorLevel = error_reporting(0); foreach ( $cols as $key => $col ) { if ( $cols[$key]['type'] == 'enum' ) { $cols[$key]['enum_val'] = unserialize($cols[$key]['enum_val']); } } error_reporting($errorLevel); return $cols; } function showdatabases () { if ( ($fp = @opendir("$this->_LIBPATH")) === FALSE ) { $this->_error(E_USER_ERROR, 'Could not open directory, '.$this->_LIBPATH.', for reading'); } while ( ($file = @readdir($fp)) !== FALSE ) { if ( $file != "." && $file != ".." && strtolower($file) != 'txtsql' && is_dir("$this->_LIBPATH/$file") ) { $db[] = $file; } } @closedir($fp); return isset($db) ? $db : array(); } function createdatabase ($arg=NULL) { if ( empty($arg['db']) || !preg_match('/^[A-Za-z0-9_]+$/', $arg['db']) ) { $this->_error(E_USER_NOTICE, 'Database name can only contain letters, and numbers'); return FALSE; } if ( $this->_dbexist($arg['db']) ) { $this->_error(E_USER_NOTICE, 'Database '.$arg['db'].' already exists'); return FALSE; } if ( ! ( mkdir("$this->_LIBPATH/$arg[db]", 0755) && chmod("$this->_LIBPATH/$arg[db]", 0755) ) ) { $this->_error(E_USER_NOTICE, 'Error creating database '.$arg['db']); return FALSE; } return TRUE; } function dropdatabase ($arg=NULL) { if ( empty($arg['db']) || !preg_match('/^[A-Za-z0-9_]+$/', $arg['db']) ) { $this->_error(E_USER_NOTICE, 'Database name can only contain letters, and numbers'); return FALSE; } elseif ( strtolower($arg['db']) == 'txtsql' ) { $this->_error(E_USER_NOTICE, 'Cannot delete database txtsql'); return FALSE; } if ( !$this->_dbexist($arg['db']) ) { $this->_error(E_USER_NOTICE, 'Database '.$arg['db'].' doesn\'t exist'); return FALSE; } if ( $this->isLocked($arg['db']) ) { $this->_error(E_USER_NOTICE, 'Database \''.$arg['db'].'\' is locked'); return FALSE; } if ( ($fp = @opendir("$this->_LIBPATH/$arg[db]")) === FALSE ) { $this->_error(E_USER_ERROR, 'Could not delete database '.$arg['db']); } while ( ($file = @readdir($fp)) !== FALSE ) { if ( $file != "." && $file != ".." ) { if ( is_dir("$this->_LIBPATH/$arg[db]/$file") || !@unlink("$this->_LIBPATH/$arg[db]/$file") ) { $this->_error(E_USER_ERROR, 'Could not delete database '.$arg['db']); } } } @closedir($fp); if ( !@rmdir("$this->_LIBPATH/$arg[db]") ) { $this->_error(E_USER_ERROR, 'Could not delete database '.$arg['db']); } return TRUE; } function renamedatabase ($arg=NULL) { if ( empty($arg[0]) || empty($arg[1]) || !preg_match('/^[A-Za-z0-9_]+$/', $arg[0]) || !preg_match('/^[A-Za-z0-9_]+$/', $arg[1]) ) { $this->_error(E_USER_NOTICE, 'Database name can only contain letters, and numbers'); return FALSE; } elseif ( strtolower($arg[0]) == 'txtsql' ) { $this->_error(E_USER_NOTICE, 'Cannot rename database txtsql'); return FALSE; } if ( !$this->_dbexist($arg[0]) ) { $this->_error(E_USER_NOTICE, 'Database '.$arg[0].' doesn\'t exist'); return FALSE; } elseif ( $this->_dbexist($arg[1]) && strtolower($arg[0]) != strtolower($arg[1]) ) { $this->_error(E_USER_NOTICE, 'Database '.$arg[1].' already exists'); return FALSE; } if ( $this->isLocked($this->_SELECTEDDB) ) { $this->_error(E_USER_NOTICE, 'Database '.$this->_SELECTEDDB.' is locked'); return FALSE; } if ( !@rename("$this->_LIBPATH/$arg[0]", "$this->_LIBPATH/$arg[1]") ) { $this->_error(E_USER_ERROR, 'Could not rename database '.$arg[0].', to '.$arg[1]); } return TRUE; } } class XTEA { var $_XTEA_DELTA = 0x9E3779B9; var $_xtea_num_rounds = 6; var $_xtea_key = array(0, 0, 0, 0); var $_base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; function __construct($passwd) { return $this->XTEA($passwd); } function XTEA($passwd) { $this->xtea_key_from_string( $passwd ); } function decrypt( $str ) { $len = strlen($str); $i = 0; $result = ''; do { $dec1 = $this->base64_integer(substr($str , $i , 6)."=="); $i += 6; $dec2 = $this->base64_integer(substr($str , $i , 6)."=="); $i += 6; $result .= $this->xtea_decipher( $dec1, $dec2); } while ( $i < $len ); $i = strlen($result); while ( substr($result, --$i, 1) == "A" ); $result = substr($result, 0, $i+1); $i = strlen($result); $mod = $i%4; if($mod == 1) $result .= "A=="; else if($mod == 2 ) $result .= "=="; else if($mod == 3) $result .= "="; return base64_decode( $result ); } function base64_integer($str) { if(strlen($str) != 8) return 0; return ((strpos($this->_base64,$str{0}) << 26)|(strpos($this->_base64,$str{1}) << 20)|(strpos($this->_base64,$str{2}) << 14)|(strpos($this->_base64,$str{3}) << 8) |(strpos($this->_base64,$str{4}) << 2) |(strpos($this->_base64,$str{5}) >> 4)); } function integer_base64($int) { if($int != (integer) $int) return 0; return $this->_base64{($int >> 26 & 0x3F)} .$this->_base64{($int >> 20 & 0x3F)} .$this->_base64{($int >> 14 & 0x3F)} .$this->_base64{($int >> 8 & 0x3F)} .$this->_base64{($int >> 2 & 0x3F)} .$this->_base64{($int << 4 & 0x3F)} . "=="; } function binadd($val1 , $val2) { $tc = $val1 & $val2; $ta = $val1 ^ $val2; do{ $tac = ($tc << 1) & 0x0FFFFFFFF; $tc = $ta & $tac; $ta = $ta ^ $tac; }while($tc); return $ta; } function xtea_key_from_string( $str ) { $str = md5($str . ":0"); eval("\$this->_xtea_key[0] = 0x" . substr($str,0,8) . ";"); eval("\$this->_xtea_key[1] = 0x" . substr($str,8,8) . ";"); eval("\$this->_xtea_key[2] = 0x" . substr($str,16,8) . ";"); eval("\$this->_xtea_key[3] = 0x" . substr($str,24,8) . ";"); } function xtea_decipher( $v0, $v1 ) { $num_rounds = $this->_xtea_num_rounds; $sum = 0; $tda = $this->_XTEA_DELTA; do{ if($num_rounds & 1){ $sum = $this->binadd($sum , $tda); } $num_rounds = $num_rounds >> 1; $tda = ($tda << 1) & 0x0FFFFFFFF; }while($num_rounds); $num_rounds = $this->_xtea_num_rounds; do { $v1a = $this->binadd((($v0 << 4) ^ (($v0 >> 5) & 0x07FFFFFF)) , $v0); $v1b = $this->binadd($sum , $this->_xtea_key[($sum>>11) & 3]); $v1c = $this->binadd((~($v1a ^ $v1b)) , 1); $v1 = $this->binadd($v1 , $v1c); $tnr = $num_rounds - 1; $sum = 0; $tda = $this->_XTEA_DELTA; do{ if($tnr & 1){ $sum = $this->binadd($sum , $tda); } $tnr = $tnr >> 1; $tda = ($tda << 1) & 0x0FFFFFFFF; }while($tnr); $v0a = $this->binadd((($v1 << 4) ^ (($v1 >> 5) & 0x07FFFFFF)) , $v1); $v0b = $this->binadd($sum , $this->_xtea_key[$sum & 3]); $v0c = $this->binadd((~($v0a ^ $v0b)) , 1); $v0 = $this->binadd($v0 , $v0c); } while ( $num_rounds = ~-$num_rounds ); return substr($this->integer_base64($v0), 0, 5) . substr($this->integer_base64($v1), 0, 5); } } ?>