commiting uncommited changes on live site
[weblabels.fsf.org.git] / crm.fsf.org / 20131203 / files / sites / all / modules-new / civicrm / packages / DB / dbase.php
1 <?php
2
3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
5 /**
6 * The PEAR DB driver for PHP's dbase extension
7 * for interacting with dBase databases
8 *
9 * PHP versions 4 and 5
10 *
11 * LICENSE: This source file is subject to version 3.0 of the PHP license
12 * that is available through the world-wide-web at the following URI:
13 * http://www.php.net/license/3_0.txt. If you did not receive a copy of
14 * the PHP License and are unable to obtain it through the web, please
15 * send a note to license@php.net so we can mail you a copy immediately.
16 *
17 * @category Database
18 * @package DB
19 * @author Tomas V.V. Cox <cox@idecnet.com>
20 * @author Daniel Convissor <danielc@php.net>
21 * @copyright 1997-2007 The PHP Group
22 * @license http://www.php.net/license/3_0.txt PHP License 3.0
23 * @version CVS: $Id: dbase.php,v 1.45 2007/09/21 13:40:41 aharvey Exp $
24 * @link http://pear.php.net/package/DB
25 */
26
27 /**
28 * Obtain the DB_common class so it can be extended from
29 */
30 require_once 'DB/common.php';
31
32 /**
33 * The methods PEAR DB uses to interact with PHP's dbase extension
34 * for interacting with dBase databases
35 *
36 * These methods overload the ones declared in DB_common.
37 *
38 * @category Database
39 * @package DB
40 * @author Tomas V.V. Cox <cox@idecnet.com>
41 * @author Daniel Convissor <danielc@php.net>
42 * @copyright 1997-2007 The PHP Group
43 * @license http://www.php.net/license/3_0.txt PHP License 3.0
44 * @version Release: 1.7.13
45 * @link http://pear.php.net/package/DB
46 */
47 class DB_dbase extends DB_common
48 {
49 // {{{ properties
50
51 /**
52 * The DB driver type (mysql, oci8, odbc, etc.)
53 * @var string
54 */
55 var $phptype = 'dbase';
56
57 /**
58 * The database syntax variant to be used (db2, access, etc.), if any
59 * @var string
60 */
61 var $dbsyntax = 'dbase';
62
63 /**
64 * The capabilities of this DB implementation
65 *
66 * The 'new_link' element contains the PHP version that first provided
67 * new_link support for this DBMS. Contains false if it's unsupported.
68 *
69 * Meaning of the 'limit' element:
70 * + 'emulate' = emulate with fetch row by number
71 * + 'alter' = alter the query
72 * + false = skip rows
73 *
74 * @var array
75 */
76 var $features = array(
77 'limit' => false,
78 'new_link' => false,
79 'numrows' => true,
80 'pconnect' => false,
81 'prepare' => false,
82 'ssl' => false,
83 'transactions' => false,
84 );
85
86 /**
87 * A mapping of native error codes to DB error codes
88 * @var array
89 */
90 var $errorcode_map = array(
91 );
92
93 /**
94 * The raw database connection created by PHP
95 * @var resource
96 */
97 var $connection;
98
99 /**
100 * The DSN information for connecting to a database
101 * @var array
102 */
103 var $dsn = array();
104
105
106 /**
107 * A means of emulating result resources
108 * @var array
109 */
110 var $res_row = array();
111
112 /**
113 * The quantity of results so far
114 *
115 * For emulating result resources.
116 *
117 * @var integer
118 */
119 var $result = 0;
120
121 /**
122 * Maps dbase data type id's to human readable strings
123 *
124 * The human readable values are based on the output of PHP's
125 * dbase_get_header_info() function.
126 *
127 * @var array
128 * @since Property available since Release 1.7.0
129 */
130 var $types = array(
131 'C' => 'character',
132 'D' => 'date',
133 'L' => 'boolean',
134 'M' => 'memo',
135 'N' => 'number',
136 );
137
138
139 // }}}
140 // {{{ constructor
141
142 /**
143 * This constructor calls <kbd>$this->DB_common()</kbd>
144 *
145 * @return void
146 */
147 function DB_dbase()
148 {
149 $this->DB_common();
150 }
151
152 // }}}
153 // {{{ connect()
154
155 /**
156 * Connect to the database and create it if it doesn't exist
157 *
158 * Don't call this method directly. Use DB::connect() instead.
159 *
160 * PEAR DB's dbase driver supports the following extra DSN options:
161 * + mode An integer specifying the read/write mode to use
162 * (0 = read only, 1 = write only, 2 = read/write).
163 * Available since PEAR DB 1.7.0.
164 * + fields An array of arrays that PHP's dbase_create() function needs
165 * to create a new database. This information is used if the
166 * dBase file specified in the "database" segment of the DSN
167 * does not exist. For more info, see the PHP manual's
168 * {@link http://php.net/dbase_create dbase_create()} page.
169 * Available since PEAR DB 1.7.0.
170 *
171 * Example of how to connect and establish a new dBase file if necessary:
172 * <code>
173 * require_once 'DB.php';
174 *
175 * $dsn = array(
176 * 'phptype' => 'dbase',
177 * 'database' => '/path/and/name/of/dbase/file',
178 * 'mode' => 2,
179 * 'fields' => array(
180 * array('a', 'N', 5, 0),
181 * array('b', 'C', 40),
182 * array('c', 'C', 255),
183 * array('d', 'C', 20),
184 * ),
185 * );
186 * $options = array(
187 * 'debug' => 2,
188 * 'portability' => DB_PORTABILITY_ALL,
189 * );
190 *
191 * $db = DB::connect($dsn, $options);
192 * if (PEAR::isError($db)) {
193 * die($db->getMessage());
194 * }
195 * </code>
196 *
197 * @param array $dsn the data source name
198 * @param bool $persistent should the connection be persistent?
199 *
200 * @return int DB_OK on success. A DB_Error object on failure.
201 */
202 function connect($dsn, $persistent = false)
203 {
204 if (!PEAR::loadExtension('dbase')) {
205 return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
206 }
207
208 $this->dsn = $dsn;
209 if ($dsn['dbsyntax']) {
210 $this->dbsyntax = $dsn['dbsyntax'];
211 }
212
213 /*
214 * Turn track_errors on for entire script since $php_errormsg
215 * is the only way to find errors from the dbase extension.
216 */
217 @ini_set('track_errors', 1);
218 $php_errormsg = '';
219
220 if (!file_exists($dsn['database'])) {
221 $this->dsn['mode'] = 2;
222 if (empty($dsn['fields']) || !is_array($dsn['fields'])) {
223 return $this->raiseError(DB_ERROR_CONNECT_FAILED,
224 null, null, null,
225 'the dbase file does not exist and '
226 . 'it could not be created because '
227 . 'the "fields" element of the DSN '
228 . 'is not properly set');
229 }
230 $this->connection = @dbase_create($dsn['database'],
231 $dsn['fields']);
232 if (!$this->connection) {
233 return $this->raiseError(DB_ERROR_CONNECT_FAILED,
234 null, null, null,
235 'the dbase file does not exist and '
236 . 'the attempt to create it failed: '
237 . $php_errormsg);
238 }
239 } else {
240 if (!isset($this->dsn['mode'])) {
241 $this->dsn['mode'] = 0;
242 }
243 $this->connection = @dbase_open($dsn['database'],
244 $this->dsn['mode']);
245 if (!$this->connection) {
246 return $this->raiseError(DB_ERROR_CONNECT_FAILED,
247 null, null, null,
248 $php_errormsg);
249 }
250 }
251 return DB_OK;
252 }
253
254 // }}}
255 // {{{ disconnect()
256
257 /**
258 * Disconnects from the database server
259 *
260 * @return bool TRUE on success, FALSE on failure
261 */
262 function disconnect()
263 {
264 $ret = @dbase_close($this->connection);
265 $this->connection = null;
266 return $ret;
267 }
268
269 // }}}
270 // {{{ &query()
271
272 function &query($query = null)
273 {
274 // emulate result resources
275 $this->res_row[(int)$this->result] = 0;
276 $tmp = new DB_result($this, $this->result++);
277 return $tmp;
278 }
279
280 // }}}
281 // {{{ fetchInto()
282
283 /**
284 * Places a row from the result set into the given array
285 *
286 * Formating of the array and the data therein are configurable.
287 * See DB_result::fetchInto() for more information.
288 *
289 * This method is not meant to be called directly. Use
290 * DB_result::fetchInto() instead. It can't be declared "protected"
291 * because DB_result is a separate object.
292 *
293 * @param resource $result the query result resource
294 * @param array $arr the referenced array to put the data in
295 * @param int $fetchmode how the resulting array should be indexed
296 * @param int $rownum the row number to fetch (0 = first row)
297 *
298 * @return mixed DB_OK on success, NULL when the end of a result set is
299 * reached or on failure
300 *
301 * @see DB_result::fetchInto()
302 */
303 function fetchInto($result, &$arr, $fetchmode, $rownum = null)
304 {
305 if ($rownum === null) {
306 $rownum = $this->res_row[(int)$result]++;
307 }
308 if ($fetchmode & DB_FETCHMODE_ASSOC) {
309 $arr = @dbase_get_record_with_names($this->connection, $rownum);
310 if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) {
311 $arr = array_change_key_case($arr, CASE_LOWER);
312 }
313 } else {
314 $arr = @dbase_get_record($this->connection, $rownum);
315 }
316 if (!$arr) {
317 return null;
318 }
319 if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
320 $this->_rtrimArrayValues($arr);
321 }
322 if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
323 $this->_convertNullArrayValuesToEmpty($arr);
324 }
325 return DB_OK;
326 }
327
328 // }}}
329 // {{{ freeResult()
330
331 /**
332 * Deletes the result set and frees the memory occupied by the result set.
333 *
334 * This method is a no-op for dbase, as there aren't result resources in
335 * the same sense as most other database backends.
336 *
337 * @param resource $result PHP's query result resource
338 *
339 * @return bool TRUE on success, FALSE if $result is invalid
340 *
341 * @see DB_result::free()
342 */
343 function freeResult($result)
344 {
345 return true;
346 }
347
348 // }}}
349 // {{{ numCols()
350
351 /**
352 * Gets the number of columns in a result set
353 *
354 * This method is not meant to be called directly. Use
355 * DB_result::numCols() instead. It can't be declared "protected"
356 * because DB_result is a separate object.
357 *
358 * @param resource $result PHP's query result resource
359 *
360 * @return int the number of columns. A DB_Error object on failure.
361 *
362 * @see DB_result::numCols()
363 */
364 function numCols($foo)
365 {
366 return @dbase_numfields($this->connection);
367 }
368
369 // }}}
370 // {{{ numRows()
371
372 /**
373 * Gets the number of rows in a result set
374 *
375 * This method is not meant to be called directly. Use
376 * DB_result::numRows() instead. It can't be declared "protected"
377 * because DB_result is a separate object.
378 *
379 * @param resource $result PHP's query result resource
380 *
381 * @return int the number of rows. A DB_Error object on failure.
382 *
383 * @see DB_result::numRows()
384 */
385 function numRows($foo)
386 {
387 return @dbase_numrecords($this->connection);
388 }
389
390 // }}}
391 // {{{ quoteBoolean()
392
393 /**
394 * Formats a boolean value for use within a query in a locale-independent
395 * manner.
396 *
397 * @param boolean the boolean value to be quoted.
398 * @return string the quoted string.
399 * @see DB_common::quoteSmart()
400 * @since Method available since release 1.7.8.
401 */
402 function quoteBoolean($boolean) {
403 return $boolean ? 'T' : 'F';
404 }
405
406 // }}}
407 // {{{ tableInfo()
408
409 /**
410 * Returns information about the current database
411 *
412 * @param mixed $result THIS IS UNUSED IN DBASE. The current database
413 * is examined regardless of what is provided here.
414 * @param int $mode a valid tableInfo mode
415 *
416 * @return array an associative array with the information requested.
417 * A DB_Error object on failure.
418 *
419 * @see DB_common::tableInfo()
420 * @since Method available since Release 1.7.0
421 */
422 function tableInfo($result = null, $mode = null)
423 {
424 if (function_exists('dbase_get_header_info')) {
425 $id = @dbase_get_header_info($this->connection);
426 if (!$id && $php_errormsg) {
427 return $this->raiseError(DB_ERROR,
428 null, null, null,
429 $php_errormsg);
430 }
431 } else {
432 /*
433 * This segment for PHP 4 is loosely based on code by
434 * Hadi Rusiah <deegos@yahoo.com> in the comments on
435 * the dBase reference page in the PHP manual.
436 */
437 $db = @fopen($this->dsn['database'], 'r');
438 if (!$db) {
439 return $this->raiseError(DB_ERROR_CONNECT_FAILED,
440 null, null, null,
441 $php_errormsg);
442 }
443
444 $id = array();
445 $i = 0;
446
447 $line = fread($db, 32);
448 while (!feof($db)) {
449 $line = fread($db, 32);
450 if (substr($line, 0, 1) == chr(13)) {
451 break;
452 } else {
453 $pos = strpos(substr($line, 0, 10), chr(0));
454 $pos = ($pos == 0 ? 10 : $pos);
455 $id[$i] = array(
456 'name' => substr($line, 0, $pos),
457 'type' => $this->types[substr($line, 11, 1)],
458 'length' => ord(substr($line, 16, 1)),
459 'precision' => ord(substr($line, 17, 1)),
460 );
461 }
462 $i++;
463 }
464
465 fclose($db);
466 }
467
468 if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
469 $case_func = 'strtolower';
470 } else {
471 $case_func = 'strval';
472 }
473
474 $res = array();
475 $count = count($id);
476
477 if ($mode) {
478 $res['num_fields'] = $count;
479 }
480
481 for ($i = 0; $i < $count; $i++) {
482 $res[$i] = array(
483 'table' => $this->dsn['database'],
484 'name' => $case_func($id[$i]['name']),
485 'type' => $id[$i]['type'],
486 'len' => $id[$i]['length'],
487 'flags' => ''
488 );
489 if ($mode & DB_TABLEINFO_ORDER) {
490 $res['order'][$res[$i]['name']] = $i;
491 }
492 if ($mode & DB_TABLEINFO_ORDERTABLE) {
493 $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
494 }
495 }
496
497 return $res;
498 }
499
500 // }}}
501 }
502
503 /*
504 * Local variables:
505 * tab-width: 4
506 * c-basic-offset: 4
507 * End:
508 */
509
510 ?>