| 1 | efrain | 1 | <?php
 | 
        
           |  |  | 2 | /**
 | 
        
           |  |  | 3 |  * Helper functions.
 | 
        
           |  |  | 4 |  *
 | 
        
           |  |  | 5 |  * Less commonly used functions are placed here to reduce size of adodb.inc.php.
 | 
        
           |  |  | 6 |  *
 | 
        
           |  |  | 7 |  * This file is part of ADOdb, a Database Abstraction Layer library for PHP.
 | 
        
           |  |  | 8 |  *
 | 
        
           |  |  | 9 |  * @package ADOdb
 | 
        
           |  |  | 10 |  * @link https://adodb.org Project's web site and documentation
 | 
        
           |  |  | 11 |  * @link https://github.com/ADOdb/ADOdb Source code and issue tracker
 | 
        
           |  |  | 12 |  *
 | 
        
           |  |  | 13 |  * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause
 | 
        
           |  |  | 14 |  * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option,
 | 
        
           |  |  | 15 |  * any later version. This means you can use it in proprietary products.
 | 
        
           |  |  | 16 |  * See the LICENSE.md file distributed with this source code for details.
 | 
        
           |  |  | 17 |  * @license BSD-3-Clause
 | 
        
           |  |  | 18 |  * @license LGPL-2.1-or-later
 | 
        
           |  |  | 19 |  *
 | 
        
           |  |  | 20 |  * @copyright 2000-2013 John Lim
 | 
        
           |  |  | 21 |  * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community
 | 
        
           |  |  | 22 |  */
 | 
        
           |  |  | 23 |   | 
        
           |  |  | 24 | // security - hide paths
 | 
        
           |  |  | 25 | if (!defined('ADODB_DIR')) die();
 | 
        
           |  |  | 26 |   | 
        
           |  |  | 27 | global $ADODB_INCLUDED_LIB;
 | 
        
           |  |  | 28 | $ADODB_INCLUDED_LIB = 1;
 | 
        
           |  |  | 29 |   | 
        
           |  |  | 30 | /**
 | 
        
           |  |  | 31 |  * Strip the ORDER BY clause from the outer SELECT.
 | 
        
           |  |  | 32 |  *
 | 
        
           |  |  | 33 |  * @param string $sql
 | 
        
           |  |  | 34 |  *
 | 
        
           |  |  | 35 |  * @return string
 | 
        
           |  |  | 36 |  */
 | 
        
           |  |  | 37 | function adodb_strip_order_by($sql)
 | 
        
           |  |  | 38 | {
 | 
        
           |  |  | 39 | 	$num = preg_match_all('/(\sORDER\s+BY\s(?:[^)](?!LIMIT))*)/is', $sql, $matches, PREG_OFFSET_CAPTURE);
 | 
        
           |  |  | 40 | 	if ($num) {
 | 
        
           |  |  | 41 | 		// Get the last match
 | 
        
           |  |  | 42 | 		list($last_order_by, $offset) = array_pop($matches[1]);
 | 
        
           |  |  | 43 |   | 
        
           |  |  | 44 | 		// If we find a ')' after the last order by, then it belongs to a
 | 
        
           |  |  | 45 | 		// sub-query, not the outer SQL statement and should not be stripped
 | 
        
           |  |  | 46 | 		if (strpos($sql, ')', $offset) === false) {
 | 
        
           |  |  | 47 | 			$sql = str_replace($last_order_by, '', $sql);
 | 
        
           |  |  | 48 | 		}
 | 
        
           |  |  | 49 | 	}
 | 
        
           |  |  | 50 | 	return $sql;
 | 
        
           |  |  | 51 | }
 | 
        
           |  |  | 52 |   | 
        
           |  |  | 53 | function adodb_probetypes($array,&$types,$probe=8)
 | 
        
           |  |  | 54 | {
 | 
        
           |  |  | 55 | // probe and guess the type
 | 
        
           |  |  | 56 | 	$types = array();
 | 
        
           |  |  | 57 | 	if ($probe > sizeof($array)) $max = sizeof($array);
 | 
        
           |  |  | 58 | 	else $max = $probe;
 | 
        
           |  |  | 59 |   | 
        
           |  |  | 60 |   | 
        
           |  |  | 61 | 	for ($j=0;$j < $max; $j++) {
 | 
        
           |  |  | 62 | 		$row = $array[$j];
 | 
        
           |  |  | 63 | 		if (!$row) break;
 | 
        
           |  |  | 64 | 		$i = -1;
 | 
        
           |  |  | 65 | 		foreach($row as $v) {
 | 
        
           |  |  | 66 | 			$i += 1;
 | 
        
           |  |  | 67 |   | 
        
           |  |  | 68 | 			if (isset($types[$i]) && $types[$i]=='C') continue;
 | 
        
           |  |  | 69 |   | 
        
           |  |  | 70 | 			//print " ($i ".$types[$i]. "$v) ";
 | 
        
           |  |  | 71 | 			$v = trim($v);
 | 
        
           |  |  | 72 |   | 
        
           |  |  | 73 | 			if (!preg_match('/^[+-]{0,1}[0-9\.]+$/',$v)) {
 | 
        
           |  |  | 74 | 				$types[$i] = 'C'; // once C, always C
 | 
        
           |  |  | 75 |   | 
        
           |  |  | 76 | 				continue;
 | 
        
           |  |  | 77 | 			}
 | 
        
           |  |  | 78 | 			if ($j == 0) {
 | 
        
           |  |  | 79 | 			// If empty string, we presume is character
 | 
        
           |  |  | 80 | 			// test for integer for 1st row only
 | 
        
           |  |  | 81 | 			// after that it is up to testing other rows to prove
 | 
        
           |  |  | 82 | 			// that it is not an integer
 | 
        
           |  |  | 83 | 				if (strlen($v) == 0) $types[$i] = 'C';
 | 
        
           |  |  | 84 | 				if (strpos($v,'.') !== false) $types[$i] = 'N';
 | 
        
           |  |  | 85 | 				else $types[$i] = 'I';
 | 
        
           |  |  | 86 | 				continue;
 | 
        
           |  |  | 87 | 			}
 | 
        
           |  |  | 88 |   | 
        
           |  |  | 89 | 			if (strpos($v,'.') !== false) $types[$i] = 'N';
 | 
        
           |  |  | 90 |   | 
        
           |  |  | 91 | 		}
 | 
        
           |  |  | 92 | 	}
 | 
        
           |  |  | 93 |   | 
        
           |  |  | 94 | }
 | 
        
           |  |  | 95 |   | 
        
           |  |  | 96 | function adodb_transpose(&$arr, &$newarr, &$hdr, $fobjs)
 | 
        
           |  |  | 97 | {
 | 
        
           |  |  | 98 | 	$oldX = sizeof(reset($arr));
 | 
        
           |  |  | 99 | 	$oldY = sizeof($arr);
 | 
        
           |  |  | 100 |   | 
        
           |  |  | 101 | 	if ($hdr) {
 | 
        
           |  |  | 102 | 		$startx = 1;
 | 
        
           |  |  | 103 | 		$hdr = array('Fields');
 | 
        
           |  |  | 104 | 		for ($y = 0; $y < $oldY; $y++) {
 | 
        
           |  |  | 105 | 			$hdr[] = $arr[$y][0];
 | 
        
           |  |  | 106 | 		}
 | 
        
           |  |  | 107 | 	} else
 | 
        
           |  |  | 108 | 		$startx = 0;
 | 
        
           |  |  | 109 |   | 
        
           |  |  | 110 | 	for ($x = $startx; $x < $oldX; $x++) {
 | 
        
           |  |  | 111 | 		if ($fobjs) {
 | 
        
           |  |  | 112 | 			$o = $fobjs[$x];
 | 
        
           |  |  | 113 | 			$newarr[] = array($o->name);
 | 
        
           |  |  | 114 | 		} else
 | 
        
           |  |  | 115 | 			$newarr[] = array();
 | 
        
           |  |  | 116 |   | 
        
           |  |  | 117 | 		for ($y = 0; $y < $oldY; $y++) {
 | 
        
           |  |  | 118 | 			$newarr[$x-$startx][] = $arr[$y][$x];
 | 
        
           |  |  | 119 | 		}
 | 
        
           |  |  | 120 | 	}
 | 
        
           |  |  | 121 | }
 | 
        
           |  |  | 122 |   | 
        
           |  |  | 123 |   | 
        
           |  |  | 124 | function _adodb_replace($zthis, $table, $fieldArray, $keyCol, $autoQuote, $has_autoinc)
 | 
        
           |  |  | 125 | {
 | 
        
           |  |  | 126 | 	// Add Quote around table name to support use of spaces / reserved keywords
 | 
        
           |  |  | 127 | 	$table=sprintf('%s%s%s', $zthis->nameQuote,$table,$zthis->nameQuote);
 | 
        
           |  |  | 128 |   | 
        
           |  |  | 129 | 	if (count($fieldArray) == 0) return 0;
 | 
        
           |  |  | 130 |   | 
        
           |  |  | 131 | 	if (!is_array($keyCol)) {
 | 
        
           |  |  | 132 | 		$keyCol = array($keyCol);
 | 
        
           |  |  | 133 | 	}
 | 
        
           |  |  | 134 | 	$uSet = '';
 | 
        
           |  |  | 135 | 	foreach($fieldArray as $k => $v) {
 | 
        
           |  |  | 136 | 		if ($v === null) {
 | 
        
           |  |  | 137 | 			$v = 'NULL';
 | 
        
           |  |  | 138 | 			$fieldArray[$k] = $v;
 | 
        
           |  |  | 139 | 		} else if ($autoQuote && /*!is_numeric($v) /*and strncmp($v,"'",1) !== 0 -- sql injection risk*/ strcasecmp($v,$zthis->null2null)!=0) {
 | 
        
           |  |  | 140 | 			$v = $zthis->qstr($v);
 | 
        
           |  |  | 141 | 			$fieldArray[$k] = $v;
 | 
        
           |  |  | 142 | 		}
 | 
        
           |  |  | 143 | 		if (in_array($k,$keyCol)) continue; // skip UPDATE if is key
 | 
        
           |  |  | 144 |   | 
        
           |  |  | 145 | 		// Add Quote around column name to support use of spaces / reserved keywords
 | 
        
           |  |  | 146 | 		$uSet .= sprintf(',%s%s%s=%s',$zthis->nameQuote,$k,$zthis->nameQuote,$v);
 | 
        
           |  |  | 147 | 	}
 | 
        
           |  |  | 148 | 	$uSet = ltrim($uSet, ',');
 | 
        
           |  |  | 149 |   | 
        
           |  |  | 150 | 	// Add Quote around column name in where clause
 | 
        
           |  |  | 151 | 	$where = '';
 | 
        
           |  |  | 152 | 	foreach ($keyCol as $v) {
 | 
        
           |  |  | 153 | 		if (isset($fieldArray[$v])) {
 | 
        
           |  |  | 154 | 			$where .= sprintf(' and %s%s%s=%s ', $zthis->nameQuote,$v,$zthis->nameQuote,$fieldArray[$v]);
 | 
        
           |  |  | 155 | 		}
 | 
        
           |  |  | 156 | 	}
 | 
        
           |  |  | 157 | 	if ($where) {
 | 
        
           |  |  | 158 | 		$where = substr($where, 5);
 | 
        
           |  |  | 159 | 	}
 | 
        
           |  |  | 160 |   | 
        
           |  |  | 161 | 	if ($uSet && $where) {
 | 
        
           |  |  | 162 | 		$update = "UPDATE $table SET $uSet WHERE $where";
 | 
        
           |  |  | 163 | 		$rs = $zthis->Execute($update);
 | 
        
           |  |  | 164 |   | 
        
           |  |  | 165 | 		if ($rs) {
 | 
        
           |  |  | 166 | 			if ($zthis->poorAffectedRows) {
 | 
        
           |  |  | 167 | 				// The Select count(*) wipes out any errors that the update would have returned.
 | 
        
           |  |  | 168 | 				// PHPLens Issue No: 5696
 | 
        
           |  |  | 169 | 				if ($zthis->ErrorNo()<>0) return 0;
 | 
        
           |  |  | 170 |   | 
        
           |  |  | 171 | 				// affected_rows == 0 if update field values identical to old values
 | 
        
           |  |  | 172 | 				// for mysql - which is silly.
 | 
        
           |  |  | 173 | 				$cnt = $zthis->GetOne("select count(*) from $table where $where");
 | 
        
           |  |  | 174 | 				if ($cnt > 0) return 1; // record already exists
 | 
        
           |  |  | 175 | 			} else {
 | 
        
           |  |  | 176 | 				if (($zthis->Affected_Rows()>0)) return 1;
 | 
        
           |  |  | 177 | 			}
 | 
        
           |  |  | 178 | 		} else
 | 
        
           |  |  | 179 | 			return 0;
 | 
        
           |  |  | 180 | 	}
 | 
        
           |  |  | 181 |   | 
        
           |  |  | 182 | 	$iCols = $iVals = '';
 | 
        
           |  |  | 183 | 	foreach($fieldArray as $k => $v) {
 | 
        
           |  |  | 184 | 		if ($has_autoinc && in_array($k,$keyCol)) continue; // skip autoinc col
 | 
        
           |  |  | 185 |   | 
        
           |  |  | 186 | 		// Add Quote around Column Name
 | 
        
           |  |  | 187 | 		$iCols .= sprintf(',%s%s%s',$zthis->nameQuote,$k,$zthis->nameQuote);
 | 
        
           |  |  | 188 | 		$iVals .= ",$v";
 | 
        
           |  |  | 189 | 	}
 | 
        
           |  |  | 190 | 	$iCols = ltrim($iCols, ',');
 | 
        
           |  |  | 191 | 	$iVals = ltrim($iVals, ',');
 | 
        
           |  |  | 192 |   | 
        
           |  |  | 193 | 	$insert = "INSERT INTO $table ($iCols) VALUES ($iVals)";
 | 
        
           |  |  | 194 | 	$rs = $zthis->Execute($insert);
 | 
        
           |  |  | 195 | 	return ($rs) ? 2 : 0;
 | 
        
           |  |  | 196 | }
 | 
        
           |  |  | 197 |   | 
        
           |  |  | 198 | function _adodb_getmenu($zthis, $name,$defstr='',$blank1stItem=true,$multiple=false,
 | 
        
           |  |  | 199 | 			$size=0, $selectAttr='',$compareFields0=true)
 | 
        
           |  |  | 200 | {
 | 
        
           |  |  | 201 | 	global $ADODB_FETCH_MODE;
 | 
        
           |  |  | 202 |   | 
        
           |  |  | 203 | 	$s = _adodb_getmenu_select($name, $defstr, $blank1stItem, $multiple, $size, $selectAttr);
 | 
        
           |  |  | 204 |   | 
        
           |  |  | 205 | 	$hasvalue = $zthis->FieldCount() > 1;
 | 
        
           |  |  | 206 | 	if (!$hasvalue) {
 | 
        
           |  |  | 207 | 		$compareFields0 = true;
 | 
        
           |  |  | 208 | 	}
 | 
        
           |  |  | 209 |   | 
        
           |  |  | 210 | 	$value = '';
 | 
        
           |  |  | 211 | 	while(!$zthis->EOF) {
 | 
        
           |  |  | 212 | 		$zval = rtrim(reset($zthis->fields));
 | 
        
           |  |  | 213 |   | 
        
           |  |  | 214 | 		if ($blank1stItem && $zval == "") {
 | 
        
           |  |  | 215 | 			$zthis->MoveNext();
 | 
        
           |  |  | 216 | 			continue;
 | 
        
           |  |  | 217 | 		}
 | 
        
           |  |  | 218 |   | 
        
           |  |  | 219 | 		if ($hasvalue) {
 | 
        
           |  |  | 220 | 			if ($ADODB_FETCH_MODE == ADODB_FETCH_ASSOC) {
 | 
        
           |  |  | 221 | 				// Get 2nd field's value regardless of its name
 | 
        
           |  |  | 222 | 				$zval2 = current(array_slice($zthis->fields, 1, 1));
 | 
        
           |  |  | 223 | 			} else {
 | 
        
           |  |  | 224 | 				// With NUM or BOTH fetch modes, we have a numeric index
 | 
        
           |  |  | 225 | 				$zval2 = $zthis->fields[1];
 | 
        
           |  |  | 226 | 			}
 | 
        
           |  |  | 227 | 			$zval2 = trim($zval2);
 | 
        
           |  |  | 228 | 			$value = 'value="' . htmlspecialchars($zval2) . '"';
 | 
        
           |  |  | 229 | 		}
 | 
        
           |  |  | 230 |   | 
        
           |  |  | 231 | 		/** @noinspection PhpUndefinedVariableInspection */
 | 
        
           |  |  | 232 | 		$s .= _adodb_getmenu_option($defstr, $compareFields0 ? $zval : $zval2, $value, $zval);
 | 
        
           |  |  | 233 |   | 
        
           |  |  | 234 | 		$zthis->MoveNext();
 | 
        
           |  |  | 235 | 	} // while
 | 
        
           |  |  | 236 |   | 
        
           |  |  | 237 | 	return $s ."\n</select>\n";
 | 
        
           |  |  | 238 | }
 | 
        
           |  |  | 239 |   | 
        
           |  |  | 240 | function _adodb_getmenu_gp($zthis, $name,$defstr='',$blank1stItem=true,$multiple=false,
 | 
        
           |  |  | 241 | 			$size=0, $selectAttr='',$compareFields0=true)
 | 
        
           |  |  | 242 | {
 | 
        
           |  |  | 243 | 	global $ADODB_FETCH_MODE;
 | 
        
           |  |  | 244 |   | 
        
           |  |  | 245 | 	$s = _adodb_getmenu_select($name, $defstr, $blank1stItem, $multiple, $size, $selectAttr);
 | 
        
           |  |  | 246 |   | 
        
           |  |  | 247 | 	$hasvalue = $zthis->FieldCount() > 1;
 | 
        
           |  |  | 248 | 	$hasgroup = $zthis->FieldCount() > 2;
 | 
        
           |  |  | 249 | 	if (!$hasvalue) {
 | 
        
           |  |  | 250 | 		$compareFields0 = true;
 | 
        
           |  |  | 251 | 	}
 | 
        
           |  |  | 252 |   | 
        
           |  |  | 253 | 	$value = '';
 | 
        
           |  |  | 254 | 	$optgroup = null;
 | 
        
           |  |  | 255 | 	$firstgroup = true;
 | 
        
           |  |  | 256 | 	while(!$zthis->EOF) {
 | 
        
           |  |  | 257 | 		$zval = rtrim(reset($zthis->fields));
 | 
        
           |  |  | 258 | 		$group = '';
 | 
        
           |  |  | 259 |   | 
        
           |  |  | 260 | 		if ($blank1stItem && $zval=="") {
 | 
        
           |  |  | 261 | 			$zthis->MoveNext();
 | 
        
           |  |  | 262 | 			continue;
 | 
        
           |  |  | 263 | 		}
 | 
        
           |  |  | 264 |   | 
        
           |  |  | 265 | 		if ($hasvalue) {
 | 
        
           |  |  | 266 | 			if ($ADODB_FETCH_MODE == ADODB_FETCH_ASSOC) {
 | 
        
           |  |  | 267 | 				// Get 2nd field's value regardless of its name
 | 
        
           |  |  | 268 | 				$fields = array_slice($zthis->fields, 1);
 | 
        
           |  |  | 269 | 				$zval2 = current($fields);
 | 
        
           |  |  | 270 | 				if ($hasgroup) {
 | 
        
           |  |  | 271 | 					$group = trim(next($fields));
 | 
        
           |  |  | 272 | 				}
 | 
        
           |  |  | 273 | 			} else {
 | 
        
           |  |  | 274 | 				// With NUM or BOTH fetch modes, we have a numeric index
 | 
        
           |  |  | 275 | 				$zval2 = $zthis->fields[1];
 | 
        
           |  |  | 276 | 				if ($hasgroup) {
 | 
        
           |  |  | 277 | 					$group = trim($zthis->fields[2]);
 | 
        
           |  |  | 278 | 				}
 | 
        
           |  |  | 279 | 			}
 | 
        
           |  |  | 280 | 			$zval2 = trim($zval2);
 | 
        
           |  |  | 281 | 			$value = "value='".htmlspecialchars($zval2)."'";
 | 
        
           |  |  | 282 | 		}
 | 
        
           |  |  | 283 |   | 
        
           |  |  | 284 | 		if ($optgroup != $group) {
 | 
        
           |  |  | 285 | 			$optgroup = $group;
 | 
        
           |  |  | 286 | 			if ($firstgroup) {
 | 
        
           |  |  | 287 | 				$firstgroup = false;
 | 
        
           |  |  | 288 | 			} else {
 | 
        
           |  |  | 289 | 				$s .="\n</optgroup>";
 | 
        
           |  |  | 290 | 			}
 | 
        
           |  |  | 291 | 			$s .="\n<optgroup label='". htmlspecialchars($group) ."'>";
 | 
        
           |  |  | 292 | 		}
 | 
        
           |  |  | 293 |   | 
        
           |  |  | 294 | 		/** @noinspection PhpUndefinedVariableInspection */
 | 
        
           |  |  | 295 | 		$s .= _adodb_getmenu_option($defstr, $compareFields0 ? $zval : $zval2, $value, $zval);
 | 
        
           |  |  | 296 |   | 
        
           |  |  | 297 | 		$zthis->MoveNext();
 | 
        
           |  |  | 298 | 	} // while
 | 
        
           |  |  | 299 |   | 
        
           |  |  | 300 | 	// closing last optgroup
 | 
        
           |  |  | 301 | 	if($optgroup != null) {
 | 
        
           |  |  | 302 | 		$s .= "\n</optgroup>";
 | 
        
           |  |  | 303 | 	}
 | 
        
           |  |  | 304 | 	return $s ."\n</select>\n";
 | 
        
           |  |  | 305 | }
 | 
        
           |  |  | 306 |   | 
        
           |  |  | 307 | /**
 | 
        
           |  |  | 308 |  * Generate the opening SELECT tag for getmenu functions.
 | 
        
           |  |  | 309 |  *
 | 
        
           |  |  | 310 |  * ADOdb internal function, used by _adodb_getmenu() and _adodb_getmenu_gp().
 | 
        
           |  |  | 311 |  *
 | 
        
           |  |  | 312 |  * @param string $name
 | 
        
           |  |  | 313 |  * @param string $defstr
 | 
        
           |  |  | 314 |  * @param bool   $blank1stItem
 | 
        
           |  |  | 315 |  * @param bool   $multiple
 | 
        
           |  |  | 316 |  * @param int    $size
 | 
        
           |  |  | 317 |  * @param string $selectAttr
 | 
        
           |  |  | 318 |  *
 | 
        
           |  |  | 319 |  * @return string HTML
 | 
        
           |  |  | 320 |  */
 | 
        
           |  |  | 321 | function _adodb_getmenu_select($name, $defstr = '', $blank1stItem = true,
 | 
        
           |  |  | 322 | 							   $multiple = false, $size = 0, $selectAttr = '')
 | 
        
           |  |  | 323 | {
 | 
        
           |  |  | 324 | 	if ($multiple || is_array($defstr)) {
 | 
        
           |  |  | 325 | 		if ($size == 0 ) {
 | 
        
           |  |  | 326 | 			$size = 5;
 | 
        
           |  |  | 327 | 		}
 | 
        
           |  |  | 328 | 		$attr = ' multiple size="' . $size . '"';
 | 
        
           |  |  | 329 | 		if (!strpos($name,'[]')) {
 | 
        
           |  |  | 330 | 			$name .= '[]';
 | 
        
           |  |  | 331 | 		}
 | 
        
           |  |  | 332 | 	} elseif ($size) {
 | 
        
           |  |  | 333 | 		$attr = ' size="' . $size . '"';
 | 
        
           |  |  | 334 | 	} else {
 | 
        
           |  |  | 335 | 		$attr = '';
 | 
        
           |  |  | 336 | 	}
 | 
        
           |  |  | 337 |   | 
        
           |  |  | 338 | 	$html = '<select name="' . $name . '"' . $attr . ' ' . $selectAttr . '>';
 | 
        
           |  |  | 339 | 	if ($blank1stItem) {
 | 
        
           |  |  | 340 | 		if (is_string($blank1stItem)) {
 | 
        
           |  |  | 341 | 			$barr = explode(':',$blank1stItem);
 | 
        
           |  |  | 342 | 			if (sizeof($barr) == 1) {
 | 
        
           |  |  | 343 | 				$barr[] = '';
 | 
        
           |  |  | 344 | 			}
 | 
        
           |  |  | 345 | 			$html .= "\n<option value=\"" . $barr[0] . "\">" . $barr[1] . "</option>";
 | 
        
           |  |  | 346 | 		} else {
 | 
        
           |  |  | 347 | 			$html .= "\n<option></option>";
 | 
        
           |  |  | 348 | 		}
 | 
        
           |  |  | 349 | 	}
 | 
        
           |  |  | 350 |   | 
        
           |  |  | 351 | 	return $html;
 | 
        
           |  |  | 352 | }
 | 
        
           |  |  | 353 |   | 
        
           |  |  | 354 | /**
 | 
        
           |  |  | 355 |  * Print the OPTION tags for getmenu functions.
 | 
        
           |  |  | 356 |  *
 | 
        
           |  |  | 357 |  * ADOdb internal function, used by _adodb_getmenu() and _adodb_getmenu_gp().
 | 
        
           |  |  | 358 |  *
 | 
        
           |  |  | 359 |  * @param string $defstr  Default values
 | 
        
           |  |  | 360 |  * @param string $compare Value to compare against defaults
 | 
        
           |  |  | 361 |  * @param string $value   Ready-to-print `value="xxx"` (or empty) string
 | 
        
           |  |  | 362 |  * @param string $display Display value
 | 
        
           |  |  | 363 |  *
 | 
        
           |  |  | 364 |  * @return string HTML
 | 
        
           |  |  | 365 |  */
 | 
        
           |  |  | 366 | function _adodb_getmenu_option($defstr, $compare, $value, $display)
 | 
        
           |  |  | 367 | {
 | 
        
           |  |  | 368 | 	if (   is_array($defstr) && in_array($compare, $defstr)
 | 
        
           | 1441 | ariadna | 369 | 		|| !is_array($defstr) && strcasecmp($compare, $defstr ?? '') == 0
 | 
        
           | 1 | efrain | 370 | 	) {
 | 
        
           |  |  | 371 | 		$selected = ' selected="selected"';
 | 
        
           |  |  | 372 | 	} else {
 | 
        
           |  |  | 373 | 		$selected = '';
 | 
        
           |  |  | 374 | 	}
 | 
        
           |  |  | 375 |   | 
        
           |  |  | 376 | 	return "\n<option $value$selected>" . htmlspecialchars($display) . '</option>';
 | 
        
           |  |  | 377 | }
 | 
        
           |  |  | 378 |   | 
        
           | 1441 | ariadna | 379 | /**
 | 
        
           |  |  | 380 |  * Count the number of records this sql statement will return by using
 | 
        
           |  |  | 381 |  * query rewriting heuristics...
 | 
        
           |  |  | 382 |  *
 | 
        
           |  |  | 383 |  * Does not work with UNIONs, except with postgresql and oracle.
 | 
        
           |  |  | 384 |  *
 | 
        
           |  |  | 385 |  * Usage:
 | 
        
           |  |  | 386 |  *     $conn->Connect(...);
 | 
        
           |  |  | 387 |  *     $cnt = _adodb_getcount($conn, $sql);
 | 
        
           |  |  | 388 |  *
 | 
        
           |  |  | 389 |  * @param ADOConnection $zthis
 | 
        
           |  |  | 390 |  * @param string        $sql
 | 
        
           |  |  | 391 |  * @param bool          $inputarr
 | 
        
           |  |  | 392 |  * @param int           $secs2cache
 | 
        
           |  |  | 393 |  *
 | 
        
           |  |  | 394 |  * @return false|int|mixed
 | 
        
           |  |  | 395 |  */
 | 
        
           | 1 | efrain | 396 | function _adodb_getcount($zthis, $sql,$inputarr=false,$secs2cache=0)
 | 
        
           |  |  | 397 | {
 | 
        
           |  |  | 398 | 	$qryRecs = 0;
 | 
        
           |  |  | 399 |   | 
        
           |  |  | 400 | 	/*
 | 
        
           |  |  | 401 | 	* These databases require a "SELECT * FROM (SELECT" type
 | 
        
           |  |  | 402 | 	* statement to have an alias for the result
 | 
        
           |  |  | 403 | 	*/
 | 
        
           |  |  | 404 | 	$requiresAlias = '';
 | 
        
           |  |  | 405 | 	$requiresAliasArray = array('postgres9','postgres','mysql','mysqli','mssql','mssqlnative','sqlsrv');
 | 
        
           |  |  | 406 | 	if (in_array($zthis->databaseType,$requiresAliasArray)
 | 
        
           |  |  | 407 | 		|| in_array($zthis->dsnType,$requiresAliasArray)
 | 
        
           |  |  | 408 | 	) {
 | 
        
           |  |  | 409 | 		$requiresAlias = '_ADODB_ALIAS_';
 | 
        
           |  |  | 410 | 	}
 | 
        
           |  |  | 411 |   | 
        
           |  |  | 412 | 	if (!empty($zthis->_nestedSQL)
 | 
        
           |  |  | 413 | 		|| preg_match("/^\s*SELECT\s+DISTINCT/is", $sql)
 | 
        
           |  |  | 414 | 		|| preg_match('/\s+GROUP\s+BY\s+/is',$sql)
 | 
        
           |  |  | 415 | 		|| preg_match('/\s+UNION\s+/is',$sql)
 | 
        
           |  |  | 416 | 	) {
 | 
        
           |  |  | 417 | 		$rewritesql = adodb_strip_order_by($sql);
 | 
        
           |  |  | 418 |   | 
        
           |  |  | 419 | 		// ok, has SELECT DISTINCT or GROUP BY so see if we can use a table alias
 | 
        
           |  |  | 420 | 		// but this is only supported by oracle and postgresql...
 | 
        
           |  |  | 421 | 		if ($zthis->dataProvider == 'oci8') {
 | 
        
           |  |  | 422 | 			// Allow Oracle hints to be used for query optimization, Chris Wrye
 | 
        
           |  |  | 423 | 			if (preg_match('#/\\*+.*?\\*\\/#', $sql, $hint)) {
 | 
        
           |  |  | 424 | 				$rewritesql = "SELECT ".$hint[0]." COUNT(*) FROM (".$rewritesql.")";
 | 
        
           |  |  | 425 | 			} else
 | 
        
           |  |  | 426 | 				$rewritesql = "SELECT COUNT(*) FROM (".$rewritesql.")";
 | 
        
           |  |  | 427 | 		} else {
 | 
        
           |  |  | 428 | 			$rewritesql = "SELECT COUNT(*) FROM ($rewritesql) $requiresAlias";
 | 
        
           |  |  | 429 | 		}
 | 
        
           |  |  | 430 |   | 
        
           |  |  | 431 | 	} else {
 | 
        
           |  |  | 432 | 		// Replace 'SELECT ... FROM' with 'SELECT COUNT(*) FROM'
 | 
        
           |  |  | 433 | 		// Parse the query one char at a time starting after the SELECT
 | 
        
           |  |  | 434 | 		// to find the FROM clause's position, ignoring any sub-queries.
 | 
        
           |  |  | 435 | 		$start = stripos($sql, 'SELECT') + 7;
 | 
        
           |  |  | 436 | 		if ($start === false) {
 | 
        
           |  |  | 437 | 			// Not a SELECT statement - probably should trigger an exception here
 | 
        
           |  |  | 438 | 			return 0;
 | 
        
           |  |  | 439 | 		}
 | 
        
           |  |  | 440 | 		$len = strlen($sql);
 | 
        
           |  |  | 441 | 		$numParentheses = 0;
 | 
        
           |  |  | 442 | 		for ($pos = $start; $pos < $len; $pos++) {
 | 
        
           |  |  | 443 | 			switch ($sql[$pos]) {
 | 
        
           |  |  | 444 | 				case '(': $numParentheses++; continue 2;
 | 
        
           |  |  | 445 | 				case ')': $numParentheses--; continue 2;
 | 
        
           |  |  | 446 | 			}
 | 
        
           |  |  | 447 | 			// Ignore whatever is between parentheses (sub-queries)
 | 
        
           |  |  | 448 | 			if ($numParentheses > 0) {
 | 
        
           |  |  | 449 | 				continue;
 | 
        
           |  |  | 450 | 			}
 | 
        
           |  |  | 451 | 			// Exit loop if 'FROM' keyword was found
 | 
        
           |  |  | 452 | 			if (strtoupper(substr($sql, $pos, 4)) == 'FROM') {
 | 
        
           |  |  | 453 | 				break;
 | 
        
           |  |  | 454 | 			}
 | 
        
           |  |  | 455 | 		}
 | 
        
           |  |  | 456 | 		$rewritesql = 'SELECT COUNT(*) ' . substr($sql, $pos);
 | 
        
           |  |  | 457 |   | 
        
           |  |  | 458 | 		// fix by alexander zhukov, alex#unipack.ru, because count(*) and 'order by' fails
 | 
        
           |  |  | 459 | 		// with mssql, access and postgresql. Also a good speedup optimization - skips sorting!
 | 
        
           |  |  | 460 | 		// also see PHPLens Issue No: 12752
 | 
        
           |  |  | 461 | 		$rewritesql = adodb_strip_order_by($rewritesql);
 | 
        
           |  |  | 462 | 	}
 | 
        
           |  |  | 463 |   | 
        
           |  |  | 464 | 	if (isset($rewritesql) && $rewritesql != $sql) {
 | 
        
           |  |  | 465 | 		if (preg_match('/\sLIMIT\s+[0-9]+/i',$sql,$limitarr)) {
 | 
        
           |  |  | 466 | 			$rewritesql .= $limitarr[0];
 | 
        
           |  |  | 467 | 		}
 | 
        
           |  |  | 468 |   | 
        
           |  |  | 469 | 		if ($secs2cache) {
 | 
        
           |  |  | 470 | 			// we only use half the time of secs2cache because the count can quickly
 | 
        
           |  |  | 471 | 			// become inaccurate if new records are added
 | 
        
           |  |  | 472 | 			$qryRecs = $zthis->CacheGetOne($secs2cache/2,$rewritesql,$inputarr);
 | 
        
           |  |  | 473 |   | 
        
           |  |  | 474 | 		} else {
 | 
        
           |  |  | 475 | 			$qryRecs = $zthis->GetOne($rewritesql,$inputarr);
 | 
        
           |  |  | 476 | 		}
 | 
        
           |  |  | 477 | 		if ($qryRecs !== false) return $qryRecs;
 | 
        
           |  |  | 478 | 	}
 | 
        
           |  |  | 479 |   | 
        
           |  |  | 480 | 	//--------------------------------------------
 | 
        
           |  |  | 481 | 	// query rewrite failed - so try slower way...
 | 
        
           |  |  | 482 |   | 
        
           |  |  | 483 | 	// strip off unneeded ORDER BY if no UNION
 | 
        
           |  |  | 484 | 	if (preg_match('/\s*UNION\s*/is', $sql)) {
 | 
        
           |  |  | 485 | 		$rewritesql = $sql;
 | 
        
           |  |  | 486 | 	} else {
 | 
        
           |  |  | 487 | 		$rewritesql = adodb_strip_order_by($sql);
 | 
        
           |  |  | 488 | 	}
 | 
        
           |  |  | 489 |   | 
        
           |  |  | 490 | 	if (preg_match('/\sLIMIT\s+[0-9]+/i',$sql,$limitarr)) {
 | 
        
           |  |  | 491 | 		$rewritesql .= $limitarr[0];
 | 
        
           |  |  | 492 | 	}
 | 
        
           |  |  | 493 |   | 
        
           |  |  | 494 | 	if ($secs2cache) {
 | 
        
           |  |  | 495 | 		$rstest = $zthis->CacheExecute($secs2cache,$rewritesql,$inputarr);
 | 
        
           |  |  | 496 | 		if (!$rstest) $rstest = $zthis->CacheExecute($secs2cache,$sql,$inputarr);
 | 
        
           |  |  | 497 | 	} else {
 | 
        
           |  |  | 498 | 		$rstest = $zthis->Execute($rewritesql,$inputarr);
 | 
        
           |  |  | 499 | 		if (!$rstest) $rstest = $zthis->Execute($sql,$inputarr);
 | 
        
           |  |  | 500 | 	}
 | 
        
           |  |  | 501 | 	if ($rstest) {
 | 
        
           |  |  | 502 | 		$qryRecs = $rstest->RecordCount();
 | 
        
           |  |  | 503 | 		if ($qryRecs == -1) {
 | 
        
           |  |  | 504 | 			// some databases will return -1 on MoveLast() - change to MoveNext()
 | 
        
           |  |  | 505 | 			while(!$rstest->EOF) {
 | 
        
           |  |  | 506 | 				$rstest->MoveNext();
 | 
        
           |  |  | 507 | 			}
 | 
        
           |  |  | 508 | 			$qryRecs = $rstest->_currentRow;
 | 
        
           |  |  | 509 | 		}
 | 
        
           |  |  | 510 | 		$rstest->Close();
 | 
        
           |  |  | 511 | 		if ($qryRecs == -1) return 0;
 | 
        
           |  |  | 512 | 	}
 | 
        
           |  |  | 513 | 	return $qryRecs;
 | 
        
           |  |  | 514 | }
 | 
        
           |  |  | 515 |   | 
        
           |  |  | 516 | /**
 | 
        
           |  |  | 517 |  * Execute query with pagination including record count.
 | 
        
           |  |  | 518 |  *
 | 
        
           |  |  | 519 |  * This code might not work with SQL that has UNION in it.
 | 
        
           |  |  | 520 |  * Also if you are using cachePageExecute(), there is a strong possibility that
 | 
        
           |  |  | 521 |  * data will get out of sync. cachePageExecute() should only be used with
 | 
        
           |  |  | 522 |  * tables that rarely change.
 | 
        
           |  |  | 523 |  *
 | 
        
           |  |  | 524 |  * @param ADOConnection $zthis      Connection
 | 
        
           |  |  | 525 |  * @param string        $sql        Query to execute
 | 
        
           |  |  | 526 |  * @param int           $nrows      Number of rows per page
 | 
        
           |  |  | 527 |  * @param int           $page       Page number to retrieve (1-based)
 | 
        
           |  |  | 528 |  * @param array         $inputarr   Array of bind variables
 | 
        
           |  |  | 529 |  * @param int           $secs2cache Time-to-live of the cache (in seconds), 0 to force query execution
 | 
        
           |  |  | 530 |  *
 | 
        
           |  |  | 531 |  * @return ADORecordSet|bool
 | 
        
           |  |  | 532 |  *
 | 
        
           |  |  | 533 |  * @author Cornel G <conyg@fx.ro>
 | 
        
           |  |  | 534 |  */
 | 
        
           |  |  | 535 | function _adodb_pageexecute_all_rows($zthis, $sql, $nrows, $page, $inputarr=false, $secs2cache=0)
 | 
        
           |  |  | 536 | {
 | 
        
           |  |  | 537 | 	$atfirstpage = false;
 | 
        
           |  |  | 538 | 	$atlastpage = false;
 | 
        
           |  |  | 539 |   | 
        
           |  |  | 540 | 	// If an invalid nrows is supplied, assume a default value of 10 rows per page
 | 
        
           |  |  | 541 | 	if (!isset($nrows) || $nrows <= 0) $nrows = 10;
 | 
        
           |  |  | 542 |   | 
        
           |  |  | 543 | 	$qryRecs = _adodb_getcount($zthis,$sql,$inputarr,$secs2cache);
 | 
        
           |  |  | 544 | 	$lastpageno = (int) ceil($qryRecs / $nrows);
 | 
        
           |  |  | 545 |   | 
        
           |  |  | 546 | 	// Check whether $page is the last page or if we are trying to retrieve
 | 
        
           |  |  | 547 | 	// a page number greater than the last one.
 | 
        
           |  |  | 548 | 	if ($page >= $lastpageno) {
 | 
        
           |  |  | 549 | 		$page = $lastpageno;
 | 
        
           |  |  | 550 | 		$atlastpage = true;
 | 
        
           |  |  | 551 | 	}
 | 
        
           |  |  | 552 |   | 
        
           |  |  | 553 | 	// If page number <= 1, then we are at the first page
 | 
        
           |  |  | 554 | 	if (empty($page) || $page <= 1) {
 | 
        
           |  |  | 555 | 		$page = 1;
 | 
        
           |  |  | 556 | 		$atfirstpage = true;
 | 
        
           |  |  | 557 | 	}
 | 
        
           |  |  | 558 |   | 
        
           |  |  | 559 | 	// We get the data we want
 | 
        
           |  |  | 560 | 	$offset = $nrows * ($page-1);
 | 
        
           |  |  | 561 | 	if ($secs2cache > 0)
 | 
        
           |  |  | 562 | 		$rsreturn = $zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $offset, $inputarr);
 | 
        
           |  |  | 563 | 	else
 | 
        
           |  |  | 564 | 		$rsreturn = $zthis->SelectLimit($sql, $nrows, $offset, $inputarr, $secs2cache);
 | 
        
           |  |  | 565 |   | 
        
           |  |  | 566 |   | 
        
           |  |  | 567 | 	// Before returning the RecordSet, we set the pagination properties we need
 | 
        
           |  |  | 568 | 	if ($rsreturn) {
 | 
        
           |  |  | 569 | 		$rsreturn->_maxRecordCount = $qryRecs;
 | 
        
           |  |  | 570 | 		$rsreturn->rowsPerPage = $nrows;
 | 
        
           |  |  | 571 | 		$rsreturn->AbsolutePage($page);
 | 
        
           |  |  | 572 | 		$rsreturn->AtFirstPage($atfirstpage);
 | 
        
           |  |  | 573 | 		$rsreturn->AtLastPage($atlastpage);
 | 
        
           |  |  | 574 | 		$rsreturn->LastPageNo($lastpageno);
 | 
        
           |  |  | 575 | 	}
 | 
        
           |  |  | 576 | 	return $rsreturn;
 | 
        
           |  |  | 577 | }
 | 
        
           |  |  | 578 |   | 
        
           |  |  | 579 | /**
 | 
        
           |  |  | 580 |  * Execute query with pagination without last page information.
 | 
        
           |  |  | 581 |  *
 | 
        
           |  |  | 582 |  * This code might not work with SQL that has UNION in it.
 | 
        
           |  |  | 583 |  * Also if you are using cachePageExecute(), there is a strong possibility that
 | 
        
           |  |  | 584 |  * data will get out of sync. cachePageExecute() should only be used with
 | 
        
           |  |  | 585 |  * tables that rarely change.
 | 
        
           |  |  | 586 |  *
 | 
        
           |  |  | 587 |  * @param ADOConnection $zthis      Connection
 | 
        
           |  |  | 588 |  * @param string        $sql        Query to execute
 | 
        
           |  |  | 589 |  * @param int           $nrows      Number of rows per page
 | 
        
           |  |  | 590 |  * @param int           $page       Page number to retrieve (1-based)
 | 
        
           |  |  | 591 |  * @param array         $inputarr   Array of bind variables
 | 
        
           |  |  | 592 |  * @param int           $secs2cache Time-to-live of the cache (in seconds), 0 to force query execution
 | 
        
           |  |  | 593 |  *
 | 
        
           |  |  | 594 |  * @return ADORecordSet|bool
 | 
        
           |  |  | 595 |  *
 | 
        
           |  |  | 596 |  * @author Iván Oliva
 | 
        
           |  |  | 597 |  */
 | 
        
           |  |  | 598 | function _adodb_pageexecute_no_last_page($zthis, $sql, $nrows, $page, $inputarr=false, $secs2cache=0)
 | 
        
           |  |  | 599 | {
 | 
        
           |  |  | 600 | 	$atfirstpage = false;
 | 
        
           |  |  | 601 | 	$atlastpage = false;
 | 
        
           |  |  | 602 |   | 
        
           |  |  | 603 | 	if (!isset($page) || $page <= 1) {
 | 
        
           |  |  | 604 | 		// If page number <= 1, then we are at the first page
 | 
        
           |  |  | 605 | 		$page = 1;
 | 
        
           |  |  | 606 | 		$atfirstpage = true;
 | 
        
           |  |  | 607 | 	}
 | 
        
           |  |  | 608 | 	if ($nrows <= 0) {
 | 
        
           |  |  | 609 | 		// If an invalid nrows is supplied, we assume a default value of 10 rows per page
 | 
        
           |  |  | 610 | 		$nrows = 10;
 | 
        
           |  |  | 611 | 	}
 | 
        
           |  |  | 612 |   | 
        
           |  |  | 613 | 	$pagecounteroffset = ($page * $nrows) - $nrows;
 | 
        
           |  |  | 614 |   | 
        
           |  |  | 615 | 	// To find out if there are more pages of rows, simply increase the limit or
 | 
        
           |  |  | 616 | 	// nrows by 1 and see if that number of records was returned. If it was,
 | 
        
           |  |  | 617 | 	// then we know there is at least one more page left, otherwise we are on
 | 
        
           |  |  | 618 | 	// the last page. Therefore allow non-Count() paging with single queries
 | 
        
           |  |  | 619 | 	// rather than three queries as was done before.
 | 
        
           |  |  | 620 | 	$test_nrows = $nrows + 1;
 | 
        
           |  |  | 621 | 	if ($secs2cache > 0) {
 | 
        
           |  |  | 622 | 		$rsreturn = $zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $pagecounteroffset, $inputarr);
 | 
        
           |  |  | 623 | 	} else {
 | 
        
           |  |  | 624 | 		$rsreturn = $zthis->SelectLimit($sql, $test_nrows, $pagecounteroffset, $inputarr, $secs2cache);
 | 
        
           |  |  | 625 | 	}
 | 
        
           |  |  | 626 |   | 
        
           |  |  | 627 | 	// Now check to see if the number of rows returned was the higher value we asked for or not.
 | 
        
           |  |  | 628 | 	if ( $rsreturn->_numOfRows == $test_nrows ) {
 | 
        
           |  |  | 629 | 		// Still at least 1 more row, so we are not on last page yet...
 | 
        
           |  |  | 630 | 		// Remove the last row from the RS.
 | 
        
           |  |  | 631 | 		$rsreturn->_numOfRows = ( $rsreturn->_numOfRows - 1 );
 | 
        
           |  |  | 632 | 	} elseif ( $rsreturn->_numOfRows == 0 && $page > 1 ) {
 | 
        
           |  |  | 633 | 		// Likely requested a page that doesn't exist, so need to find the last
 | 
        
           |  |  | 634 | 		// page and return it. Revert to original method and loop through pages
 | 
        
           |  |  | 635 | 		// until we find some data...
 | 
        
           |  |  | 636 | 		$pagecounter = $page + 1;
 | 
        
           |  |  | 637 |   | 
        
           |  |  | 638 | 		$rstest = $rsreturn;
 | 
        
           |  |  | 639 | 		if ($rstest) {
 | 
        
           |  |  | 640 | 			while ($rstest && $rstest->EOF && $pagecounter > 0) {
 | 
        
           |  |  | 641 | 				$atlastpage = true;
 | 
        
           |  |  | 642 | 				$pagecounter--;
 | 
        
           |  |  | 643 | 				$pagecounteroffset = $nrows * ($pagecounter - 1);
 | 
        
           |  |  | 644 | 				$rstest->Close();
 | 
        
           |  |  | 645 | 				if ($secs2cache>0) {
 | 
        
           |  |  | 646 | 					$rstest = $zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $pagecounteroffset, $inputarr);
 | 
        
           |  |  | 647 | 				}
 | 
        
           |  |  | 648 | 				else {
 | 
        
           |  |  | 649 | 					$rstest = $zthis->SelectLimit($sql, $nrows, $pagecounteroffset, $inputarr, $secs2cache);
 | 
        
           |  |  | 650 | 				}
 | 
        
           |  |  | 651 | 			}
 | 
        
           |  |  | 652 | 			if ($rstest) $rstest->Close();
 | 
        
           |  |  | 653 | 		}
 | 
        
           |  |  | 654 | 		if ($atlastpage) {
 | 
        
           |  |  | 655 | 			// If we are at the last page or beyond it, we are going to retrieve it
 | 
        
           |  |  | 656 | 			$page = $pagecounter;
 | 
        
           |  |  | 657 | 			if ($page == 1) {
 | 
        
           |  |  | 658 | 				// We have to do this again in case the last page is the same as
 | 
        
           |  |  | 659 | 				// the first page, that is, the recordset has only 1 page.
 | 
        
           |  |  | 660 | 				$atfirstpage = true;
 | 
        
           |  |  | 661 | 			}
 | 
        
           |  |  | 662 | 		}
 | 
        
           |  |  | 663 | 		// We get the data we want
 | 
        
           |  |  | 664 | 		$offset = $nrows * ($page-1);
 | 
        
           |  |  | 665 | 		if ($secs2cache > 0) {
 | 
        
           |  |  | 666 | 			$rsreturn = $zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $offset, $inputarr);
 | 
        
           |  |  | 667 | 		}
 | 
        
           |  |  | 668 | 		else {
 | 
        
           |  |  | 669 | 			$rsreturn = $zthis->SelectLimit($sql, $nrows, $offset, $inputarr, $secs2cache);
 | 
        
           |  |  | 670 | 		}
 | 
        
           |  |  | 671 | 	} elseif ( $rsreturn->_numOfRows < $test_nrows ) {
 | 
        
           |  |  | 672 | 		// Rows is less than what we asked for, so must be at the last page.
 | 
        
           |  |  | 673 | 		$atlastpage = true;
 | 
        
           |  |  | 674 | 	}
 | 
        
           |  |  | 675 |   | 
        
           |  |  | 676 | 	// Before returning the RecordSet, we set the pagination properties we need
 | 
        
           |  |  | 677 | 	if ($rsreturn) {
 | 
        
           |  |  | 678 | 		$rsreturn->rowsPerPage = $nrows;
 | 
        
           |  |  | 679 | 		$rsreturn->AbsolutePage($page);
 | 
        
           |  |  | 680 | 		$rsreturn->AtFirstPage($atfirstpage);
 | 
        
           |  |  | 681 | 		$rsreturn->AtLastPage($atlastpage);
 | 
        
           |  |  | 682 | 	}
 | 
        
           |  |  | 683 | 	return $rsreturn;
 | 
        
           |  |  | 684 | }
 | 
        
           |  |  | 685 |   | 
        
           |  |  | 686 | /**
 | 
        
           |  |  | 687 |  * Performs case conversion and quoting of the given field name.
 | 
        
           |  |  | 688 |  *
 | 
        
           |  |  | 689 |  * See Global variable $ADODB_QUOTE_FIELDNAMES.
 | 
        
           |  |  | 690 |  *
 | 
        
           |  |  | 691 |  * @param ADOConnection $zthis
 | 
        
           |  |  | 692 |  * @param string $fieldName
 | 
        
           |  |  | 693 |  *
 | 
        
           |  |  | 694 |  * @return string Quoted field name
 | 
        
           |  |  | 695 |  */
 | 
        
           |  |  | 696 | function _adodb_quote_fieldname($zthis, $fieldName)
 | 
        
           |  |  | 697 | {
 | 
        
           |  |  | 698 | 	global $ADODB_QUOTE_FIELDNAMES;
 | 
        
           |  |  | 699 |   | 
        
           |  |  | 700 | 	// Case conversion - defaults to UPPER
 | 
        
           |  |  | 701 | 	$case = is_bool($ADODB_QUOTE_FIELDNAMES) ? 'UPPER' : $ADODB_QUOTE_FIELDNAMES;
 | 
        
           |  |  | 702 | 	switch ($case) {
 | 
        
           |  |  | 703 | 		case 'LOWER':
 | 
        
           |  |  | 704 | 			$fieldName = strtolower($fieldName);
 | 
        
           |  |  | 705 | 			break;
 | 
        
           |  |  | 706 | 		case 'NATIVE':
 | 
        
           |  |  | 707 | 			// Do nothing
 | 
        
           |  |  | 708 | 			break;
 | 
        
           |  |  | 709 | 		case 'UPPER':
 | 
        
           |  |  | 710 | 		case 'BRACKETS':
 | 
        
           |  |  | 711 | 		default:
 | 
        
           |  |  | 712 | 			$fieldName = strtoupper($fieldName);
 | 
        
           |  |  | 713 | 			break;
 | 
        
           |  |  | 714 | 	}
 | 
        
           |  |  | 715 |   | 
        
           |  |  | 716 | 	// Quote field if requested, or necessary (field contains space)
 | 
        
           |  |  | 717 | 	if ($ADODB_QUOTE_FIELDNAMES || strpos($fieldName, ' ') !== false ) {
 | 
        
           |  |  | 718 | 		if ($ADODB_QUOTE_FIELDNAMES === 'BRACKETS') {
 | 
        
           |  |  | 719 | 			return $zthis->leftBracket . $fieldName . $zthis->rightBracket;
 | 
        
           |  |  | 720 | 		} else {
 | 
        
           |  |  | 721 | 			return $zthis->nameQuote . $fieldName . $zthis->nameQuote;
 | 
        
           |  |  | 722 | 		}
 | 
        
           |  |  | 723 | 	} else {
 | 
        
           |  |  | 724 | 		return $fieldName;
 | 
        
           |  |  | 725 | 	}
 | 
        
           |  |  | 726 | }
 | 
        
           |  |  | 727 |   | 
        
           |  |  | 728 | function _adodb_getupdatesql(&$zthis, $rs, $arrFields, $forceUpdate=false, $force=2)
 | 
        
           |  |  | 729 | {
 | 
        
           |  |  | 730 | 	if (!$rs) {
 | 
        
           |  |  | 731 | 		printf(ADODB_BAD_RS,'GetUpdateSQL');
 | 
        
           |  |  | 732 | 		return false;
 | 
        
           |  |  | 733 | 	}
 | 
        
           |  |  | 734 |   | 
        
           |  |  | 735 | 	$fieldUpdatedCount = 0;
 | 
        
           |  |  | 736 | 	if (is_array($arrFields))
 | 
        
           |  |  | 737 | 		$arrFields = array_change_key_case($arrFields,CASE_UPPER);
 | 
        
           |  |  | 738 |   | 
        
           |  |  | 739 | 	$hasnumeric = isset($rs->fields[0]);
 | 
        
           |  |  | 740 | 	$setFields = '';
 | 
        
           |  |  | 741 |   | 
        
           |  |  | 742 | 	// Loop through all of the fields in the recordset
 | 
        
           |  |  | 743 | 	for ($i=0, $max=$rs->fieldCount(); $i < $max; $i++) {
 | 
        
           |  |  | 744 | 		// Get the field from the recordset
 | 
        
           |  |  | 745 | 		$field = $rs->fetchField($i);
 | 
        
           |  |  | 746 |   | 
        
           |  |  | 747 | 		// If the recordset field is one
 | 
        
           |  |  | 748 | 		// of the fields passed in then process.
 | 
        
           |  |  | 749 | 		$upperfname = strtoupper($field->name);
 | 
        
           |  |  | 750 | 		if (adodb_key_exists($upperfname, $arrFields, $force)) {
 | 
        
           |  |  | 751 |   | 
        
           |  |  | 752 | 			// If the existing field value in the recordset
 | 
        
           |  |  | 753 | 			// is different from the value passed in then
 | 
        
           |  |  | 754 | 			// go ahead and append the field name and new value to
 | 
        
           |  |  | 755 | 			// the update query.
 | 
        
           |  |  | 756 |   | 
        
           |  |  | 757 | 			if ($hasnumeric) $val = $rs->fields[$i];
 | 
        
           |  |  | 758 | 			else if (isset($rs->fields[$upperfname])) $val = $rs->fields[$upperfname];
 | 
        
           |  |  | 759 | 			else if (isset($rs->fields[$field->name])) $val = $rs->fields[$field->name];
 | 
        
           |  |  | 760 | 			else if (isset($rs->fields[strtolower($upperfname)])) $val = $rs->fields[strtolower($upperfname)];
 | 
        
           |  |  | 761 | 			else $val = '';
 | 
        
           |  |  | 762 |   | 
        
           |  |  | 763 | 			if ($forceUpdate || $val !== $arrFields[$upperfname]) {
 | 
        
           |  |  | 764 | 				// Set the counter for the number of fields that will be updated.
 | 
        
           |  |  | 765 | 				$fieldUpdatedCount++;
 | 
        
           |  |  | 766 |   | 
        
           |  |  | 767 | 				// Based on the datatype of the field
 | 
        
           |  |  | 768 | 				// Format the value properly for the database
 | 
        
           |  |  | 769 | 				$type = $rs->metaType($field->type);
 | 
        
           |  |  | 770 |   | 
        
           |  |  | 771 | 				if ($type == 'null') {
 | 
        
           |  |  | 772 | 					$type = 'C';
 | 
        
           |  |  | 773 | 				}
 | 
        
           |  |  | 774 |   | 
        
           |  |  | 775 | 				$fnameq = _adodb_quote_fieldname($zthis, $field->name);
 | 
        
           |  |  | 776 |   | 
        
           |  |  | 777 | 				//********************************************************//
 | 
        
           |  |  | 778 | 				if (is_null($arrFields[$upperfname])
 | 
        
           |  |  | 779 | 					|| (empty($arrFields[$upperfname]) && strlen($arrFields[$upperfname]) == 0)
 | 
        
           |  |  | 780 | 					|| $arrFields[$upperfname] === $zthis->null2null
 | 
        
           |  |  | 781 | 					) {
 | 
        
           |  |  | 782 |   | 
        
           |  |  | 783 | 					switch ($force) {
 | 
        
           |  |  | 784 |   | 
        
           |  |  | 785 | 						//case 0:
 | 
        
           |  |  | 786 | 						//	// Ignore empty values. This is already handled in "adodb_key_exists" function.
 | 
        
           |  |  | 787 | 						//	break;
 | 
        
           |  |  | 788 |   | 
        
           |  |  | 789 | 						case 1:
 | 
        
           |  |  | 790 | 							// set null
 | 
        
           |  |  | 791 | 							$setFields .= $fnameq . " = null, ";
 | 
        
           |  |  | 792 | 							break;
 | 
        
           |  |  | 793 |   | 
        
           |  |  | 794 | 						case 2:
 | 
        
           |  |  | 795 | 							// set empty
 | 
        
           |  |  | 796 | 							$arrFields[$upperfname] = "";
 | 
        
           |  |  | 797 | 							$setFields .= _adodb_column_sql($zthis, 'U', $type, $upperfname, $fnameq, $arrFields);
 | 
        
           |  |  | 798 | 							break;
 | 
        
           |  |  | 799 |   | 
        
           |  |  | 800 | 						default:
 | 
        
           |  |  | 801 | 						case 3:
 | 
        
           |  |  | 802 | 							// set the value that was given in array, so you can give both null and empty values
 | 
        
           |  |  | 803 | 							if (is_null($arrFields[$upperfname]) || $arrFields[$upperfname] === $zthis->null2null) {
 | 
        
           |  |  | 804 | 								$setFields .= $fnameq . " = null, ";
 | 
        
           |  |  | 805 | 							} else {
 | 
        
           |  |  | 806 | 								$setFields .= _adodb_column_sql($zthis, 'U', $type, $upperfname, $fnameq, $arrFields);
 | 
        
           |  |  | 807 | 							}
 | 
        
           |  |  | 808 | 							break;
 | 
        
           |  |  | 809 |   | 
        
           |  |  | 810 | 						case ADODB_FORCE_NULL_AND_ZERO:
 | 
        
           |  |  | 811 |   | 
        
           |  |  | 812 | 							switch ($type) {
 | 
        
           |  |  | 813 | 								case 'N':
 | 
        
           |  |  | 814 | 								case 'I':
 | 
        
           |  |  | 815 | 								case 'L':
 | 
        
           |  |  | 816 | 									$setFields .= $fnameq . ' = 0, ';
 | 
        
           |  |  | 817 | 									break;
 | 
        
           |  |  | 818 | 								default:
 | 
        
           |  |  | 819 | 									$setFields .= $fnameq . ' = null, ';
 | 
        
           |  |  | 820 | 									break;
 | 
        
           |  |  | 821 | 							}
 | 
        
           |  |  | 822 | 							break;
 | 
        
           |  |  | 823 |   | 
        
           |  |  | 824 | 					}
 | 
        
           |  |  | 825 | 				//********************************************************//
 | 
        
           |  |  | 826 | 				} else {
 | 
        
           |  |  | 827 | 					// we do this so each driver can customize the sql for
 | 
        
           |  |  | 828 | 					// DB specific column types.
 | 
        
           |  |  | 829 | 					// Oracle needs BLOB types to be handled with a returning clause
 | 
        
           |  |  | 830 | 					// postgres has special needs as well
 | 
        
           |  |  | 831 | 					$setFields .= _adodb_column_sql($zthis, 'U', $type, $upperfname, $fnameq, $arrFields);
 | 
        
           |  |  | 832 | 				}
 | 
        
           |  |  | 833 | 			}
 | 
        
           |  |  | 834 | 		}
 | 
        
           |  |  | 835 | 	}
 | 
        
           |  |  | 836 |   | 
        
           |  |  | 837 | 	// If there were any modified fields then build the rest of the update query.
 | 
        
           |  |  | 838 | 	if ($fieldUpdatedCount > 0 || $forceUpdate) {
 | 
        
           |  |  | 839 | 		// Get the table name from the existing query.
 | 
        
           |  |  | 840 | 		if (!empty($rs->tableName)) {
 | 
        
           |  |  | 841 | 			$tableName = $rs->tableName;
 | 
        
           |  |  | 842 | 		} else {
 | 
        
           |  |  | 843 | 			preg_match("/FROM\s+".ADODB_TABLE_REGEX."/is", $rs->sql, $tableName);
 | 
        
           |  |  | 844 | 			$tableName = $tableName[1];
 | 
        
           |  |  | 845 | 		}
 | 
        
           |  |  | 846 |   | 
        
           |  |  | 847 | 		// Get the full where clause excluding the word "WHERE" from the existing query.
 | 
        
           |  |  | 848 | 		preg_match('/\sWHERE\s(.*)/is', $rs->sql, $whereClause);
 | 
        
           |  |  | 849 |   | 
        
           |  |  | 850 | 		$discard = false;
 | 
        
           |  |  | 851 | 		// not a good hack, improvements?
 | 
        
           |  |  | 852 | 		if ($whereClause) {
 | 
        
           |  |  | 853 | 			if (preg_match('/\s(ORDER\s.*)/is', $whereClause[1], $discard));
 | 
        
           |  |  | 854 | 			else if (preg_match('/\s(LIMIT\s.*)/is', $whereClause[1], $discard));
 | 
        
           |  |  | 855 | 			else if (preg_match('/\s(FOR UPDATE.*)/is', $whereClause[1], $discard));
 | 
        
           |  |  | 856 | 			else preg_match('/\s.*(\) WHERE .*)/is', $whereClause[1], $discard); # see https://sourceforge.net/p/adodb/bugs/37/
 | 
        
           |  |  | 857 | 		} else {
 | 
        
           |  |  | 858 | 			$whereClause = array(false, false);
 | 
        
           |  |  | 859 | 		}
 | 
        
           |  |  | 860 |   | 
        
           |  |  | 861 | 		if ($discard) {
 | 
        
           |  |  | 862 | 			$whereClause[1] = substr($whereClause[1], 0, strlen($whereClause[1]) - strlen($discard[1]));
 | 
        
           |  |  | 863 | 		}
 | 
        
           |  |  | 864 |   | 
        
           |  |  | 865 | 		$sql = 'UPDATE '.$tableName.' SET '.substr($setFields, 0, -2);
 | 
        
           |  |  | 866 | 		if (strlen($whereClause[1]) > 0) {
 | 
        
           |  |  | 867 | 			$sql .= ' WHERE '.$whereClause[1];
 | 
        
           |  |  | 868 | 		}
 | 
        
           |  |  | 869 | 		return $sql;
 | 
        
           |  |  | 870 | 	} else {
 | 
        
           |  |  | 871 | 		return false;
 | 
        
           |  |  | 872 | 	}
 | 
        
           |  |  | 873 | }
 | 
        
           |  |  | 874 |   | 
        
           |  |  | 875 | function adodb_key_exists($key, $arr,$force=2)
 | 
        
           |  |  | 876 | {
 | 
        
           |  |  | 877 | 	if ($force<=0) {
 | 
        
           |  |  | 878 | 		// the following is the old behaviour where null or empty fields are ignored
 | 
        
           |  |  | 879 | 		return (!empty($arr[$key])) || (isset($arr[$key]) && strlen($arr[$key])>0);
 | 
        
           |  |  | 880 | 	}
 | 
        
           |  |  | 881 |   | 
        
           |  |  | 882 | 	if (isset($arr[$key]))
 | 
        
           |  |  | 883 | 		return true;
 | 
        
           |  |  | 884 | 	## null check below
 | 
        
           |  |  | 885 | 	return array_key_exists($key,$arr);
 | 
        
           |  |  | 886 | }
 | 
        
           |  |  | 887 |   | 
        
           |  |  | 888 | /**
 | 
        
           |  |  | 889 |  * There is a special case of this function for the oci8 driver.
 | 
        
           |  |  | 890 |  * The proper way to handle an insert w/ a blob in oracle requires
 | 
        
           |  |  | 891 |  * a returning clause with bind variables and a descriptor blob.
 | 
        
           |  |  | 892 |  *
 | 
        
           |  |  | 893 |  *
 | 
        
           |  |  | 894 |  */
 | 
        
           |  |  | 895 | function _adodb_getinsertsql(&$zthis, $rs, $arrFields, $force=2)
 | 
        
           |  |  | 896 | {
 | 
        
           |  |  | 897 | static $cacheRS = false;
 | 
        
           |  |  | 898 | static $cacheSig = 0;
 | 
        
           |  |  | 899 | static $cacheCols;
 | 
        
           |  |  | 900 |   | 
        
           |  |  | 901 | 	$tableName = '';
 | 
        
           |  |  | 902 | 	$values = '';
 | 
        
           |  |  | 903 | 	$fields = '';
 | 
        
           |  |  | 904 | 	if (is_array($arrFields))
 | 
        
           |  |  | 905 | 		$arrFields = array_change_key_case($arrFields,CASE_UPPER);
 | 
        
           |  |  | 906 | 	$fieldInsertedCount = 0;
 | 
        
           |  |  | 907 |   | 
        
           |  |  | 908 | 	if (is_string($rs)) {
 | 
        
           |  |  | 909 | 		//ok we have a table name
 | 
        
           |  |  | 910 | 		//try and get the column info ourself.
 | 
        
           |  |  | 911 | 		$tableName = $rs;
 | 
        
           |  |  | 912 |   | 
        
           |  |  | 913 | 		//we need an object for the recordSet
 | 
        
           |  |  | 914 | 		//because we have to call MetaType.
 | 
        
           |  |  | 915 | 		//php can't do a $rsclass::MetaType()
 | 
        
           |  |  | 916 | 		$rsclass = $zthis->rsPrefix.$zthis->databaseType;
 | 
        
           |  |  | 917 | 		$recordSet = new $rsclass(ADORecordSet::DUMMY_QUERY_ID, $zthis->fetchMode);
 | 
        
           |  |  | 918 | 		$recordSet->connection = $zthis;
 | 
        
           |  |  | 919 |   | 
        
           |  |  | 920 | 		if (is_string($cacheRS) && $cacheRS == $rs) {
 | 
        
           |  |  | 921 | 			$columns = $cacheCols;
 | 
        
           |  |  | 922 | 		} else {
 | 
        
           |  |  | 923 | 			$columns = $zthis->MetaColumns( $tableName );
 | 
        
           |  |  | 924 | 			$cacheRS = $tableName;
 | 
        
           |  |  | 925 | 			$cacheCols = $columns;
 | 
        
           |  |  | 926 | 		}
 | 
        
           |  |  | 927 | 	} else if (is_subclass_of($rs, 'adorecordset')) {
 | 
        
           |  |  | 928 | 		if (isset($rs->insertSig) && is_integer($cacheRS) && $cacheRS == $rs->insertSig) {
 | 
        
           |  |  | 929 | 			$columns = $cacheCols;
 | 
        
           |  |  | 930 | 		} else {
 | 
        
           |  |  | 931 | 			$columns = [];
 | 
        
           |  |  | 932 | 			for ($i=0, $max=$rs->FieldCount(); $i < $max; $i++)
 | 
        
           |  |  | 933 | 				$columns[] = $rs->FetchField($i);
 | 
        
           |  |  | 934 | 			$cacheRS = $cacheSig;
 | 
        
           |  |  | 935 | 			$cacheCols = $columns;
 | 
        
           |  |  | 936 | 			$rs->insertSig = $cacheSig++;
 | 
        
           |  |  | 937 | 		}
 | 
        
           |  |  | 938 | 		$recordSet = $rs;
 | 
        
           |  |  | 939 |   | 
        
           |  |  | 940 | 	} else {
 | 
        
           |  |  | 941 | 		printf(ADODB_BAD_RS,'GetInsertSQL');
 | 
        
           |  |  | 942 | 		return false;
 | 
        
           |  |  | 943 | 	}
 | 
        
           |  |  | 944 |   | 
        
           |  |  | 945 | 	// Loop through all of the fields in the recordset
 | 
        
           |  |  | 946 | 	foreach( $columns as $field ) {
 | 
        
           |  |  | 947 | 		$upperfname = strtoupper($field->name);
 | 
        
           |  |  | 948 | 		if (adodb_key_exists($upperfname, $arrFields, $force)) {
 | 
        
           |  |  | 949 | 			$bad = false;
 | 
        
           |  |  | 950 | 			$fnameq = _adodb_quote_fieldname($zthis, $field->name);
 | 
        
           |  |  | 951 | 			$type = $recordSet->MetaType($field->type);
 | 
        
           |  |  | 952 |   | 
        
           |  |  | 953 | 			/********************************************************/
 | 
        
           |  |  | 954 | 			if (is_null($arrFields[$upperfname])
 | 
        
           |  |  | 955 | 				|| (empty($arrFields[$upperfname]) && strlen($arrFields[$upperfname]) == 0)
 | 
        
           |  |  | 956 | 				|| $arrFields[$upperfname] === $zthis->null2null
 | 
        
           |  |  | 957 | 			) {
 | 
        
           |  |  | 958 | 				switch ($force) {
 | 
        
           |  |  | 959 |   | 
        
           |  |  | 960 | 					case ADODB_FORCE_IGNORE: // we must always set null if missing
 | 
        
           |  |  | 961 | 						$bad = true;
 | 
        
           |  |  | 962 | 						break;
 | 
        
           |  |  | 963 |   | 
        
           |  |  | 964 | 					case ADODB_FORCE_NULL:
 | 
        
           |  |  | 965 | 						$values .= "null, ";
 | 
        
           |  |  | 966 | 						break;
 | 
        
           |  |  | 967 |   | 
        
           |  |  | 968 | 					case ADODB_FORCE_EMPTY:
 | 
        
           |  |  | 969 | 						//Set empty
 | 
        
           |  |  | 970 | 						$arrFields[$upperfname] = "";
 | 
        
           |  |  | 971 | 						$values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq, $arrFields);
 | 
        
           |  |  | 972 | 						break;
 | 
        
           |  |  | 973 |   | 
        
           |  |  | 974 | 					default:
 | 
        
           |  |  | 975 | 					case ADODB_FORCE_VALUE:
 | 
        
           |  |  | 976 | 						//Set the value that was given in array, so you can give both null and empty values
 | 
        
           |  |  | 977 | 						if (is_null($arrFields[$upperfname]) || $arrFields[$upperfname] === $zthis->null2null) {
 | 
        
           |  |  | 978 | 							$values .= "null, ";
 | 
        
           |  |  | 979 | 						} else {
 | 
        
           |  |  | 980 | 							$values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq, $arrFields);
 | 
        
           |  |  | 981 | 						}
 | 
        
           |  |  | 982 | 						break;
 | 
        
           |  |  | 983 |   | 
        
           |  |  | 984 | 					case ADODB_FORCE_NULL_AND_ZERO:
 | 
        
           |  |  | 985 | 						switch ($type) {
 | 
        
           |  |  | 986 | 							case 'N':
 | 
        
           |  |  | 987 | 							case 'I':
 | 
        
           |  |  | 988 | 							case 'L':
 | 
        
           |  |  | 989 | 								$values .= '0, ';
 | 
        
           |  |  | 990 | 								break;
 | 
        
           |  |  | 991 | 							default:
 | 
        
           |  |  | 992 | 								$values .= "null, ";
 | 
        
           |  |  | 993 | 								break;
 | 
        
           |  |  | 994 | 						}
 | 
        
           |  |  | 995 | 						break;
 | 
        
           |  |  | 996 |   | 
        
           |  |  | 997 | 				} // switch
 | 
        
           |  |  | 998 |   | 
        
           |  |  | 999 | 				/*********************************************************/
 | 
        
           |  |  | 1000 | 			} else {
 | 
        
           |  |  | 1001 | 				//we do this so each driver can customize the sql for
 | 
        
           |  |  | 1002 | 				//DB specific column types.
 | 
        
           |  |  | 1003 | 				//Oracle needs BLOB types to be handled with a returning clause
 | 
        
           |  |  | 1004 | 				//postgres has special needs as well
 | 
        
           |  |  | 1005 | 				$values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq, $arrFields);
 | 
        
           |  |  | 1006 | 			}
 | 
        
           |  |  | 1007 |   | 
        
           |  |  | 1008 | 			if ($bad) {
 | 
        
           |  |  | 1009 | 				continue;
 | 
        
           |  |  | 1010 | 			}
 | 
        
           |  |  | 1011 | 			// Set the counter for the number of fields that will be inserted.
 | 
        
           |  |  | 1012 | 			$fieldInsertedCount++;
 | 
        
           |  |  | 1013 |   | 
        
           |  |  | 1014 | 			// Get the name of the fields to insert
 | 
        
           |  |  | 1015 | 			$fields .= $fnameq . ", ";
 | 
        
           |  |  | 1016 | 		}
 | 
        
           |  |  | 1017 | 	}
 | 
        
           |  |  | 1018 |   | 
        
           |  |  | 1019 |   | 
        
           |  |  | 1020 | 	// If there were any inserted fields then build the rest of the insert query.
 | 
        
           |  |  | 1021 | 	if ($fieldInsertedCount <= 0) return false;
 | 
        
           |  |  | 1022 |   | 
        
           |  |  | 1023 | 	// Get the table name from the existing query.
 | 
        
           |  |  | 1024 | 	if (!$tableName) {
 | 
        
           |  |  | 1025 | 		if (!empty($rs->tableName)) $tableName = $rs->tableName;
 | 
        
           |  |  | 1026 | 		else if (preg_match("/FROM\s+".ADODB_TABLE_REGEX."/is", $rs->sql, $tableName))
 | 
        
           |  |  | 1027 | 			$tableName = $tableName[1];
 | 
        
           |  |  | 1028 | 		else
 | 
        
           |  |  | 1029 | 			return false;
 | 
        
           |  |  | 1030 | 	}
 | 
        
           |  |  | 1031 |   | 
        
           |  |  | 1032 | 	// Strip off the comma and space on the end of both the fields
 | 
        
           |  |  | 1033 | 	// and their values.
 | 
        
           |  |  | 1034 | 	$fields = substr($fields, 0, -2);
 | 
        
           |  |  | 1035 | 	$values = substr($values, 0, -2);
 | 
        
           |  |  | 1036 |   | 
        
           |  |  | 1037 | 	// Append the fields and their values to the insert query.
 | 
        
           |  |  | 1038 | 	return 'INSERT INTO '.$tableName.' ( '.$fields.' ) VALUES ( '.$values.' )';
 | 
        
           |  |  | 1039 | }
 | 
        
           |  |  | 1040 |   | 
        
           |  |  | 1041 |   | 
        
           |  |  | 1042 | /**
 | 
        
           |  |  | 1043 |  * This private method is used to help construct
 | 
        
           |  |  | 1044 |  * the update/sql which is generated by GetInsertSQL and GetUpdateSQL.
 | 
        
           |  |  | 1045 |  * It handles the string construction of 1 column -> sql string based on
 | 
        
           |  |  | 1046 |  * the column type.  We want to do 'safe' handling of BLOBs
 | 
        
           |  |  | 1047 |  *
 | 
        
           |  |  | 1048 |  * @param string the type of sql we are trying to create
 | 
        
           |  |  | 1049 |  *                'I' or 'U'.
 | 
        
           |  |  | 1050 |  * @param string column data type from the db::MetaType() method
 | 
        
           |  |  | 1051 |  * @param string the column name
 | 
        
           |  |  | 1052 |  * @param array the column value
 | 
        
           |  |  | 1053 |  *
 | 
        
           |  |  | 1054 |  * @return string
 | 
        
           |  |  | 1055 |  *
 | 
        
           |  |  | 1056 |  */
 | 
        
           |  |  | 1057 | function _adodb_column_sql_oci8(&$zthis,$action, $type, $fname, $fnameq, $arrFields)
 | 
        
           |  |  | 1058 | {
 | 
        
           |  |  | 1059 | 	// Based on the datatype of the field
 | 
        
           |  |  | 1060 | 	// Format the value properly for the database
 | 
        
           |  |  | 1061 | 	switch ($type) {
 | 
        
           |  |  | 1062 | 		case 'B':
 | 
        
           |  |  | 1063 | 			//in order to handle Blobs correctly, we need
 | 
        
           |  |  | 1064 | 			//to do some magic for Oracle
 | 
        
           |  |  | 1065 |   | 
        
           |  |  | 1066 | 			//we need to create a new descriptor to handle
 | 
        
           |  |  | 1067 | 			//this properly
 | 
        
           |  |  | 1068 | 			if (!empty($zthis->hasReturningInto)) {
 | 
        
           |  |  | 1069 | 				if ($action == 'I') {
 | 
        
           |  |  | 1070 | 					$sql = 'empty_blob(), ';
 | 
        
           |  |  | 1071 | 				} else {
 | 
        
           |  |  | 1072 | 					$sql = $fnameq . '=empty_blob(), ';
 | 
        
           |  |  | 1073 | 				}
 | 
        
           |  |  | 1074 | 				//add the variable to the returning clause array
 | 
        
           |  |  | 1075 | 				//so the user can build this later in
 | 
        
           |  |  | 1076 | 				//case they want to add more to it
 | 
        
           |  |  | 1077 | 				$zthis->_returningArray[$fname] = ':xx' . $fname . 'xx';
 | 
        
           |  |  | 1078 | 			} else {
 | 
        
           |  |  | 1079 | 				if (empty($arrFields[$fname])) {
 | 
        
           |  |  | 1080 | 					if ($action == 'I') {
 | 
        
           |  |  | 1081 | 						$sql = 'empty_blob(), ';
 | 
        
           |  |  | 1082 | 					} else {
 | 
        
           |  |  | 1083 | 						$sql = $fnameq . '=empty_blob(), ';
 | 
        
           |  |  | 1084 | 					}
 | 
        
           |  |  | 1085 | 				} else {
 | 
        
           |  |  | 1086 | 					//this is to maintain compatibility
 | 
        
           |  |  | 1087 | 					//with older adodb versions.
 | 
        
           |  |  | 1088 | 					$sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, false);
 | 
        
           |  |  | 1089 | 				}
 | 
        
           |  |  | 1090 | 			}
 | 
        
           |  |  | 1091 | 			break;
 | 
        
           |  |  | 1092 |   | 
        
           |  |  | 1093 | 		case "X":
 | 
        
           |  |  | 1094 | 			//we need to do some more magic here for long variables
 | 
        
           |  |  | 1095 | 			//to handle these correctly in oracle.
 | 
        
           |  |  | 1096 |   | 
        
           |  |  | 1097 | 			//create a safe bind var name
 | 
        
           |  |  | 1098 | 			//to avoid conflicts w/ dupes.
 | 
        
           |  |  | 1099 | 			if (!empty($zthis->hasReturningInto)) {
 | 
        
           |  |  | 1100 | 				if ($action == 'I') {
 | 
        
           |  |  | 1101 | 					$sql = ':xx' . $fname . 'xx, ';
 | 
        
           |  |  | 1102 | 				} else {
 | 
        
           |  |  | 1103 | 					$sql = $fnameq . '=:xx' . $fname . 'xx, ';
 | 
        
           |  |  | 1104 | 				}
 | 
        
           |  |  | 1105 | 				//add the variable to the returning clause array
 | 
        
           |  |  | 1106 | 				//so the user can build this later in
 | 
        
           |  |  | 1107 | 				//case they want to add more to it
 | 
        
           |  |  | 1108 | 				$zthis->_returningArray[$fname] = ':xx' . $fname . 'xx';
 | 
        
           |  |  | 1109 | 			} else {
 | 
        
           |  |  | 1110 | 				//this is to maintain compatibility
 | 
        
           |  |  | 1111 | 				//with older adodb versions.
 | 
        
           |  |  | 1112 | 				$sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, false);
 | 
        
           |  |  | 1113 | 			}
 | 
        
           |  |  | 1114 | 			break;
 | 
        
           |  |  | 1115 |   | 
        
           |  |  | 1116 | 		default:
 | 
        
           |  |  | 1117 | 			$sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, false);
 | 
        
           |  |  | 1118 | 			break;
 | 
        
           |  |  | 1119 | 	}
 | 
        
           |  |  | 1120 |   | 
        
           |  |  | 1121 | 	return $sql;
 | 
        
           |  |  | 1122 | }
 | 
        
           |  |  | 1123 |   | 
        
           |  |  | 1124 | function _adodb_column_sql(&$zthis, $action, $type, $fname, $fnameq, $arrFields, $recurse=true)
 | 
        
           |  |  | 1125 | {
 | 
        
           |  |  | 1126 |   | 
        
           |  |  | 1127 | 	if ($recurse) {
 | 
        
           |  |  | 1128 | 		switch($zthis->dataProvider) {
 | 
        
           |  |  | 1129 | 		case 'postgres':
 | 
        
           |  |  | 1130 | 			if ($type == 'L') $type = 'C';
 | 
        
           |  |  | 1131 | 			break;
 | 
        
           |  |  | 1132 | 		case 'oci8':
 | 
        
           |  |  | 1133 | 			return _adodb_column_sql_oci8($zthis, $action, $type, $fname, $fnameq, $arrFields);
 | 
        
           |  |  | 1134 |   | 
        
           |  |  | 1135 | 		}
 | 
        
           |  |  | 1136 | 	}
 | 
        
           |  |  | 1137 |   | 
        
           |  |  | 1138 | 	switch($type) {
 | 
        
           |  |  | 1139 | 		case "C":
 | 
        
           |  |  | 1140 | 		case "X":
 | 
        
           |  |  | 1141 | 		case 'B':
 | 
        
           |  |  | 1142 | 			$val = $zthis->qstr($arrFields[$fname]);
 | 
        
           |  |  | 1143 | 			break;
 | 
        
           |  |  | 1144 |   | 
        
           |  |  | 1145 | 		case "D":
 | 
        
           |  |  | 1146 | 			$val = $zthis->DBDate($arrFields[$fname]);
 | 
        
           |  |  | 1147 | 			break;
 | 
        
           |  |  | 1148 |   | 
        
           |  |  | 1149 | 		case "T":
 | 
        
           |  |  | 1150 | 			$val = $zthis->DBTimeStamp($arrFields[$fname]);
 | 
        
           |  |  | 1151 | 			break;
 | 
        
           |  |  | 1152 |   | 
        
           |  |  | 1153 | 		case "N":
 | 
        
           |  |  | 1154 | 			$val = $arrFields[$fname];
 | 
        
           |  |  | 1155 | 			if (!is_numeric($val)) $val = str_replace(',', '.', (float)$val);
 | 
        
           |  |  | 1156 | 			break;
 | 
        
           |  |  | 1157 |   | 
        
           |  |  | 1158 | 		case "I":
 | 
        
           |  |  | 1159 | 		case "R":
 | 
        
           |  |  | 1160 | 			$val = $arrFields[$fname];
 | 
        
           |  |  | 1161 | 			if (!is_numeric($val)) $val = (integer) $val;
 | 
        
           |  |  | 1162 | 			break;
 | 
        
           |  |  | 1163 |   | 
        
           |  |  | 1164 | 		default:
 | 
        
           |  |  | 1165 | 			$val = str_replace(array("'"," ","("),"",$arrFields[$fname]); // basic sql injection defence
 | 
        
           |  |  | 1166 | 			if (empty($val)) $val = '0';
 | 
        
           |  |  | 1167 | 			break;
 | 
        
           |  |  | 1168 | 	}
 | 
        
           |  |  | 1169 |   | 
        
           |  |  | 1170 | 	if ($action == 'I') return $val . ", ";
 | 
        
           |  |  | 1171 |   | 
        
           |  |  | 1172 | 	return $fnameq . "=" . $val . ", ";
 | 
        
           |  |  | 1173 | }
 | 
        
           |  |  | 1174 |   | 
        
           |  |  | 1175 |   | 
        
           |  |  | 1176 | /**
 | 
        
           |  |  | 1177 | * Replaces standard _execute when debug mode is enabled
 | 
        
           |  |  | 1178 | *
 | 
        
           |  |  | 1179 | * @param ADOConnection   $zthis    An ADOConnection object
 | 
        
           |  |  | 1180 | * @param string|string[] $sql      A string or array of SQL statements
 | 
        
           |  |  | 1181 | * @param string[]|null   $inputarr An optional array of bind parameters
 | 
        
           |  |  | 1182 | *
 | 
        
           |  |  | 1183 | * @return  handle|void A handle to the executed query
 | 
        
           |  |  | 1184 | */
 | 
        
           |  |  | 1185 | function _adodb_debug_execute($zthis, $sql, $inputarr)
 | 
        
           |  |  | 1186 | {
 | 
        
           |  |  | 1187 | 	// Unpack the bind parameters
 | 
        
           |  |  | 1188 | 	$ss = '';
 | 
        
           |  |  | 1189 | 	if ($inputarr) {
 | 
        
           |  |  | 1190 | 		foreach ($inputarr as $kk => $vv) {
 | 
        
           |  |  | 1191 | 			if (is_string($vv) && strlen($vv) > 64) {
 | 
        
           |  |  | 1192 | 				$vv = substr($vv, 0, 64) . '...';
 | 
        
           |  |  | 1193 | 			}
 | 
        
           |  |  | 1194 | 			if (is_null($vv)) {
 | 
        
           |  |  | 1195 | 				$ss .= "($kk=>null) ";
 | 
        
           |  |  | 1196 | 			} else {
 | 
        
           |  |  | 1197 | 				if (is_array($vv)) {
 | 
        
           |  |  | 1198 | 					$vv = sprintf("Array Of Values: [%s]", implode(',', $vv));
 | 
        
           |  |  | 1199 | 				}
 | 
        
           |  |  | 1200 | 				$ss .= "($kk=>'$vv') ";
 | 
        
           |  |  | 1201 | 			}
 | 
        
           |  |  | 1202 | 		}
 | 
        
           |  |  | 1203 | 		$ss = "[ $ss ]";
 | 
        
           |  |  | 1204 | 	}
 | 
        
           |  |  | 1205 |   | 
        
           |  |  | 1206 | 	$sqlTxt = is_array($sql) ? $sql[0] : $sql;
 | 
        
           |  |  | 1207 |   | 
        
           |  |  | 1208 | 	// Remove newlines and tabs, compress repeating spaces
 | 
        
           |  |  | 1209 | 	$sqlTxt = preg_replace('/\s+/', ' ', $sqlTxt);
 | 
        
           |  |  | 1210 |   | 
        
           |  |  | 1211 | 	// check if running from browser or command-line
 | 
        
           |  |  | 1212 | 	$inBrowser = isset($_SERVER['HTTP_USER_AGENT']);
 | 
        
           |  |  | 1213 |   | 
        
           |  |  | 1214 | 	$myDatabaseType = $zthis->databaseType;
 | 
        
           |  |  | 1215 | 	if (!isset($zthis->dsnType)) {
 | 
        
           |  |  | 1216 | 		// Append the PDO driver name
 | 
        
           |  |  | 1217 | 		$myDatabaseType .= '-' . $zthis->dsnType;
 | 
        
           |  |  | 1218 | 	}
 | 
        
           |  |  | 1219 |   | 
        
           |  |  | 1220 | 	if ($inBrowser) {
 | 
        
           |  |  | 1221 | 		if ($ss) {
 | 
        
           |  |  | 1222 | 			// Default formatting for passed parameter
 | 
        
           |  |  | 1223 | 			$ss = sprintf('<code class="adodb-debug">%s</code>', htmlspecialchars($ss));
 | 
        
           |  |  | 1224 | 		}
 | 
        
           |  |  | 1225 | 		if ($zthis->debug === -1) {
 | 
        
           |  |  | 1226 | 			$outString = "<br class='adodb-debug'>(%s):  %s   %s<br class='adodb-debug'>";
 | 
        
           |  |  | 1227 | 			ADOConnection::outp(sprintf($outString, $myDatabaseType, htmlspecialchars($sqlTxt), $ss), false);
 | 
        
           |  |  | 1228 | 		} elseif ($zthis->debug !== -99) {
 | 
        
           |  |  | 1229 | 			$outString = "<hr class='adodb-debug'>(%s):  %s   %s<hr class='adodb-debug'>";
 | 
        
           |  |  | 1230 | 			ADOConnection::outp(sprintf($outString, $myDatabaseType, htmlspecialchars($sqlTxt), $ss), false);
 | 
        
           |  |  | 1231 | 		}
 | 
        
           |  |  | 1232 | 	} else {
 | 
        
           |  |  | 1233 | 		// CLI output
 | 
        
           |  |  | 1234 | 		if ($zthis->debug !== -99) {
 | 
        
           |  |  | 1235 | 			$outString = sprintf("%s\n%s\n    %s %s \n%s\n", str_repeat('-', 78), $myDatabaseType, $sqlTxt, $ss, str_repeat('-', 78));
 | 
        
           |  |  | 1236 | 			ADOConnection::outp($outString, false);
 | 
        
           |  |  | 1237 | 		}
 | 
        
           |  |  | 1238 | 	}
 | 
        
           |  |  | 1239 |   | 
        
           |  |  | 1240 | 	// Now execute the query
 | 
        
           |  |  | 1241 | 	$qID = $zthis->_query($sql, $inputarr);
 | 
        
           |  |  | 1242 |   | 
        
           |  |  | 1243 | 	// Alexios Fakios notes that ErrorMsg() must be called before ErrorNo() for mssql
 | 
        
           |  |  | 1244 | 	// because ErrorNo() calls Execute('SELECT @ERROR'), causing recursion
 | 
        
           |  |  | 1245 | 	if ($zthis->databaseType == 'mssql') {
 | 
        
           |  |  | 1246 | 		// ErrorNo is a slow function call in mssql
 | 
        
           |  |  | 1247 | 		if ($emsg = $zthis->ErrorMsg()) {
 | 
        
           |  |  | 1248 | 			if ($err = $zthis->ErrorNo()) {
 | 
        
           |  |  | 1249 | 				if ($zthis->debug === -99) {
 | 
        
           |  |  | 1250 | 					ADOConnection::outp("<hr>\n($myDatabaseType): " . htmlspecialchars($sqlTxt) . "   $ss\n<hr>\n", false);
 | 
        
           |  |  | 1251 | 				}
 | 
        
           |  |  | 1252 |   | 
        
           |  |  | 1253 | 				ADOConnection::outp($err . ': ' . $emsg);
 | 
        
           |  |  | 1254 | 			}
 | 
        
           |  |  | 1255 | 		}
 | 
        
           |  |  | 1256 | 	} else {
 | 
        
           |  |  | 1257 | 		if (!$qID) {
 | 
        
           |  |  | 1258 | 			// Statement execution has failed
 | 
        
           |  |  | 1259 | 			if ($zthis->debug === -99) {
 | 
        
           |  |  | 1260 | 				if ($inBrowser) {
 | 
        
           |  |  | 1261 | 					$outString = "<hr class='adodb-debug'>(%s):  %s   %s<hr class='adodb-debug'>";
 | 
        
           |  |  | 1262 | 					ADOConnection::outp(sprintf($outString, $myDatabaseType, htmlspecialchars($sqlTxt), $ss), false);
 | 
        
           |  |  | 1263 | 				} else {
 | 
        
           |  |  | 1264 | 					$outString = sprintf("%s\n%s\n    %s %s \n%s\n",str_repeat('-',78),$myDatabaseType,$sqlTxt,$ss,str_repeat('-',78));
 | 
        
           |  |  | 1265 | 					ADOConnection::outp($outString, false);
 | 
        
           |  |  | 1266 | 				}
 | 
        
           |  |  | 1267 | 			}
 | 
        
           |  |  | 1268 |   | 
        
           |  |  | 1269 | 			// Send last error to output
 | 
        
           |  |  | 1270 | 			$errno = $zthis->ErrorNo();
 | 
        
           |  |  | 1271 | 			if ($errno) {
 | 
        
           |  |  | 1272 | 				ADOConnection::outp($errno . ': ' . $zthis->ErrorMsg());
 | 
        
           |  |  | 1273 | 			}
 | 
        
           |  |  | 1274 | 		}
 | 
        
           |  |  | 1275 | 	}
 | 
        
           |  |  | 1276 |   | 
        
           |  |  | 1277 | 	if ($qID === false || $zthis->debug === 99) {
 | 
        
           |  |  | 1278 | 		_adodb_backtrace();
 | 
        
           |  |  | 1279 | 	}
 | 
        
           |  |  | 1280 | 	return $qID;
 | 
        
           |  |  | 1281 | }
 | 
        
           |  |  | 1282 |   | 
        
           |  |  | 1283 | /**
 | 
        
           |  |  | 1284 |  * Pretty print the debug_backtrace function
 | 
        
           |  |  | 1285 |  *
 | 
        
           |  |  | 1286 |  * @param string[]|bool $printOrArr       Whether to print the result directly or return the result
 | 
        
           |  |  | 1287 |  * @param int           $maximumDepth     The maximum depth of the array to traverse
 | 
        
           |  |  | 1288 |  * @param int           $elementsToIgnore The backtrace array indexes to ignore
 | 
        
           |  |  | 1289 |  * @param null|bool     $ishtml           True if we are in a CGI environment, false for CLI,
 | 
        
           |  |  | 1290 |  *                                        null to auto detect
 | 
        
           |  |  | 1291 |  *
 | 
        
           |  |  | 1292 |  * @return string Formatted backtrace
 | 
        
           |  |  | 1293 |  */
 | 
        
           |  |  | 1294 | function _adodb_backtrace($printOrArr=true, $maximumDepth=9999, $elementsToIgnore=0, $ishtml=null)
 | 
        
           |  |  | 1295 | {
 | 
        
           |  |  | 1296 | 	if (!function_exists('debug_backtrace')) {
 | 
        
           |  |  | 1297 | 		return '';
 | 
        
           |  |  | 1298 | 	}
 | 
        
           |  |  | 1299 |   | 
        
           |  |  | 1300 | 	if ($ishtml === null) {
 | 
        
           |  |  | 1301 | 		// Auto determine if we in a CGI enviroment
 | 
        
           |  |  | 1302 | 		$html = (isset($_SERVER['HTTP_USER_AGENT']));
 | 
        
           |  |  | 1303 | 	} else {
 | 
        
           |  |  | 1304 | 		$html = $ishtml;
 | 
        
           |  |  | 1305 | 	}
 | 
        
           |  |  | 1306 |   | 
        
           |  |  | 1307 | 	$cgiString = "</font><font color=#808080 size=-1> %% line %4d, file: <a href=\"file:/%s\">%s</a></font>";
 | 
        
           |  |  | 1308 | 	$cliString = "%% line %4d, file: %s";
 | 
        
           |  |  | 1309 | 	$fmt = ($html) ? $cgiString : $cliString;
 | 
        
           |  |  | 1310 |   | 
        
           |  |  | 1311 | 	$MAXSTRLEN = 128;
 | 
        
           |  |  | 1312 |   | 
        
           |  |  | 1313 | 	$s = ($html) ? '<pre align=left>' : '';
 | 
        
           |  |  | 1314 |   | 
        
           |  |  | 1315 | 	if (is_array($printOrArr)) {
 | 
        
           |  |  | 1316 | 		$traceArr = $printOrArr;
 | 
        
           |  |  | 1317 | 	} else {
 | 
        
           |  |  | 1318 | 		$traceArr = debug_backtrace();
 | 
        
           |  |  | 1319 | 	}
 | 
        
           |  |  | 1320 |   | 
        
           |  |  | 1321 | 	// Remove first 2 elements that just show calls to adodb_backtrace
 | 
        
           |  |  | 1322 | 	array_shift($traceArr);
 | 
        
           |  |  | 1323 | 	array_shift($traceArr);
 | 
        
           |  |  | 1324 |   | 
        
           |  |  | 1325 | 	// We want last element to have no indent
 | 
        
           |  |  | 1326 | 	$tabs = sizeof($traceArr) - 1;
 | 
        
           |  |  | 1327 |   | 
        
           |  |  | 1328 | 	foreach ($traceArr as $arr) {
 | 
        
           |  |  | 1329 | 		if ($elementsToIgnore) {
 | 
        
           |  |  | 1330 | 			// Ignore array element at start of array
 | 
        
           |  |  | 1331 | 			$elementsToIgnore--;
 | 
        
           |  |  | 1332 | 			$tabs--;
 | 
        
           |  |  | 1333 | 			continue;
 | 
        
           |  |  | 1334 | 		}
 | 
        
           |  |  | 1335 | 		$maximumDepth--;
 | 
        
           |  |  | 1336 | 		if ($maximumDepth < 0) {
 | 
        
           |  |  | 1337 | 			break;
 | 
        
           |  |  | 1338 | 		}
 | 
        
           |  |  | 1339 |   | 
        
           |  |  | 1340 | 		$args = array();
 | 
        
           |  |  | 1341 |   | 
        
           |  |  | 1342 | 		if ($tabs) {
 | 
        
           |  |  | 1343 | 			$s .= str_repeat($html ? '   ' : "\t", $tabs);
 | 
        
           |  |  | 1344 | 			$tabs--;
 | 
        
           |  |  | 1345 | 		}
 | 
        
           |  |  | 1346 | 		if ($html) {
 | 
        
           |  |  | 1347 | 			$s .= '<font face="Courier New,Courier">';
 | 
        
           |  |  | 1348 | 		}
 | 
        
           |  |  | 1349 |   | 
        
           |  |  | 1350 | 		if (isset($arr['class'])) {
 | 
        
           |  |  | 1351 | 			$s .= $arr['class'] . '.';
 | 
        
           |  |  | 1352 | 		}
 | 
        
           |  |  | 1353 |   | 
        
           |  |  | 1354 | 		if (isset($arr['args'])) {
 | 
        
           |  |  | 1355 | 			foreach ($arr['args'] as $v) {
 | 
        
           |  |  | 1356 | 				if (is_null($v)) {
 | 
        
           |  |  | 1357 | 					$args[] = 'null';
 | 
        
           |  |  | 1358 | 				} elseif (is_array($v)) {
 | 
        
           |  |  | 1359 | 					$args[] = 'Array[' . sizeof($v) . ']';
 | 
        
           |  |  | 1360 | 				} elseif (is_object($v)) {
 | 
        
           |  |  | 1361 | 					$args[] = 'Object:' . get_class($v);
 | 
        
           |  |  | 1362 | 				} elseif (is_bool($v)) {
 | 
        
           |  |  | 1363 | 					$args[] = $v ? 'true' : 'false';
 | 
        
           |  |  | 1364 | 				} else {
 | 
        
           |  |  | 1365 | 					$v = (string)@$v;
 | 
        
           |  |  | 1366 | 					// Truncate
 | 
        
           |  |  | 1367 | 					$v = substr($v, 0, $MAXSTRLEN);
 | 
        
           |  |  | 1368 | 					// Remove newlines and tabs, compress repeating spaces
 | 
        
           |  |  | 1369 | 					$v = preg_replace('/\s+/', ' ', $v);
 | 
        
           |  |  | 1370 | 					// Convert htmlchars (not sure why we do this in CLI)
 | 
        
           |  |  | 1371 | 					$str = htmlspecialchars($v);
 | 
        
           |  |  | 1372 |   | 
        
           |  |  | 1373 | 					if (strlen($v) > $MAXSTRLEN) {
 | 
        
           |  |  | 1374 | 						$str .= '...';
 | 
        
           |  |  | 1375 | 					}
 | 
        
           |  |  | 1376 |   | 
        
           |  |  | 1377 | 					$args[] = $str;
 | 
        
           |  |  | 1378 | 				}
 | 
        
           |  |  | 1379 | 			}
 | 
        
           |  |  | 1380 | 		}
 | 
        
           |  |  | 1381 | 		$s .= $arr['function'] . '(' . implode(', ', $args) . ')';
 | 
        
           |  |  | 1382 | 		$s .= @sprintf($fmt, $arr['line'], $arr['file'], basename($arr['file']));
 | 
        
           |  |  | 1383 | 		$s .= "\n";
 | 
        
           |  |  | 1384 | 	}
 | 
        
           |  |  | 1385 | 	if ($html) {
 | 
        
           |  |  | 1386 | 		$s .= '</pre>';
 | 
        
           |  |  | 1387 | 	}
 | 
        
           |  |  | 1388 | 	if ($printOrArr) {
 | 
        
           | 1441 | ariadna | 1389 | 		ADOConnection::outp($s);
 | 
        
           | 1 | efrain | 1390 | 	}
 | 
        
           |  |  | 1391 |   | 
        
           |  |  | 1392 | 	return $s;
 | 
        
           |  |  | 1393 | }
 |