Вход Регистрация
Файл: txtSQL.class.php
Строк: 1261
<?php
/************************************************************************
* txtSQL                                                 ver. 2.2.1 SE  *
*************************************************************************
* A php class of functions which simulats, and acts almost like a mySQL *
* service                                                               *
*-----------------------------------------------------------------------*
* This program is free software; you can redistribute it and/or         *
* modify it under the terms of the GNU General Public License           *
* as published by the Free Software Foundation; either version 2        *
* of the License, or (at your option) any later version.                *
*                                                                       *
* This program is distributed in the hope that it will be useful,       *
* but WITHOUT ANY WARRANTY; without even the implied warranty of        *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
* GNU General Public License for more details.                          *
*                                                                       *
* You should have received a copy of the GNU General Public License     *
* along with this program; if not, write to the Free Software           *
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307 *
* USA.                                                                  *
*-----------------------------------------------------------------------*
*  NOTE- Tab size in this file: 8 spaces/tab                            *
*-----------------------------------------------------------------------*
*  ©2003 Faraz Ali, ChibiGuy Production [http://txtsql.sourceforge.net] *
*  File: txtsql.core.php                                                *
*                                                                       *
*  Siteman Secure Filewriting 2.1 implemented by Helge Langen           *
*  http://sitem.sourceforge.net                                         *
************************************************************************/
if ( !defined("TXTSQL_CORE_PATH") )
{
    
define('TXTSQL_CORE_PATH''./');
}
require_once(
TXTSQL_CORE_PATH.'/txtSQL.core.php');

/**
 * Extracts data from a flatfile database via a limited SQL
 *
 * @package txtSQL
 * @author Faraz Ali <Faraz87@comcast.net>
 * @version 2.2 Final
 * @access public
 */
