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