<?php
///////////////////////////////////////////
// Class to connect to a MySQL database
//
// Shawn Parker
// gipetto.dyndns.org
// scripts@topfroggraphics.com
//
// Distributed with no license or warranty.
//
// If you redistribute please do so with
// this statement included and with the
// usage suggestions at the bottom of
// this file intact.
//
// v.1.4 - 2006/03/06
//
// See bottom of file for usage suggestions
// and Changelog
//
///////////////////////////////////////////

class dbConnect 
    
{
        
/* CONFIGURATION */
        
        // set some default connection values
        
var $host '';                                // database server - FQDN or IP address
        
var $username '';                            // default read-only username
        
var $password '';                            // default read-only password
        
var $database '';                            // default table
        
var $write_username '';                    // set to username of write enabled user
        
var $write_password '';                    // set to password of write enabled user
        
var $persistent False;                    // set to True to default to persistent connections
        
var $type 'read';                            // set default type to read only 

        // set default error reporting values
        
var $error_to '';                            // recipient of error emails
        
var $error_from '';                        // who the error emails should be from
        
var $error_subject 'SQL ERROR';            // subject line for error emails
        
var $show_all_errors False;                // wether to show all PHP/SQL errors or not
        
        // flag to allow or deny override abilites at runtime
        
var $allow_override True;                    // defaults to allow override. Set to false to lock in the above values
        