class txtSQL
{
    
/**
     * If set to true, prints all errors and warnings
     * @var bool
     * @access public
     * @see strict()
     */
    
var $_STRICT        TRUE;

    
/**
     * Holds the path of the txtSQL data directory
     * @var string
     * @access private
     */
    
var $_LIBPATH       NULL;

    
/**
     * Holds the name of the currently logged in user
     * @var string
     * @access private
     * @see _isconnected()
     */
    
var $_USER          NULL;

    
/**
     * Holds the md5() hash of the password of the currently logged in user
     * @var string
     * @access private
     * @see _isconnected()
     * @see disconnect()
     */
    
var $_PASS          NULL;

    
/**
     * Contains a cache of any files that have been read to increase execution time
     * @var array
     * @access private
     * @see readFile()
     */
    
var $_CACHE         = array();

    
/**
     * Holds the name of the currently selected database
     * @var string
     * @access private
     * @see selectdb()
     */
    
var $_SELECTEDDB    NULL;

    
/**
     * Holds the number of queries sent to txtSQL
     * @var int
     * @access private
     * @see query_count()
     */
    
var $_QUERYCOUNT    0;

    
/**
     * The constructor of the txtSQL class
     * @param string $path The path to which the databases are located
     * @return void
     * @access public
     */
    
function txtSQL ($path='./data')
    {
        
$this->_LIBPATH $path;
        return 
TRUE;
    }

    
/**
     * Connects a user to the txtSQL service
     * @param string $user The username of the user
     * @param string $pass The corressponding password of the user
     * @return void
     * @access public
     */
    
function connect ($user$pass)
    {
        
/* Check to see if our data exists */
        
if ( !is_dir($this->_LIBPATH) )
        {
            
$this->_error(E_USER_ERROR'Invalid data directory specified');
        }

        
/* Instantiate parser and core class */
        
$this->_query            = new txtSQLCore;
        
$this->_query->_LIBPATH  $this->_LIBPATH;

        
/* Read in the user/pass information */
        
if ( ($DATA $this->_readFile("$this->_LIBPATH/txtsql/txtsql.MYI")) === FALSE )
        {
            
$this->_error(E_USER_WARNING'Database file is corrupted!');
            return 
FALSE;
        }
        
$this->_data $DATA;

        
/* Check to see if the username exists, and for a matching password */
        
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;
    }

    
/**
     * Disconnects a user from the txtSQL Service
     * @return void
     * @access public
     */
    
function disconnect ()
    {
        
/* Check to see that we are already connected */
        
if( !$this->_isconnected() )
        {
            
$this->_error(E_USER_NOTICE'Can only disconnect when connected!');
            return 
FALSE;
        }

        
/* Unset user, pass variables
         * Then remove the core executer object and the parser object
         * And finally return */
        
unset($this->_USER$this->_PASS$this->_query);
        return 
TRUE;
    }

    
/**
     * Selects rows of information from a selected database and a table
     * that fits the given 'where' clause
     * @param mixed $arguments The arguments in form of "[$key] => $value"
     *                         where $key can be 'db', 'table', 'select', 'where', 'limit'
     *                         and 'orderby'
     * @return mixed $results An array that txtSQL returns that matches the given criteria
     * @access public
     */
    
function select ($arguments)
    {
        
/* Check for a connection, and valid arguments */
        
$this->_validate($arguments);
        
$this->_QUERYCOUNT++;

        return 
$this->_query->select($arguments);
    }

    
/**
     * Inserts a new row into a table with the given information
     * @param mixed $arguments The arguments in form of "[$key] => $value"
     *                         where $key can be 'db', 'table', 'values'
     * @return int $inserted The number of rows inserted into the table
     * @access public
     */
    
function insert ($arguments)
    {
        
/* Check for a connection, and valid arguments */
        
$this->_validate($arguments);
        
$this->_QUERYCOUNT++;

        return 
$this->_query->insert($arguments);
    }

    
/**
     * Updates a row that matches a 'where' clause, with new information
     * @param mixed $arguments The arguments in form of "[$key] => $value"
     *                         where $key can be 'db', 'table', 'where', 'limit',
     *                         and 'values'
     * @return int $inserted The number of rows updated
     * @access public
     */
    
function update ($arguments)
    {
        
/* Check for a connection, and valid arguments */
        
$this->_validate($arguments);
        
$this->_QUERYCOUNT++;

        return 
$this->_query->update($arguments);
    }

    
/**
     * Deletes a row from a table that matches a 'where' clause
     * @param mixed $arguments The arguments in form of "[$key] => $value"
     *                         where $key can be 'db', 'table', 'where', 'limit'
     * @return int $inserted The number of rows deleted
     * @access public
     */
    
function delete ($arguments)
    {
        
/* Check for a connection, and valid arguments */
        
$this->_validate($arguments);
        
$this->_QUERYCOUNT++;

        return 
$this->_query->delete($arguments);
    }

    
/**
     * Returns a list containing the current valid txtSQL databases
     * @return mixed $databases A list containing the databases
     * @access public
     */
    
function showdbs ()
    {
        
/* Check for a connection, and valid arguments */
        
$this->_validate(array());
        
$this->_QUERYCOUNT++;

        return 
$this->_query->showdatabases();
    }

    
/**
     * Creates a new database
     * @param mixed $arguments The arguments in form of "[$key] => $value"
     *                         where $key can be 'db'
     * @return void
     * @access public
     */
    
function createdb ($arguments)
    {
        
/* Check for a connection, and valid arguments */
        
$this->_validate($arguments);
        
$this->_QUERYCOUNT++;

        return 
$this->_query->createdatabase($arguments);
    }

    
/**
     * Drops a database
     * @param mixed $arguments The arguments in form of "[$key] => $value"
     *                         where $key can be 'db'
     * @return void
     * @access public
     */
    
function dropdb ($arguments)
    {
        
/* Check for a connection, and valid arguments */
        
$this->_validate($arguments);
        
$this->_QUERYCOUNT++;

        return 
$this->_query->dropdatabase($arguments);
    }

    
/**
     * Renames a database
     * @param mixed $arguments The arguments in form of "[old db name], [new db name]"
     * @return void
     * @access public
     */
    
function renamedb ($arguments)
    {
        
/* Check for a connection, and valid arguments */
        
$this->_validate($arguments);
        
$this->_QUERYCOUNT++;

        return 
$this->_query->renamedatabase($arguments);
    }

    
/**
     * Returns an array containing a list of tables inside of a database
     * @param mixed $arguments The arguments in form of "[$key] => $value"
     *                         where $key can be 'db'
     * @return mixed $tables   An array with a list of tables
     * @access public
     */
    
function showtables ($arguments)
    {
        
/* Check for a connection, and valid arguments */
        
$this->_validate($arguments);
        
$this->_QUERYCOUNT++;

        return 
$this->_query->showtables($arguments);
    }

    
/**
     * Creates a new table with the given criteria inside a database
     * @param mixed $arguments The arguments in form of "[$key] => $value"
     *                         where $key can be 'db', 'table', 'columns'
     * @return int $deleted The number of rows deleted
     * @access public
     */
    
function createtable ($arguments)
    {
        
/* Check for a connection, and valid arguments */
        
$this->_validate($arguments);
        
$this->_QUERYCOUNT++;

        return 
$this->_query->createtable($arguments);
    }

    
/**
     * Drops a table from a database
     * @param mixed $arguments The arguments in form of "[$key] => $value"
     *                         where $key can be 'db', 'table'
     * @return void
     * @access public
     */
    
function droptable ($arguments)
    {
        
/* Check for a connection, and valid arguments */
        
$this->_validate($arguments);
        
$this->_QUERYCOUNT++;

        return 
$this->_query->droptable($arguments);
    }

    
/**
     * Alters a database by working with its columns
     * @param mixed $arguments The arguments in form of "[$key] => $value"
     *                         where $key can be 'db', 'table', 'action',
     *                         'name', and 'values'
     * @return void
     * @access public
     */
    
function altertable ($arguments)
    {
        
/* Check for a connection, and valid arguments */
        
$this->_validate($arguments);
        
$this->_QUERYCOUNT++;

        return 
$this->_query->altertable($arguments);
    }

    
/**
     * Returns a description of a table using an array
     * @param mixed $arguments The arguments in form of "[$key] => $value"
     *                         where $key can be 'db', 'table'
     * @return int $columns An array with the description of a table
     * @access public
     */
    
function describe ($arguments)
    {
        
/* Check for a connection, and valid arguments */
        
$this->_validate($arguments);
        
$this->_QUERYCOUNT++;

        return 
$this->_query->describe($arguments);
    }

    
/**
     * Checks for a connection, and valid arguments
     * @param mixed $arguments The arguments to validify
     * @return void
     * @access private
     */
    
function _validate ($arguments)
    {
        
/* Check to see user is connected */
        
if ( !$this->_isconnected() )
        {
            
$this->_error(E_USER_NOTICE'Can only perform queries when connected!');
            return 
FALSE;
        }

        
/* Arguments have to be inside of an array */
        
if ( !empty($arguments) && !is_array($arguments) )
        {
            
$this->_error(E_USER_ERROR'txtSQL can only accept arguments in an array');
        }

        return 
TRUE;
    }

    
/**
     * Evaluates a query with manually inputted arguments.
     * The $action can be either 'show databases', 'create databases', 'drop database', 'rename database'
     * 'show tables', 'create table', 'drop table', 'alter table', 'describe', 'select', 'insert', 'delete',
     * and 'insert'. See the readme for more information.
     *
     * @param string $action The command txtSQL is to perform
     * @param mixed $arguments The arguments in form of "[$key] => $value"
     * @return mixed $results The results that txtSQL returned
     * @access public
     */
    
function execute ($action$arguments NULL)
    {
        
/* Check to see user is connected */
        
if ( !$this->_isconnected() )
        {
            
$this->_error(E_USER_NOTICE'Can only perform queries when connected!');
            return 
FALSE;
        }

        
/* If there is no action */
        
if ( empty($action) )
        {
            
$this->_error(E_USER_NOTICE'You have an error in your txtSQL query');
            return 
FALSE;
        }

        
/* Arguments have to be inside of an array */
        
if ( !empty($arguments) && !is_array($arguments) )
        {
            
$this->_error(E_USER_ERROR'txtSQL Can only accept arguments in an array');
        }

        
/* Depending on what type of action it is, then perform right query */
        
switch ( strtolower($action) )
        {
            
/* ----- Database Related ----- */
            
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;

            
/* ----- Table Related ----- */
            
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;

            
/* ----- Main functions ----- */
            
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;
        }

        
/* Return whatever results we got back */
        
$this->_QUERYCOUNT++;
        return isset(
$results) ? $results '';
    }

    
/**
     * Turns strict property of txtSQL off/on
     * @param bool $strict The value of the strict property
     * @return void
     * @access public
     */
    
function strict ($strict FALSE)
    {
        
$strict        = (bool) $strict;
        
$this->_STRICT $strict;

        if ( 
$this->_isconnected() )
        {
            
$this->_query->strict($strict);
        }
        return 
TRUE;
    }

    
/**
     * To set username and/or passwords, or create/delete users
     * @param string $action The action to perform (add, drop, edit)
     * @param string $user The username to be added/modified
     * @param string $pass The password of the username
     * @param string $pass1 The new password of the username (optional if editing)
     * @return void
     * @access public
     */
    
function grant_permissions($action$user$pass NULL$pass1 NULL)
    {
        
/* Are we connected? */
        
if ( !$this->_isconnected() )
        {
            
$this->_error(E_USER_NOTICE'Not connected');
            return 
FALSE;
        }

        
/* Can only work with strings */
        
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;
        }

        
/* Read in user database */
        
if ( ($DATA $this->_readFile("$this->_LIBPATH/txtsql/txtsql.MYI")) === FALSE )
        {
            
$this->_error(E_USER_WARNING'Database file is corrupted!');
            return 
FALSE;
        }

        
/* Need a username */
        
if ( empty($user) )
        {
            
$this->_error(E_USER_NOTICE'Forgot to input username');
            return 
FALSE;
        }

        
/* Perform the correct operation */
        
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;
        }

        
