Server IP : 103.119.228.120 / Your IP : 3.135.189.25 Web Server : Apache System : Linux v8.techscape8.com 3.10.0-1160.119.1.el7.tuxcare.els2.x86_64 #1 SMP Mon Jul 15 12:09:18 UTC 2024 x86_64 User : nobody ( 99) PHP Version : 5.6.40 Disable Function : shell_exec,symlink,system,exec,proc_get_status,proc_nice,proc_terminate,define_syslog_variables,syslog,openlog,closelog,escapeshellcmd,passthru,ocinum cols,ini_alter,leak,listen,chgrp,apache_note,apache_setenv,debugger_on,debugger_off,ftp_exec,dl,dll,myshellexec,proc_open,socket_bind,proc_close,escapeshellarg,parse_ini_filepopen,fpassthru,exec,passthru,escapeshellarg,escapeshellcmd,proc_close,proc_open,ini_alter,popen,show_source,proc_nice,proc_terminate,proc_get_status,proc_close,pfsockopen,leak,apache_child_terminate,posix_kill,posix_mkfifo,posix_setpgid,posix_setsid,posix_setuid,dl,symlink,shell_exec,system,dl,passthru,escapeshellarg,escapeshellcmd,myshellexec,c99_buff_prepare,c99_sess_put,fpassthru,getdisfunc,fx29exec,fx29exec2,is_windows,disp_freespace,fx29sh_getupdate,fx29_buff_prepare,fx29_sess_put,fx29shexit,fx29fsearch,fx29ftpbrutecheck,fx29sh_tools,fx29sh_about,milw0rm,imagez,sh_name,myshellexec,checkproxyhost,dosyayicek,c99_buff_prepare,c99_sess_put,c99getsource,c99sh_getupdate,c99fsearch,c99shexit,view_perms,posix_getpwuid,posix_getgrgid,posix_kill,parse_perms,parsesort,view_perms_color,set_encoder_input,ls_setcheckboxall,ls_reverse_all,rsg_read,rsg_glob,selfURL,dispsecinfo,unix2DosTime,addFile,system,get_users,view_size,DirFiles,DirFilesWide,DirPrintHTMLHeaders,GetFilesTotal,GetTitles,GetTimeTotal,GetMatchesCount,GetFileMatchesCount,GetResultFiles,fs_copy_dir,fs_copy_obj,fs_move_dir,fs_move_obj,fs_rmdir,SearchText,getmicrotime MySQL : ON | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /usr/share/awl/inc/ |
Upload File : |
<?php /** * @package awl * @subpackage AwlDatabase * @author Andrew McMillan <andrew@morphoss.com> * @copyright Morphoss Ltd * @license http://gnu.org/copyleft/gpl.html GNU GPL v3 or later * @compatibility Requires PHP 5.1 or later */ require_once('AwlDatabase.php'); /** * Database query class and associated functions * * This subpackage provides some functions that are useful around database * activity and an AwlQuery class to simplify handling of database queries. * * The class is intended to be a very lightweight wrapper with no pretentions * towards database independence, but it does include some features that have * proved useful in developing and debugging web-based applications: * - All queries are timed, and an expected time can be provided. * - Parameters replaced into the SQL will be escaped correctly in order to * minimise the chances of SQL injection errors. * - Queries which fail, or which exceed their expected execution time, will * be logged for potential further analysis. * - Debug logging of queries may be enabled globally, or restricted to * particular sets of queries. * - Simple syntax for iterating through a result set. * * This class is intended as a transitional mechanism for moving from the * PostgreSQL-specific Pg Query class to something which uses PDO in a more * replaceable manner. * */ /** * Connect to the database defined in the $c->db_connect[] (or $c->pg_connect) arrays */ function _awl_connect_configured_database() { global $c, $_awl_dbconn; /** * Attempt to connect to the configured connect strings */ $_awl_dbconn = false; if ( isset($c->db_connect) ) { $connection_strings = $c->db_connect; } elseif ( isset($c->pg_connect) ) { $connection_strings = $c->pg_connect; } foreach( $connection_strings AS $k => $v ) { $dbuser = null; $dbpass = null; if ( is_array($v) ) { $dsn = $v['dsn']; if ( isset($v['dbuser']) ) $dbuser = $v['dbuser']; if ( isset($v['dbpass']) ) $dbpass = $v['dbpass']; } elseif ( preg_match( '/^(\S+:)?(.*)( user=(\S+))?( password=(\S+))?$/', $v, $matches ) ) { $dsn = $matches[2]; if ( isset($matches[1]) && $matches[1] != '' ) { $dsn = $matches[1] . $dsn; } else { $dsn = 'pgsql:' . $dsn; } if ( isset($matches[4]) && $matches[4] != '' ) $dbuser = $matches[4]; if ( isset($matches[6]) && $matches[6] != '' ) $dbpass = $matches[6]; } if ( $_awl_dbconn = new AwlDatabase( $dsn, $dbuser, $dbpass, (isset($c->use_persistent) && $c->use_persistent ? array(PDO::ATTR_PERSISTENT => true) : null) ) ) break; } if ( ! $_awl_dbconn ) { echo <<<EOERRMSG <html><head><title>Database Connection Failure</title></head><body> <h1>Database Error</h1> <h3>Could not connect to database</h3> </body> </html> EOERRMSG; exit; } if ( isset($c->db_schema) && $c->db_schema != '' ) { $_awl_dbconn->SetSearchPath( $c->db_schema . ',public' ); } $c->_awl_dbversion = $_awl_dbconn->GetVersion(); } /** * The AwlQuery Class. * * This class builds and executes SQL Queries and traverses the * set of results returned from the query. * * <b>Example usage</b> * <code> * $sql = "SELECT * FROM mytable WHERE mytype = ?"; * $qry = new AwlQuery( $sql, $myunsanitisedtype ); * if ( $qry->Exec("typeselect", __line__, __file__ ) * && $qry->rows > 0 ) * { * while( $row = $qry->Fetch() ) { * do_something_with($row); * } * } * </code> * * @package awl */ class AwlQuery { /**#@+ * @access private */ /** * Our database connection, normally copied from a global one * @var resource */ protected $connection; /** * The original query string * @var string */ protected $querystring; /** * The actual query string, after we've replaced parameters in it * @var string */ protected $bound_querystring; /** * The current array of bound parameters * @var array */ protected $bound_parameters; /** * The PDO statement handle, or null if we don't have one yet. * @var string */ protected $sth; /** * Result of the last execution * @var resource */ protected $result; /** * number of current row - use accessor to get/set * @var int */ protected $rownum = null; /** * number of rows from pg_numrows - use accessor to get value * @var int */ protected $rows; /** * The Database error information, if the query fails. * @var string */ protected $error_info; /** * Stores the query execution time - used to deal with long queries. * should be read-only * @var string */ protected $execution_time; /**#@-*/ /**#@+ * @access public */ /** * Where we called this query from so we can find it in our code! * Debugging may also be selectively enabled for a $location. * @var string */ public $location; /** * How long the query should take before a warning is issued. * * This is writable, but a method to set it might be a better interface. * The default is 5 seconds, which can be overridden by setting a value * for $c->default_query_warning_threshold * @var double */ public $query_time_warning = 5; /**#@-*/ /** * Constructor * @param string The query string in PDO syntax with replacable '?' characters or bindable parameters. * @param mixed The values to replace into the SQL string. * @return The AwlQuery object */ function __construct() { global $_awl_dbconn, $c; $this->rows = null; $this->execution_time = 0; $this->error_info = null; if ( isset($c->default_query_warning_threshold) ) { $this->query_time_warning = $c->default_query_warning_threshold; } $this->rownum = -1; if ( isset($_awl_dbconn) ) $this->connection = $_awl_dbconn; else $this->connection = null; $argc = func_num_args(); $args = func_get_args(); $this->querystring = array_shift($args); if ( 1 < $argc ) { if ( is_array($args[0]) ) $this->bound_parameters = $args[0]; else $this->bound_parameters = $args; // print_r( $this->bound_parameters ); } return $this; } /** * Use a different database connection for this query * @param resource $new_connection The database connection to use. */ function SetConnection( $new_connection, $options = null ) { if ( is_string($new_connection) || is_array($new_connection) ) { $dbuser = null; $dbpass = null; if ( is_array($new_connection) ) { $dsn = $new_connection['dsn']; if ( isset($new_connection['dbuser']) ) $dbuser = $new_connection['dbuser']; if ( isset($new_connection['dbpass']) ) $dbpass = $new_connection['dbpass']; } elseif ( preg_match( '/^(\S+:)?(.*)( user=(\S+))?( password=(\S+))?$/', $new_connection, $matches ) ) { $dsn = $matches[2]; if ( isset($matches[1]) && $matches[1] != '' ) { $dsn = $matches[1] . $dsn; } else { $dsn = 'pgsql:' . $dsn; } if ( isset($matches[4]) && $matches[4] != '' ) $dbuser = $matches[4]; if ( isset($matches[6]) && $matches[6] != '' ) $dbpass = $matches[6]; } if ( ! $new_connection = new AwlDatabase( $dsn, $dbuser, $dbpass, $options ) ) return; } $this->connection = $new_connection; return $new_connection; } /** * Get the current database connection for this query */ function GetConnection() { return $this->connection; } /** * Log query, optionally with file and line location of the caller. * * This function should not really be used outside of AwlQuery. For a more * useful generic logging interface consider calling dbg_error_log(...); * * @param string $locn A string identifying the calling location. * @param string $tag A tag string, e.g. identifying the type of event. * @param string $string The information to be logged. * @param int $line The line number where the logged event occurred. * @param string $file The file name where the logged event occurred. */ function _log_query( $locn, $tag, $string, $line = 0, $file = "") { // replace more than one space with one space $string = preg_replace('/\s+/', ' ', $string); if ( ($tag == 'QF' || $tag == 'SQ') && ( $line != 0 && $file != "" ) ) { dbg_error_log( "LOG-$locn", " Query: %s: %s in '%s' on line %d", ($tag == 'QF' ? 'Error' : 'Possible slow query'), $tag, $file, $line ); } while( strlen( $string ) > 0 ) { dbg_error_log( "LOG-$locn", " Query: %s: %s", $tag, substr( $string, 0, 240) ); $string = substr( "$string", 240 ); } } /** * Quote the given string so it can be safely used within string delimiters * in a query. To be avoided, in general. * * @param mixed $str Data to be converted to a string suitable for including as a value in SQL. * @return string NULL, TRUE, FALSE, a plain number, or the original string quoted and with ' and \ characters escaped */ public static function quote($str = null) { global $_awl_dbconn; if ( !isset($_awl_dbconn) ) { _awl_connect_configured_database(); } return $_awl_dbconn->Quote($str); } /** * Bind some parameters. This can be called in three ways: * 1) As Bind(':key','value), when using named parameters * 2) As Bind('value'), when using ? placeholders * 3) As Bind(array()), to overwrite the existing bound parameters. The array may * be ':name' => 'value' pairs or ordinal values, depending on whether the SQL * is using ':name' or '?' style placeholders. * * @param mixed $args See details above. */ function Bind() { $argc = func_num_args(); $args = func_get_args(); if ( $argc == 1 ) { if ( gettype($args[0]) == 'array' ) { $this->bound_parameters = $args[0]; } else { $this->bound_parameters[] = $args[0]; } } else { $this->bound_parameters[$args[0]] = $args[1]; } } /** * Tell the database to prepare the query that we will execute */ function Prepare() { global $c; if ( isset($this->sth) ) return; // Already prepared if ( isset($c->expand_pdo_parameters) && $c->expand_pdo_parameters ) return; // No-op if we're expanding internally if ( !isset($this->connection) ) { _awl_connect_configured_database(); $this->connection = $GLOBALS['_awl_dbconn']; } $this->sth = $this->connection->prepare( $this->querystring ); if ( ! $this->sth ) { $this->error_info = $this->connection->errorInfo(); } else $this->error_info = null; } /** * Tell the database to execute the query */ function Execute() { global $c; if ( !isset($this->connection) ) { _awl_connect_configured_database(); $this->connection = $GLOBALS['_awl_dbconn']; } if ( !is_object($this->connection) ) throw new Exception('Database not connected.'); if ( isset($c->expand_pdo_parameters) && $c->expand_pdo_parameters ) { $this->bound_querystring = $this->querystring; if ( isset($this->bound_parameters) ) { $this->bound_querystring = $this->connection->ReplaceParameters($this->querystring,$this->bound_parameters); // printf( "\n=============================================================== OQ\n%s\n", $this->querystring); // printf( "\n=============================================================== QQ\n%s\n", $this->bound_querystring); // print_r( $this->bound_parameters ); } $t1 = microtime(true); // get start time $execute_result = $this->sth = $this->connection->query($this->bound_querystring); } else { $t1 = microtime(true); // get start time $execute_result = $this->sth = $this->connection->prepare($this->querystring); if ( $this->sth ) $execute_result = $this->sth->execute($this->bound_parameters); // printf( "\n=============================================================== OQ\n%s\n", $this->querystring); // print_r( $this->bound_parameters ); } $this->bound_querystring = null; if ( $execute_result === false ) { $this->error_info = $this->connection->errorInfo(); return false; } $this->rows = $this->sth->rowCount(); $i_took = microtime(true) - $t1; $c->total_query_time += $i_took; $this->execution_time = sprintf( "%2.06lf", $i_took); $this->error_info = null; return true; } /** * Return the query string we are planning to execute */ function QueryString() { return $this->querystring; } /** * Return the parameters we are planning to substitute into the query string */ function Parameters() { return $this->bound_parameters; } /** * Return the count of rows retrieved/affected */ function rows() { return $this->rows; } /** * Return the current rownum in the retrieved set */ function rownum() { return $this->rownum; } /** * Returns the current state of a transaction, indicating if we have begun a transaction, whether the transaction * has failed, or if we are not in a transaction. * @return int 0 = not started, 1 = in progress, -1 = error pending rollback/commit */ function TransactionState() { global $_awl_dbconn; if ( !isset($this->connection) ) { if ( !isset($_awl_dbconn) ) _awl_connect_configured_database(); $this->connection = $_awl_dbconn; } return $this->connection->TransactionState(); } /** * Wrap the parent DB class Begin() so we can $qry->Begin() sometime before we $qry->Exec() */ public function Begin() { global $_awl_dbconn; if ( !isset($this->connection) ) { if ( !isset($_awl_dbconn) ) _awl_connect_configured_database(); $this->connection = $_awl_dbconn; } return $this->connection->Begin(); } /** * Wrap the parent DB class Commit() so we can $qry->Commit() sometime after we $qry->Exec() */ public function Commit() { if ( !isset($this->connection) ) { trigger_error("Cannot commit a transaction without an active statement.", E_USER_ERROR); } return $this->connection->Commit(); } /** * Wrap the parent DB class Rollback() so we can $qry->Rollback() sometime after we $qry->Exec() */ public function Rollback() { if ( !isset($this->connection) ) { trigger_error("Cannot rollback a transaction without an active statement.", E_USER_ERROR); } return $this->connection->Rollback(); } /** * Simple SetSql() class which will reset the object with the querystring from the first argument. * @param string The query string in PDO syntax with replacable '?' characters or bindable parameters. */ public function SetSql( $sql ) { $this->rows = null; $this->execution_time = 0; $this->error_info = null; $this->rownum = -1; $this->bound_parameters = null; $this->bound_querystring = null; $this->sth = null; $this->querystring = $sql; } /** * Simple QDo() class which will re-use this query for whatever was passed in, and execute it * returning the result of the Exec() call. We can't call it Do() since that's a reserved word... * @param string The query string in PDO syntax with replacable '?' characters or bindable parameters. * @param mixed The values to replace into the SQL string. * @return boolean Success (true) or Failure (false) */ public function QDo() { $argc = func_num_args(); $args = func_get_args(); $this->SetSql( array_shift($args) ); if ( 1 < $argc ) { if ( is_array($args[0]) ) $this->bound_parameters = $args[0]; else $this->bound_parameters = $args; } return $this->Exec(); } /** * Execute the query, logging any debugging. * * <b>Example</b> * So that you can nicely enable/disable the queries for a particular class, you * could use some of PHPs magic constants in your call. * <code> * $qry->Exec(__CLASS__, __LINE__, __FILE__); * </code> * * * @param string $location The name of the location for enabling debugging or just * to help our children find the source of a problem. * @param int $line The line number where Exec was called * @param string $file The file where Exec was called * @return boolean Success (true) or Failure (false) */ function Exec( $location = null, $line = null, $file = null ) { global $c; if ( isset($location) ) $this->location = trim($location); if ( !isset($this->location) || $this->location == "" ) $this->location = substr($_SERVER['PHP_SELF'],1); if ( isset($line) ) $this->location_line = intval($line); else if ( isset($this->location_line) ) $line = $this->location_line; if ( isset($file) ) $this->location_file = trim($file); else if ( isset($this->location_file) ) $file = $this->location_file; if ( isset($c->dbg['querystring']) || isset($c->dbg['ALL']) ) { $this->_log_query( $this->location, 'DBGQ', $this->querystring, $line, $file ); if ( isset($this->bound_parameters) && !isset($this->sth) ) { foreach( $this->bound_parameters AS $k => $v ) { $this->_log_query( $this->location, 'DBGQ', sprintf(' "%s" => "%s"', $k, $v), $line, $file ); } } } if ( isset($this->bound_parameters) ) { $this->Prepare(); } $success = $this->Execute(); if ( ! $success ) { // query failed $this->errorstring = sprintf( 'SQL error "%s" - %s"', $this->error_info[0], (isset($this->error_info[2]) ? $this->error_info[2] : '')); if ( isset($c->dbg['print_query_errors']) && $c->dbg['print_query_errors'] ) { printf( "\n=====================\n" ); printf( "%s[%d] QF: %s\n", $file, $line, $this->errorstring); printf( "%s\n", $this->querystring ); if ( isset($this->bound_parameters) ) { foreach( $this->bound_parameters AS $k => $v ) { printf( " %-18s \t=> '%s'\n", "'$k'", $v ); } } printf( ".....................\n" ); } $this->_log_query( $this->location, 'QF', $this->errorstring, $line, $file ); $this->_log_query( $this->location, 'QF', $this->querystring, $line, $file ); if ( isset($this->bound_parameters) && ! ( isset($c->dbg['querystring']) || isset($c->dbg['ALL']) ) ) { foreach( $this->bound_parameters AS $k => $v ) { dbg_error_log( 'LOG-'.$this->location, ' Query: QF: "%s" => "%s"', $k, $v); } } } elseif ( $this->execution_time > $this->query_time_warning ) { // if execution time is too long $this->_log_query( $this->location, 'SQ', "Took: $this->execution_time for $this->querystring", $line, $file ); // SQ == Slow Query :-) } elseif ( isset($c->dbg['querystring']) || isset($c->dbg[strtolower($this->location)]) || isset($c->dbg['ALL']) ) { // query successful, but we're debugging and want to know how long it took anyway $this->_log_query( $this->location, 'DBGQ', "Took: $this->execution_time to find $this->rows rows.", $line, $file ); } return $success; } /** * Fetch the next row from the query results * @param boolean $as_array True if thing to be returned is array * @return mixed query row */ function Fetch($as_array = false) { if ( ! $this->sth || $this->rows == 0 ) return false; // no results if ( $this->rownum == null ) $this->rownum = -1; if ( ($this->rownum + 1) >= $this->rows ) return false; // reached the end of results $this->rownum++; $row = $this->sth->fetch( ($as_array ? PDO::FETCH_NUM : PDO::FETCH_OBJ) ); return $row; } /** * Get any error information from the last query */ function getErrorInfo() { return $this->error_info; } /** * Set the slow query threshold for this query (and subsequent queries using this object). The * overall default is $c->slow_query_threshold, or 5 seconds if that is not set. * @param double $new_threshold The new threshold for slow queries to be logged * @return double The old threshold. */ function SetSlowQueryThreshold( $new_threshold ) { $old = $this->query_time_warning; $this->query_time_warning = $new_threshold; return $oldval; } }