        // first few octals of and address range that it is OK to show errors to
        
var $display_error_to = array('127.0.0.1');
        
        
/* END CONFIGURATION */
        
        
var $con;
        var 
$result;
        var 
$query;
        
        
// php4 constructor simulator
        
function dbConnect($settings=array())
            {
                if(
phpversion('tidy') < 5)
                    {
                        
// construct
                        
$argcv func_get_args();
                        
call_user_func_array(array(&$this'__construct'), $argcv);
                        
                        
// destruct
                        
register_shutdown_function(array(&$this), '__destruct');
                    }
            }
        
        
        
// constructor to bring in and initialize vars
        
function __construct($settings=array())
            {
                if(
$this->allow_override == True)
                    {
                        if(isset(
$settings['username']) && $settings['username'] != NULL
                            
$this->username $settings['username'];
                        if(isset(
$settings['password']) && $settings['password'] != NULL
                            
$this->password $settings['password'];
                        if(isset(
$settings['write_username']) && $settings['write_username'] != NULL)
                            
$this->write_username $settings['write_username'];
                        if(isset(
$settings['write_password']) && $settings['write_password'] != NULL
                            
$this->write_password $settings['write_password'];                
                        if(isset(
$settings['host']) && $settings['host'] != NULL
                            
$this->host $settings['host'];
                        if(isset(
$settings['database']) && $settings['database'] != NULL
                            
$this->database $settings['database'];
                        if(isset(
$settings['error_from']) && $settings['error_from'] != NULL
                            
$this->error_from $settings['error_from'];
                        if(isset(
$settings['error_to']) && $settings['error_to'] != NULL
                            
$this->error_to $settings['error_to'];
                        if(isset(
$settings['type']) && eregi('read|write',$settings['type']))
                            
$this->type $settings['type'];
                        if(isset(
$settings['persistent']) && is_bool($settings['persistent']))
                            
$this->persistent $settings['persistent'];
                        if(isset(
$settings['show_all_errors']) && is_bool($settings['show_all_errors']))
                            
$this->show_all_errors $settings['show_all_errors'];
                    }

                
$p '<p><strong>'$cp "</strong></p>\n";

                
// die if required parameters are not defined
                
if($this->username == NULL)
                    die (
$p.'No Username defined'.$cp);
                if(
$this->host == NULL)
                    die (
$p.'No database host defined'.$cp);
                if(
$this->password == NULL)
                    die (
$p.'No database password provided'.$cp);
                if(
$this->database == NULL)
                    die (
$p.'No database name provided'.$cp);
                if(
$this->type == 'write' && $this->write_username == NULL)
                    die (
$p.'No write-enabled Username Defined'.$cp);
                if(
$this->type == 'write' && $this->write_password == NULL)
                    die(
$p.'No write-enabled Password Defined'.$cp);                

                
// automatically connect to host
                
$this->hostConnect();
            }
            
        
// destructor
        
function __destruct()
            {
                
$this->closeCon();
            }

        
// connect to the host
        
function hostConnect()
            {
                
// connection type
                
$ctype = ($this->persistent == True 'mysql_pconnect' 'mysql_connect');
                
                
// set read or write
                
if($this->type == 'write')
                    {
                        
$u $this->write_username;
                        
$p $this->write_password;
                    }
                else
                    {
                        
$u $this->username;
                        
$p $this->password;
                    }
                
                
// connect
                
$this->con $ctype($this->host,$u,$p)
                    or die (
$this->error('Connecting to host'));

                
// select database
                
@mysql_select_db($this->database
                    or die(
$this->error('Database Select'));
            }

        
// prepare data for input using mysql_real_escape_string
        // this is better than add_slashes as it does not require processing of data on the way out...
        
function escapeData($d)
            {
                
// Stripslashes if magic quotes has already added them
                
if (get_magic_quotes_gpc()) 
                    {
                        
$d stripslashes($d);
                    }
                
                
// quote it out if its not an integer
                // specific to this connection so multiple connections can be maintained separately
                
if(!is_numeric($d))
                    {
                        
$d "'".mysql_real_escape_string($d,$this->con)."'";
                    }
                    
                
// send it back
                
return $d;
            }
            
        
// build a query from input data
        // function emulates sprintf with a for loop
        
function buildQuery($base)
            {
                
// count the passed arguments
                
$count func_num_args();
                
                
// get the passed arguments
                
$args func_get_args();
                
                
// run them all into an query string
                
for($i 1$i $count$i++)
                    {
                        
// replace placeholders with processed data
                        
$base str_replace('%'.$i$this->escapeData($args[$i]),$base);
                    }
                
                return 
$base;
                
            }

        
// query the database
        
function queryDB($q)
            {
                
$this->result mysql_query($q,$this->con
                    or die (
$this->error('Querying database. Query was: '.$q));
            }
        
        
//Query result functions
        
function affectedRows() 
            {
                return @
mysql_affected_rows($this->con);
            }
        function 
numRows() 
            {
                return @
mysql_num_rows($this->result);
            }
        function 
fetchObject() 
            {
                return @
mysql_fetch_object($this->resultMYSQL_ASSOC);
            }
        function 
fetchArray() 
            {
                return @
mysql_fetch_array($this->resultMYSQL_NUM);
            }
        function 
fetchAssoc() 
            {
                return @
mysql_fetch_assoc($this->result);
            }
        function 
fetchID()
            {
                return @
mysql_insert_id($this->con);
            }

        
// automatically loop results into arrays
        
function arrayAssoc()
            {
                while(
$row $this->fetchAssoc())
                    {
                        
$array[] = $row;
                    }
                return isset(
$array) ? $array NULL;
            }
        function 
arrayNum()
            {
                while(
$row $this->fetchArray())
                    {
                        
$array[] = $row;
                    }
                return isset(
$array) ? $array NULL;
            }
            
        
// mysql system info
        
function getInfo()
            {
                
$sys 'MySQL Client Info: '.@mysql_get_client_info()."\n<br />".
                       
'MySQL Server Info: '.@mysql_get_server_info()."\n<br />".
                       
'MySQL Host Info: '.@mysql_get_host_info()."\n<br />";
                       
                return 
$sys;
            }
            
        
// show available tables
        
function showTables()
            {
                
$tableinfo mysql_list_tables($this->database);
                
                while(
$row mysql_fetch_row($tableinfo))
                    {
                        
$array[] = $row[0];
                    }
                return 
$array;
            }

        
// free result for reuse
        
function freeResult()
            {
                @
mysql_free_result($this->result);
            }

        
// close db connection
        
function closeCon()
            {
                @
mysql_close($this->con);
            }
            
        
// error routine sends mail to admin & displays error to user
        
function error($z)
            {
                if(
$this->error_to != NULL)
                    {
                        
$error_message "Server: {$_SERVER['SERVER_NAME']}\n\n".
                                   
"Page: {$_SERVER['PHP_SELF']}\n\n".
                                   
"ON: {$z}\n\n".
                                   
"Error: ".mysql_error()."\n\n";

                        
$default_subject 'SQL Error Notification';
                
                        
$headers = (isset($this->error_from) && $this->error_from != NULL "From: ".$this->error_from '');
                        
$subject = (isset($this->error_subject) && $this->error_subject != NULL $this->error_subject $default_subject);
                
                        @
mail($this->error_to,$subject,$error_message,$headers);
                    }
                    
                foreach(
$this->display_error_to AS $ad)
                    {
                        if(
eregi($ad,$_SERVER['REMOTE_ADDR']))
                            {
                                
$show_match TRUE;
                            }
                    }
                
                
// send tame error to user - edit as needed to suit your needs.
                
return '<p><strong>There was an error querying the database.'.
                       
' We apologize for the inconvenience.'.
                       
//' The webmaster is being flogged as you read this.'.
                       
(isset($show_match) && $show_match == True || $this->show_all_errors == True '<br />Error: '.mysql_error() : '').
                       
'</strong></p>';
            }
            
        
// quick routine for popping out a returned array with <pre> formatting for easy reading
        
function printPre($array)
            {
                echo 
'<pre>'.print_r($array,true).'</pre>';
            }

    }
    
///////////////////////////////////////////
// Class to connect to a MySQL database
//
// Usage suggestions. Please leave these 
// instructions intact if you redistribute
// this file.
//
///////////////////////////////////////////
/*
    I built this class with simplicity and robustness in mind.
    I also wanted to include a couple of routines that I commonly use when
    pulling information from a database. There are a ton of scripts out
    there that do this but I wanted one built how I like to work. Hopefully
    this serves you well.
    
    Basic usage is just as with any other OOP script and db connection
    
            $db = &new dbConnect();
            $query = 'SELECT * FROM table';
            $db->queryDB($query);
            while($row = $db->fetchArray())
                {
                    echo 'data: '.$row[0];
                }
            $db->closeCon();
            
    A brief outline of the call methods:
    
            $db->fetchArray()    // will return an array row with numbered keys
            $db->fetchAssoc()    // will return an array row with associative keys matching the table field names
            $db->fetchObject()    // will return an object with properties that correspond to the fetched row
            $db->affectedRows()    // will return the number of rows affected by UPDATE, INSERT, & DELETE query
            $db->numRows()        // will return the number of rows affected by SELECT query only
            $db->fetchID()        // will return the auto-incremented id number for the previous INSERT query
            
    One of the things that I do almost exclusively with databse calls is to
    drop the data directly into an array. So I included 2 functions to do this
    automatically - one for associative arrays and one for a standard numbered array
    
            $db = &new dbConnect();
            $query = 'SELECT * FROM table';
            $db->queryDB($query);
            $array = $db->arrayAssoc();
            $db->closeCon();
    
    This class allows for the use of mysql_real_escape_string through a simplified function. Suggested usage is
    as follows if it is to be used alone:
            
            $query = sprintf("SELECT * FROM table WHERE email=%1 AND name=%2",
                             $this->escapeData($email),
                             $this->escapeData($name));
                            
    You can also have this class build the query for you and do the escaping string itself using the function
    below. It is not mandatory but can save some typing on long queries.
        
            $base_query = "SELECT * FROM table WHERE email=%1 AND name=%2";
            $query = $db->buildQuery($base_query,$var1,$var2,etc...);
    
    $array is now an associative array of the results of the database call ready
    to be used elsewhre in your program. Returns NULL on zero results returned.
    A brief outline of the array methods:
            
            $db->arrayAssoc()    // will return an associative array of the complete result set
            $db->arrayNum()        // will return a standard numbered array of the complete result set
            
    Also included are standard methods for freeing the result and closing the connection.
            
            $db->freeResult()    // clears the result for reuse during multiple queries per connection
            $db->closeCon()        // closes the database connection. Not needed if connection is persistent
            
    For finding out table information on the server there's a function to list all tables into an array
    
            $tables = $db->showTables();    // drops table list into an array
            
    For testing purposes I include a method for querying the server version
            
            $sys = $db->getInfo();    // returns information about the MySQL environment
    
    I also wanted the ability to temporarily override the settings in the 
    databases routine without having to set up another config file. I did this
    by enabling you to pass an array to the object when instantiating it.
    
    It is as simple as setting up an array of values. Below are the available 
    options. All are optional - you only need to include the settings you want to 
    override for this instantiation of the script.
    
            $settings = ('type' => 'write'                     // default is read only, set this to enable write user/pass
                         'persistent' => True                // default is non-persistent connection    
                         'host' => 'dbserver.domain.com',    // new database server address FQDN or IP address
                         'username' => 'my_username',        // new read only username to use instead
                         'password' => 'my_password',        // new read only password to use instead
                         'write_username' => 'w_user',        // new read / write username to use instead
                         'write_password' => 'w_pass',        // new read / write password to use instead
                         'database' => 'my_dbname',            // new database to select
                         'error_to' => 'me@domain.com',        // who to send error emails to
                         'error_from' => 'sv@domain.com',    // who the error emails will be from
                         'error_subject' => 'SQL ERROR',    // the subject line of the error message
                         'show_all_errors' => True);        // wether to show full SQL/PHP errors for this script. Default is false
                                                                 // True should only be used in testing environments
            
            $db = &new dbConnect($settings);
            and so on...
        
    The script contains an $allow_override value that can be set to false to 
    deny the ability to change settings at runtime. If you're in a shared environment
    and need to further protect this file consider changing the ownership of the file (chown)
    to the apache webserver user and revoke read privileges (chmod) all users except for the 
    apache webserver user or by putting the file into a directory that is only readable by the 
    apache webserver user.
            
    The script has a built in error reporter that will send an email to the
    you (or someone you designate) and show only a basic error to the user so 
    we don't give away any details about the config should an error occur. This
    requires a functioning mail server running on the machine. Leave these settings blank
    to disable email error reporting on this script.
    
    You can hard code addresses or partial IP strings to match and show complete errors to
    into the $display_error_to variable. The more specific you get the more you can fine tune it.
    A partial IP will let an IP range see the error while a specific IP will limit to a specific
    computer. An example of usage is:
    
            var $display_error_to = array('192.168','10.1.1.108');
    
    The email routine sends plain text emails only and I have no plans on integrating
    HTML formatting. Feel free to edit the email and error message to suit your needs.
    
    Last, but not least, is a little routine that I use a lot which outputs a given array with <pre>
    formatting. This is very useful for checking returned values without having to format any
    actual HTML code. Example:
    
            $array = array('apple','orange' => array('fruit','peel'));
            $db->printPre($array);
            
    will output
            
            Array
            (
                [0] => apple
                [orange] => Array
                        (
                            [0] => 'fruit'
                            [1] => 'peel'
                        }
            )
    
    Future plans: I would like to include features in the future for creating new tables and doing
    more advanced SQL operations.
    
    I accept any and all comments and criticism on my scripts. Please feel free to email me with
    any comments or concerns with this script even if its just to let me know that you found it
    useful enough to include in your site.
    
    
    CHANGELOG
    v.1.4 - 2006/03/06
        Updated to be a little more PHP 5 centric and still have PHP 4 backward 
        compatability with true constructors and destructors
    v.1.3 - 2005/09-12
        Added routines ( escapeData, buildQuery ) for processing mysql_real_escape_string - better than using 
        addslashes/stripslashes as the escaping is done by mySQL instead of PHP - more reliable as mySQL knows 
        what it needs a little bit better than PHP does at it better accounts for character encodings.
        
    v.1.2 - 2005/06/24
        Fixed arrayAssoc & arrayNum to return NULL if query has 0 results
    
    v.1.1 - 2005/06/19
        First major release
        
*/

?>