/* Save the new information */
        
$this->writedata(serialize($DATA),"$this->_LIBPATH/txtsql/txtsql.MYI"'w') or $this->_error(E_USER_FATAL,  "Couldn't open $this->_LIBPATH/txtsql/txtsql.MYI for writing");

        
/* Save it in the cache */
        
$this->_CACHE["$this->_LIBPATH/txtsql/txtsql.MYI"] = $DATA;
        return 
TRUE;
    }

    
/**
     * Returns an array filled with a list of current txtSQL users
     * @return mixed $users
     * @access public
     */
    
function getUsers ()
    {
        
/* Are we connected? */
        
if ( !$this->_isconnected() )
        {
            
$this->_error(E_USER_NOTICE'Not connected');
            return 
FALSE;
        }

        
/* Read in user database */
        
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;
    }

    
/**
     * Check whether a database is locked or not
     * @param string $db The database to check
     * @return bool $locked Whether it is locked or not
     * @access public
     */
    
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;
    }

    /**
     * To put a file lock on the database
     * @param string $db The database to have a file lock placed on
     * @return void
     * @access public
     */
    function lockdb ($db)
    {
        /* Make sure that the user is connected */
        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;
    }

    /**
     * To remove a file lock from the database
     * @param string $db The database to have a file lock removed from
     * @return void
     * @access public
     */
    function unlockdb ($db)
    {
        /* Make sure that the user is connected */
        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;
    }

    
