Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.2.x will end 22 April 2024 (12 months).
  • Bug fixes for security issues in 4.2.x will end 7 October 2024 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.1.x is supported too.

Differences Between: [Versions 310 and 402] [Versions 311 and 402] [Versions 39 and 402]

   1  <?php
   2  /**
   3   * PEAR DB Emulation Layer for ADOdb.
   4   *
   5   * The following code is modelled on PEAR DB code by Stig Bakken <ssb@fast.no>
   6   * and Tomas V.V.Cox <cox@idecnet.com>. Portions (c)1997-2002 The PHP Group.
   7   *
   8   * This file is part of ADOdb, a Database Abstraction Layer library for PHP.
   9   *
  10   * @package ADOdb
  11   * @link https://adodb.org Project's web site and documentation
  12   * @link https://github.com/ADOdb/ADOdb Source code and issue tracker
  13   *
  14   * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause
  15   * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option,
  16   * any later version. This means you can use it in proprietary products.
  17   * See the LICENSE.md file distributed with this source code for details.
  18   * @license BSD-3-Clause
  19   * @license LGPL-2.1-or-later
  20   *
  21   * @copyright 2000-2013 John Lim
  22   * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community
  23   */
  24  
  25   /*
  26   We support:
  27  
  28   DB_Common
  29   ---------
  30   	 query - returns PEAR_Error on error
  31  	 limitQuery - return PEAR_Error on error
  32  	 prepare - does not return PEAR_Error on error
  33  	 execute - does not return PEAR_Error on error
  34  	 setFetchMode - supports ASSOC and ORDERED
  35  	 errorNative
  36  	 quote
  37  	 nextID
  38  	 disconnect
  39  
  40  	 getOne
  41  	 getAssoc
  42  	 getRow
  43  	 getCol
  44  	 getAll
  45  
  46   DB_Result
  47   ---------
  48   	 numRows - returns -1 if not supported
  49  	 numCols
  50  	 fetchInto - does not support passing of fetchmode
  51  	 fetchRows - does not support passing of fetchmode
  52  	 free
  53   */
  54  
  55  define('ADODB_PEAR',dirname(__FILE__));
  56  include_once "PEAR.php";
  57  include_once  ADODB_PEAR."/adodb-errorpear.inc.php";
  58  include_once  ADODB_PEAR."/adodb.inc.php";
  59  
  60  if (!defined('DB_OK')) {
  61  define("DB_OK",	 1);
  62  define("DB_ERROR",-1);
  63  
  64  /**
  65   * This is a special constant that tells DB the user hasn't specified
  66   * any particular get mode, so the default should be used.
  67   */
  68  
  69  define('DB_FETCHMODE_DEFAULT', 0);
  70  
  71  /**
  72   * Column data indexed by numbers, ordered from 0 and up
  73   */
  74  
  75  define('DB_FETCHMODE_ORDERED', 1);
  76  
  77  /**
  78   * Column data indexed by column names
  79   */
  80  
  81  define('DB_FETCHMODE_ASSOC', 2);
  82  
  83  /* for compatibility */
  84  
  85  define('DB_GETMODE_ORDERED', DB_FETCHMODE_ORDERED);
  86  define('DB_GETMODE_ASSOC',   DB_FETCHMODE_ASSOC);
  87  
  88  /**
  89   * these are constants for the tableInfo-function
  90   * they are bitwised or'ed. so if there are more constants to be defined
  91   * in the future, adjust DB_TABLEINFO_FULL accordingly
  92   */
  93  
  94  define('DB_TABLEINFO_ORDER', 1);
  95  define('DB_TABLEINFO_ORDERTABLE', 2);
  96  define('DB_TABLEINFO_FULL', 3);
  97  }
  98  
  99  /**
 100   * The main "DB" class is simply a container class with some static
 101   * methods for creating DB objects as well as some utility functions
 102   * common to all parts of DB.
 103   *
 104   */
 105  
 106  class DB
 107  {
 108  	 /**
 109  	  * Create a new DB object for the specified database type
 110  	  *
 111  	  * @param $type string database type, for example "mysql"
 112  	  *
 113  	  * @return object a newly created DB object, or a DB error code on
 114  	  * error
 115  	  */
 116  
 117  	function factory($type)
 118  	 {
 119  	 	 include_once(ADODB_DIR."/drivers/adodb-$type.inc.php");
 120  	 	 $obj = NewADOConnection($type);
 121  	 	 if (!is_object($obj)) $obj = new PEAR_Error('Unknown Database Driver: '.$dsninfo['phptype'],-1);
 122  	 	 return $obj;
 123  	 }
 124  
 125  	 /**
 126  	  * Create a new DB object and connect to the specified database
 127  	  *
 128  	  * @param $dsn mixed "data source name", see the DB::parseDSN
 129  	  * method for a description of the dsn format.  Can also be
 130  	  * specified as an array of the format returned by DB::parseDSN.
 131  	  *
 132  	  * @param $options mixed if boolean (or scalar), tells whether
 133  	  * this connection should be persistent (for backends that support
 134  	  * this).  This parameter can also be an array of options, see
 135  	  * DB_common::setOption for more information on connection
 136  	  * options.
 137  	  *
 138  	  * @return object a newly created DB connection object, or a DB
 139  	  * error object on error
 140  	  *
 141  	  * @see DB::parseDSN
 142  	  * @see DB::isError
 143  	  */
 144  	function connect($dsn, $options = false)
 145  	 {
 146  	 	 if (is_array($dsn)) {
 147  	 	 	 $dsninfo = $dsn;
 148  	 	 } else {
 149  	 	 	 $dsninfo = DB::parseDSN($dsn);
 150  	 	 }
 151  	 	 switch ($dsninfo["phptype"]) {
 152  	 	 	 case 'pgsql': 	 $type = 'postgres7'; break;
 153  	 	 	 case 'ifx':	 	 $type = 'informix9'; break;
 154  	 	 	 default: 	 	 $type = $dsninfo["phptype"]; break;
 155  	 	 }
 156  
 157  	 	 if (is_array($options) && isset($options["debug"]) &&
 158  	 	 	 $options["debug"] >= 2) {
 159  	 	 	 // expose php errors with sufficient debug level
 160  	 	 	  @include_once("adodb-$type.inc.php");
 161  	 	 } else {
 162  	 	 	  @include_once("adodb-$type.inc.php");
 163  	 	 }
 164  
 165  	 	 @$obj = NewADOConnection($type);
 166  	 	 if (!is_object($obj)) {
 167  	 	 	 $obj = new PEAR_Error('Unknown Database Driver: '.$dsninfo['phptype'],-1);
 168  	 	 	 return $obj;
 169  	 	 }
 170  	 	 if (is_array($options)) {
 171  	 	 	 foreach($options as $k => $v) {
 172  	 	 	 	 switch(strtolower($k)) {
 173  	 	 	 	 case 'persist':
 174  	 	 	 	 case 'persistent': 	 $persist = $v; break;
 175  	 	 	 	 #ibase
 176  	 	 	 	 case 'dialect': 	 $obj->dialect = $v; break;
 177  	 	 	 	 case 'charset':	 	 $obj->charset = $v; break;
 178  	 	 	 	 case 'buffers':	 	 $obj->buffers = $v; break;
 179  	 	 	 	 #ado
 180  	 	 	 	 case 'charpage':	 $obj->charPage = $v; break;
 181  	 	 	 	 #mysql
 182  	 	 	 	 case 'clientflags': $obj->clientFlags = $v; break;
 183  	 	 	 	 }
 184  	 	 	 }
 185  	 	 } else {
 186  	 	    	 $persist = false;
 187  	 	 }
 188  
 189  	 	 if (isset($dsninfo['socket'])) $dsninfo['hostspec'] .= ':'.$dsninfo['socket'];
 190  	 	 else if (isset($dsninfo['port'])) $dsninfo['hostspec'] .= ':'.$dsninfo['port'];
 191  
 192  	 	 if($persist) $ok = $obj->PConnect($dsninfo['hostspec'], $dsninfo['username'],$dsninfo['password'],$dsninfo['database']);
 193  	 	 else  $ok = $obj->Connect($dsninfo['hostspec'], $dsninfo['username'],$dsninfo['password'],$dsninfo['database']);
 194  
 195  	 	 if (!$ok) $obj = ADODB_PEAR_Error();
 196  	 	 return $obj;
 197  	 }
 198  
 199  	 /**
 200  	  * Return the DB API version
 201  	  *
 202  	  * @return int the DB API version number
 203  	  */
 204  	function apiVersion()
 205  	 {
 206  	 	 return 2;
 207  	 }
 208  
 209  	 /**
 210  	  * Tell whether a result code from a DB method is an error
 211  	  *
 212  	  * @param $value int result code
 213  	  *
 214  	  * @return bool whether $value is an error
 215  	  */
 216  	function isError($value)
 217  	 {
 218  	 	 if (!is_object($value)) return false;
 219  	 	 $class = strtolower(get_class($value));
 220  	 	 return $class == 'pear_error' || is_subclass_of($value, 'pear_error') ||
 221  	 	 	 	 $class == 'db_error' || is_subclass_of($value, 'db_error');
 222  	 }
 223  
 224  
 225  	 /**
 226  	  * Tell whether a result code from a DB method is a warning.
 227  	  * Warnings differ from errors in that they are generated by DB,
 228  	  * and are not fatal.
 229  	  *
 230  	  * @param $value mixed result value
 231  	  *
 232  	  * @return bool whether $value is a warning
 233  	  */
 234  	function isWarning($value)
 235  	 {
 236  	 	 return false;
 237  	 	 /*
 238  	 	 return is_object($value) &&
 239  	 	 	 (get_class( $value ) == "db_warning" ||
 240  	 	 	  is_subclass_of($value, "db_warning"));*/
 241  	 }
 242  
 243  	 /**
 244  	  * Parse a data source name
 245  	  *
 246  	  * @param $dsn string Data Source Name to be parsed
 247  	  *
 248  	  * @return array an associative array with the following keys:
 249  	  *
 250  	  *  phptype: Database backend used in PHP (mysql, odbc etc.)
 251  	  *  dbsyntax: Database used with regards to SQL syntax etc.
 252  	  *  protocol: Communication protocol to use (tcp, unix etc.)
 253  	  *  hostspec: Host specification (hostname[:port])
 254  	  *  database: Database to use on the DBMS server
 255  	  *  username: User name for login
 256  	  *  password: Password for login
 257  	  *
 258  	  * The format of the supplied DSN is in its fullest form:
 259  	  *
 260  	  *  phptype(dbsyntax)://username:password@protocol+hostspec/database
 261  	  *
 262  	  * Most variations are allowed:
 263  	  *
 264  	  *  phptype://username:password@protocol+hostspec:110//usr/db_file.db
 265  	  *  phptype://username:password@hostspec/database_name
 266  	  *  phptype://username:password@hostspec
 267  	  *  phptype://username@hostspec
 268  	  *  phptype://hostspec/database
 269  	  *  phptype://hostspec
 270  	  *  phptype(dbsyntax)
 271  	  *  phptype
 272  	  *
 273  	  * @author Tomas V.V.Cox <cox@idecnet.com>
 274  	  */
 275  	function parseDSN($dsn)
 276  	 {
 277  	 	 if (is_array($dsn)) {
 278  	 	 	 return $dsn;
 279  	 	 }
 280  
 281  	 	 $parsed = array(
 282  	 	 	 'phptype'  => false,
 283  	 	 	 'dbsyntax' => false,
 284  	 	 	 'protocol' => false,
 285  	 	 	 'hostspec' => false,
 286  	 	 	 'database' => false,
 287  	 	 	 'username' => false,
 288  	 	 	 'password' => false
 289  	 	 );
 290  
 291  	 	 // Find phptype and dbsyntax
 292  	 	 if (($pos = strpos($dsn, '://')) !== false) {
 293  	 	 	 $str = substr($dsn, 0, $pos);
 294  	 	 	 $dsn = substr($dsn, $pos + 3);
 295  	 	 } else {
 296  	 	 	 $str = $dsn;
 297  	 	 	 $dsn = NULL;
 298  	 	 }
 299  
 300  	 	 // Get phptype and dbsyntax
 301  	 	 // $str => phptype(dbsyntax)
 302  	 	 if (preg_match('|^(.+?)\((.*?)\)$|', $str, $arr)) {
 303  	 	 	 $parsed['phptype'] = $arr[1];
 304  	 	 	 $parsed['dbsyntax'] = (empty($arr[2])) ? $arr[1] : $arr[2];
 305  	 	 } else {
 306  	 	 	 $parsed['phptype'] = $str;
 307  	 	 	 $parsed['dbsyntax'] = $str;
 308  	 	 }
 309  
 310  	 	 if (empty($dsn)) {
 311  	 	 	 return $parsed;
 312  	 	 }
 313  
 314  	 	 // Get (if found): username and password
 315  	 	 // $dsn => username:password@protocol+hostspec/database
 316  	 	 if (($at = strpos($dsn,'@')) !== false) {
 317  	 	 	 $str = substr($dsn, 0, $at);
 318  	 	 	 $dsn = substr($dsn, $at + 1);
 319  	 	 	 if (($pos = strpos($str, ':')) !== false) {
 320  	 	 	 	 $parsed['username'] = urldecode(substr($str, 0, $pos));
 321  	 	 	 	 $parsed['password'] = urldecode(substr($str, $pos + 1));
 322  	 	 	 } else {
 323  	 	 	 	 $parsed['username'] = urldecode($str);
 324  	 	 	 }
 325  	 	 }
 326  
 327  	 	 // Find protocol and hostspec
 328  	 	 // $dsn => protocol+hostspec/database
 329  	 	 if (($pos=strpos($dsn, '/')) !== false) {
 330  	 	 	 $str = substr($dsn, 0, $pos);
 331  	 	 	 $dsn = substr($dsn, $pos + 1);
 332  	 	 } else {
 333  	 	 	 $str = $dsn;
 334  	 	 	 $dsn = NULL;
 335  	 	 }
 336  
 337  	 	 // Get protocol + hostspec
 338  	 	 // $str => protocol+hostspec
 339  	 	 if (($pos=strpos($str, '+')) !== false) {
 340  	 	 	 $parsed['protocol'] = substr($str, 0, $pos);
 341  	 	 	 $parsed['hostspec'] = urldecode(substr($str, $pos + 1));
 342  	 	 } else {
 343  	 	 	 $parsed['hostspec'] = urldecode($str);
 344  	 	 }
 345  
 346  	 	 // Get database if any
 347  	 	 // $dsn => database
 348  	 	 if (!empty($dsn)) {
 349  	 	 	 $parsed['database'] = $dsn;
 350  	 	 }
 351  
 352  	 	 return $parsed;
 353  	 }
 354  
 355  	 /**
 356  	  * Load a PHP database extension if it is not loaded already.
 357  	  *
 358  	  * @access public
 359  	  *
 360  	  * @param $name the base name of the extension (without the .so or
 361  	  * .dll suffix)
 362  	  *
 363  	  * @return bool true if the extension was already or successfully
 364  	  * loaded, false if it could not be loaded
 365  	  */
 366  	function assertExtension($name)
 367  	 {
 368  	 	 if (function_exists('dl') && !extension_loaded($name)) {
 369  	 	 	 $dlext = (strncmp(PHP_OS,'WIN',3) === 0) ? '.dll' : '.so';
 370  	 	 	 @dl($name . $dlext);
 371  	 	 }
 372  	 	 if (!extension_loaded($name)) {
 373  	 	 	 return false;
 374  	 	 }
 375  	 	 return true;
 376  	 }
 377  }