/**
     * To select a database for txtsql to use as a default
     * @param string $db The name of the database that is to be selected
     * @return void
     * @access public
     */
    
function selectdb ($db)
    {
        
/* Valid db name? */
        
if ( empty($db) )
        {
            
$this->_error(E_USER_NOTICE'Cannot select database '.$db);
            return 
FALSE;
        }

        
/* Does it exist? */
        
if ( !$this->_dbexist($db) )
        {
            
$this->_error(E_USER_NOTICE'Database '.$db.' doesn't exist');
            return FALSE;
        }

        /* Select the database */
        $this->_SELECTEDDB = $db;
        $this->_query->_SELECTEDDB = $db;
        return TRUE;
    }

    /**
     * An alias (but public) of the private function _tableexist()
     * @param $table Table to be checked for existence
     * @param $db The database the table is in
     * @return bool Whether it exists or not
     */
    function table_exists ($table, $db)
    {
        return $this->_tableexist($table, $db);
    }

    /**
     * An alias (public) of the private function _dbexist()
     * @param $table DB to be checked for existence
     * @return bool Whether it exists or not
     */
    function db_exists ($db)
    {
        return $this->_dbexist($db);
    }

    /**
     * To retrieve the number of records inside of a table
     * @param string $table The name of the table
     * @param string $database The database the table is inside of (optional)
     * @return int $count The number of records in the table
     * @access public
     */
    function table_count ($table, $database=NULL)
    {
        /* Inside of another database? */
        if ( !empty($database) )
        {
            if ( !$this->selectdb($database) )
            {
                return FALSE;
            }
        }

        /* No database or no table specified means that we stop here */
        if ( empty($this->_SELECTEDDB) || empty($table) )
        {
            $this->_error(E_USER_NOTICE, '
No database selected');
            return FALSE;
        }

        /* Does table exist? */
        $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;
        }

        
/* Read in the table's records */
        
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 the count */
        return $count;
    }

    /**
     * To retrieve the last ID generated by an auto_increment field in a table
     * @param string $table The name of the table
     * @param string $db The database the table is inside of (optional)
     * @return string $column Get the last ID generated by this column instead of the priamry key (optional)
     * @access public
     */
    function last_insert_id( $table, $db = '', $column = '' )
    {
        /* Select a database if one is given */
        if ( !empty($db) )
        {
            if ( !$this->selectdb($db) )
            {
                return FALSE;
            }
        }

        /* Check for a selected database */
        if ( empty($this->_SELECTEDDB) )
        {
            $this->_error(E_USER_NOTICE, '
No database selected');
            return FALSE;
        }

        /* Read in the column definitions */
        if ( ( $cols = $this->_readFile("$this->_LIBPATH/$this->_SELECTEDDB/$table.FRM") ) === FALSE )
        {
            $this->_error(E_USER_NOTICE, '
Table "'.$table.'" doesn't exist');
            return 
FALSE;
        }

        
/* Check for a valid column that is auto_increment */
        
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;
        }

        /* If we are using the primary key, make sure it exists */
        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'];
    }

    /**
     * To return the number of queries sent to txtSQL
     * @return int $_QUERYCOUNT
     * @access public
     */
    function query_count()
    {
        return $this->_QUERYCOUNT;
    }

    /**
     * To print the last error that occurred
     * @return void
     * @access public
     */
    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>';
        }
    }

    /**
     * To return the last error that occurred
     * @return string $error The last error
     * @access public
     */
    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];
        }        
    }

    /**
     * To print any errors that occurred during script execution so far
     * @return void
     * @access public
     */
    function errordump()
    {
        /* No errors? */
        if ( empty($this->_ERRORS) && empty($this->_query->_ERRORS) )
        {
            echo '
No errors occurred during script execution';
            return TRUE;
        }

        /* Errors during this part of script */
        if ( !empty($this->_ERRORS) )
        {
            foreach ( $this->_ERRORS as $key => $value )
            {
                echo '
ERROR #['.$key.'] '.$value;
            
}
        }

        
/* Errors during query execution portion */
        
elseif ( !empty($this->_query->_ERRORS) )
        {
            foreach ( 
$this->_query->_ERRORS as $key => $value )
            {
                echo 
'ERROR #['.$key.'] '.$value;
            }
        }

        return 
TRUE;
    }

    
/**
     * Removes any cache that is being stored
     * @return void
     * @access public
     */
    
function emptyCache()
    {
        
$this->_CACHE = array();
        return 
TRUE;
    }

    
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////////////////////////////////
    /**
     * To retrieve the number of records inside of a table
     * @param int $errno The error type (number form)
     * @param string $errstr The error message that will be shown
     * @param string $errtype Prints this string before the message
     * @return void
     * @access private
     */
    
function _error ($errno$errstr$errtype=NULL)
    {
        
/* If this error is not an internal error, then generate a backtrace
         * to the line that originally caused the error */
        
$backtrace array_reverse(@debug_backtrace());
        
$errfile   $backtrace[0]['file'];
        
$errline   $backtrace[0]['line'];

        
/* Determine what kind of error this is, so we can display it. */
        
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;

        
/* Print the message to the screen, if strict is on */
        
$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 this is a fatal error, then we are forced to exit and stop execution */
        
if ( $errno == E_USER_ERROR )
        {
            exit;
        }
        return 
TRUE;
    }

    
/**
     * To Read a file into a string and return it
     * @param string $filename The path to the file needed to be opened
     * @param bool $useCache Whether to save/retrieve this file from a cache
     * @param bool $unserialize Whether to unserialize the string or not
     * @return string $contents The file's contents
     * @access private
     */
    
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;
    }

    
/**
     * Check to see whether a user is connected or not
     * @return bool $connected Whether the user is connected or not
     * @access private
     */
    
function _isconnected ()
    {
        
/* If either one of the user or pass vars are empty, then return false; */
        
if ( empty($this->_USER) )
        {
            return 
FALSE;
        }

        
/* Are we authenticated? */
        
if ( $this->_data[strtolower($this->_USER)] != md5($this->_PASS) )
        {
            return 
FALSE;
        }
        return 
TRUE;
    }

    
/**
     * To check whether a database exists or not
     * @param string $db The name of the database
     * @return bool Whether the db exists or not
     * @access private
     */
    
function _dbexist ($db)
    {
        return 
is_dir("$this->_LIBPATH/$db") ? TRUE FALSE;
    }

    
/**
     * To check whether a table exists or not
     * @param string $table The name of the table
     * @param string $db The name of the database the table is in
     * @return bool Whether the db exists or not
     * @access private
     */
    
function _tableexist ($table$db)
    {
        
/* Check to see if the database exists */
        
if ( !empty($db) )
        {
            if ( !
$this->selectdb($db) )
            {
                
$this->_error(E_USER_NOTICE'Database, ''.$db.'', doesn't exist');
                return FALSE;
            }
        }

        /* Check to see if the table exists */
        $filename = "$this->_LIBPATH/$this->_SELECTEDDB/$table";

        if ( is_file($filename.'
.MYD') && is_file($filename.'.FRM') )
        {
            return TRUE;
        }
        return FALSE;
    }

    /**
     * To build an if-statement which can be used to see if a row
     * fits the given credentials
     * @param mixed $where The array containing the where clause
     * @param mixed $cols The array containing the column definitions
     * @return string $query The string which contains the php-equivelent to the where clause
     * @access private
     */
    function _buildIf ($where, $cols)
    {
        /* We can only work with a string containing where */
        if ( !is_array($where) || empty($where) )
        {
            $this->_error(E_USER_NOTICE, '
Where clause must be an array');
            return FALSE;
        }
        $query = '';

        /* Start creating the query */
        foreach ( $where as $key => $value )
        {
            /* Are we on an '
and|or'? */
            if ( $key % 2 == 1 )
            {
                /* Check for a valid "and|or" */
                $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;
            }

            /* Find out which operator we are going to use to create the if
             * NOTE: I'
m pretty sure the order in which these operators are checked
             
*       are correct. If anyone notices a bug in the orderlet me know*/
            
$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:
                    
/* Check for a valid function that requires no operator */
                    
$val 'TRUE';
                    if ( 
substr(trim($value), 01) == '!' )
                    {
                        
$val   'FALSE';
                        
$value substr($valuestrpos($value'!')+1);
                    }

                    
$function substr($value0strpos($value'('));
                    
$col      substr($valuestrlen($function) + 1strlen($value) - strlen($function) - );

                    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;
                        }
                    }

                    
/* There is an error in your where clause */
                    
$this->_error(E_USER_NOTICE'You have an error in your where clause, (operators allowed: =, !=, <>, =~, !~, <, >, <=, >=)'); return FALSE;
            }

            
/* Split string by the proper operator, as long as there is an operator */
            
if ( !isset($function) )
            {
                list ( 
$col$val ) = explode($op$value2);
            }

            
/* Check to see if we are utilizing a function */
            
if ( substr_count($col'(') == && substr_count($col')') == )
            {
                
$function substr($col0strpos($col'('));

                if ( 
$val != '' && $col{strlen($col)-1}.$val{0} == "  " )
                {
                    
$col  substr($colstrlen($function) + 1strlen($col) - strlen($function) - ( ($col{strlen($col)-1} != " " ) ? ) )." ";
                    
$val  $val;
                }
                else
                {
                    
$col substr($colstrlen($function) + 1strlen($col) - strlen($function) - ( ($col{strlen($col)-1} != " " ) ? ) );
                }

                
/* Check for a valid function call */
                
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;

                    
/* These are functions that should NOT have an operator */
                    
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;
                }
            }

            /* What if the column name is primary? */
            if ( strtolower(trim($col)) == '
primary' )
            {
                /* Make sure there is a primary key */
                if ( empty($cols['
primary']) )
                {
                    $this->_error(E_USER_NOTICE, '
No primary key has been assigned to this table');
                    return FALSE;
                }
                $col = $cols['
primary'];
            }

            /* Does the specified column exist? */
            if ( ( $position = $this->_getColPos(rtrim($col), $cols) ) === FALSE )
            {
                $this->_error(E_USER_NOTICE, '
Column ''.rtrim($col).'' doesn't exist');
                return 
FALSE;
            }

            
/* Create/Add-To the queries */
            
$val str_replace("'""'"addslashes($val));
            
$val = ( $col{strlen($col)-1}.$val{0} == "  " ) ? substr($val1) : $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 )
            {
                
/* Test for equality */
                
case 1:
                case 
2$quotes = ( !is_numeric($val) || $cols[rtrim($col)]['type'] != 'int' ) ? '"' '';
                    
$query .= ' ( '.$f1.'$value['.$position.']'.$f2.' '.( $op == '=' '==' $op ).' '.$quotes.$val.$quotes.' ) ';
                    break;

                
/* Test using regex, with[out] a function */
                
case 3:    $val    str_replace(array('(',   ')',  '{',  '}''.',  '$',  '/',       '%',  '*',     '%''$$PERC$$'),
                                          array(
'('')''{''}''.''$''/''$$PERC$$''*''(.+)?',       '%'), $val);
                    
$query .= ' ( '.($op == '!~' '!' '').'preg_match("/^'.$val.'$/iU", '.$f1.'$value['.$position.']'.$f2.') ) ';
                    break;

                
/* Test involving a function */
                
case 4$query .= ' ( '.$f1.'$value['.$position.']'.$f2.' === '.$val.' ) ';
                        break;

                
/* Test involving a strpos with[out] function */
                
case 5$query .= ' ( strpos('.$f1.'' '.$value['.$position.']), ''.$val.'') '.(($op == '!?') ? '=' '!' ).'== FALSE ) ';
            }
            unset(
$function$f1$f2$quotes$position$val$col$op);
        }

        
/* Make sure that we have a valid query ending */
        
$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;
    }

    
/**
     * To retrieve the index of the column from the columns' array
     * @param string $colname The name of the column to be searched for
     * @param mixed $cols The column definitions array
     * @return int $position The index of the column in the array
     * @access private
     */
    
function _getColPos ($colname$cols)
    {
        
/* Make sure array is not empty, and the parameter is an array */
        
if ( empty($cols) || !is_array($cols) || !array_key_exists($colname$cols) )
        {
            return 
FALSE;
        }
        unset(
$cols['primary']);

        
/* Get the index for the column */
        
if ( ( $position array_search($colnamearray_keys($cols)) ) === FALSE )
        {
            return 
FALSE;
        }
        return 
$position;
    }

    
/**
     * To sort a multi-dimensional array by a key
     * @author fmmarzoa@gmx.net <fmmarzoa@gmx.net>
     * @param mixed $array The array to be sorted
     * @param string $num The name of the key to sort the array by
     * @return string $order Either a 'ASC' or 'DESC' for sorting order
     * @access private
     */
    
function _qsort($array$num 0$order "ASC"$left 0$right = -1)
    {
        if ( 
count($array) >= )
        {
            if ( 
$right == -)
            {
                
$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;
    }

    
/**
     * Does what unique_array() does but with multidimensional arrays
     * @param mixed $array The array that will be filtered
     * @param string $sub_key The $key that will be examined for duplicates
     */
    
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;
    }

    
/**
     * Returns the current txtSQL version
     * @return string $version The current version of txtSQL
     * @access public
     */
    
function version()
    {
        return 
'2.2.1 SE';
    }
    
    function 
writedata($data,$filename,$mode "w") {
        
$lockdir $filename.".lock";
        
$start explode(" ",microtime());
        
$starttime $start[1] . substr($start[0],2,3);
        
$diff 0;
        
$result FALSE;
        while (
$diff 1000) {
            if (@
mkdir($lockdir)) {
                
$fp fopen($filename,$mode);
                
flock($fp,LOCK_EX);
                
fwrite($fp,$data);
                
flock($fp,LOCK_UN);
                
fclose($fp);
                
rmdir($lockdir);
                
$diff 2000;
                
$result TRUE;
            }
            else {
                
$life time()-filemtime($lockdir);
                if (
$life 30) {
                    
rmdir($lockdir);
                }
                else {
                    
$time explode(" ",microtime());
                    
$nowtime $time[1] . substr($time[0],2,3);
                    
$diff $nowtime-$starttime;
                }
            }
        }
        return 
$result;
    }
}
?>
Онлайн: 2
Реклама