Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/lib/adodb/adodb-lib.inc.php
Go to the documentation of this file.
00001 <?php
00002 // security - hide paths
00003 if (!defined('ADODB_DIR')) die();
00004 
00005 global $ADODB_INCLUDED_LIB;
00006 $ADODB_INCLUDED_LIB = 1;
00007 
00008 /* 
00009   @version V5.14 8 Sept 2011  (c) 2000-2011 John Lim (jlim#natsoft.com). All rights reserved.
00010   Released under both BSD license and Lesser GPL library license. 
00011   Whenever there is any discrepancy between the two licenses, 
00012   the BSD license will take precedence. See License.txt. 
00013   Set tabs to 4 for best viewing.
00014   
00015   Less commonly used functions are placed here to reduce size of adodb.inc.php. 
00016 */ 
00017 
00018 function adodb_strip_order_by($sql)
00019 {
00020         $rez = preg_match('/(\sORDER\s+BY\s[^)]*)/is',$sql,$arr);
00021         if ($arr)
00022                 if (strpos($arr[0],'(') !== false) {
00023                         $at = strpos($sql,$arr[0]);
00024                         $cntin = 0;
00025                         for ($i=$at, $max=strlen($sql); $i < $max; $i++) {
00026                                 $ch = $sql[$i];
00027                                 if ($ch == '(') {
00028                                         $cntin += 1;
00029                                 } elseif($ch == ')') {
00030                                         $cntin -= 1;
00031                                         if ($cntin < 0) {
00032                                                 break;
00033                                         }
00034                                 }
00035                         }
00036                         $sql = substr($sql,0,$at).substr($sql,$i);
00037                 } else
00038                         $sql = str_replace($arr[0], '', $sql); 
00039         return $sql;
00040  }
00041 
00042 if (false) {
00043         $sql = 'select * from (select a from b order by a(b),b(c) desc)';
00044         $sql = '(select * from abc order by 1)';
00045         die(adodb_strip_order_by($sql));
00046 }
00047 
00048 function adodb_probetypes(&$array,&$types,$probe=8)
00049 {
00050 // probe and guess the type
00051         $types = array();
00052         if ($probe > sizeof($array)) $max = sizeof($array);
00053         else $max = $probe;
00054         
00055         
00056         for ($j=0;$j < $max; $j++) {
00057                 $row = $array[$j];
00058                 if (!$row) break;
00059                 $i = -1;
00060                 foreach($row as $v) {
00061                         $i += 1;
00062 
00063                         if (isset($types[$i]) && $types[$i]=='C') continue;
00064                         
00065                         //print " ($i ".$types[$i]. "$v) ";
00066                         $v = trim($v);
00067                         
00068                         if (!preg_match('/^[+-]{0,1}[0-9\.]+$/',$v)) {
00069                                 $types[$i] = 'C'; // once C, always C
00070                                 
00071                                 continue;
00072                         }
00073                         if ($j == 0) { 
00074                         // If empty string, we presume is character
00075                         // test for integer for 1st row only
00076                         // after that it is up to testing other rows to prove
00077                         // that it is not an integer
00078                                 if (strlen($v) == 0) $types[$i] = 'C';
00079                                 if (strpos($v,'.') !== false) $types[$i] = 'N';
00080                                 else  $types[$i] = 'I';
00081                                 continue;
00082                         }
00083                         
00084                         if (strpos($v,'.') !== false) $types[$i] = 'N';
00085                         
00086                 }
00087         }
00088         
00089 }
00090 
00091 function  adodb_transpose(&$arr, &$newarr, &$hdr, &$fobjs)
00092 {
00093         $oldX = sizeof(reset($arr));
00094         $oldY = sizeof($arr);   
00095         
00096         if ($hdr) {
00097                 $startx = 1;
00098                 $hdr = array('Fields');
00099                 for ($y = 0; $y < $oldY; $y++) {
00100                         $hdr[] = $arr[$y][0];
00101                 }
00102         } else
00103                 $startx = 0;
00104 
00105         for ($x = $startx; $x < $oldX; $x++) {
00106                 if ($fobjs) {
00107                         $o = $fobjs[$x];
00108                         $newarr[] = array($o->name);
00109                 } else
00110                         $newarr[] = array();
00111                         
00112                 for ($y = 0; $y < $oldY; $y++) {
00113                         $newarr[$x-$startx][] = $arr[$y][$x];
00114                 }
00115         }
00116 }
00117 
00118 // Force key to upper. 
00119 // See also http://www.php.net/manual/en/function.array-change-key-case.php
00120 function _array_change_key_case($an_array)
00121 {
00122         if (is_array($an_array)) {
00123                 $new_array = array();
00124                 foreach($an_array as $key=>$value)
00125                         $new_array[strtoupper($key)] = $value;
00126 
00127                 return $new_array;
00128    }
00129 
00130         return $an_array;
00131 }
00132 
00133 function _adodb_replace(&$zthis, $table, $fieldArray, $keyCol, $autoQuote, $has_autoinc)
00134 {
00135                 if (count($fieldArray) == 0) return 0;
00136                 $first = true;
00137                 $uSet = '';
00138                 
00139                 if (!is_array($keyCol)) {
00140                         $keyCol = array($keyCol);
00141                 }
00142                 foreach($fieldArray as $k => $v) {
00143                         if ($v === null) {
00144                                 $v = 'NULL';
00145                                 $fieldArray[$k] = $v;
00146                         } else if ($autoQuote &&  strcasecmp($v,$zthis->null2null)!=0) {
00147                                 $v = $zthis->qstr($v);
00148                                 $fieldArray[$k] = $v;
00149                         }
00150                         if (in_array($k,$keyCol)) continue; // skip UPDATE if is key
00151                         
00152                         if ($first) {
00153                                 $first = false;                 
00154                                 $uSet = "$k=$v";
00155                         } else
00156                                 $uSet .= ",$k=$v";
00157                 }
00158                 
00159                 $where = false;
00160                 foreach ($keyCol as $v) {
00161                         if (isset($fieldArray[$v])) {
00162                                 if ($where) $where .= ' and '.$v.'='.$fieldArray[$v];
00163                                 else $where = $v.'='.$fieldArray[$v];
00164                         }
00165                 }
00166                 
00167                 if ($uSet && $where) {
00168                         $update = "UPDATE $table SET $uSet WHERE $where";
00169 
00170                         $rs = $zthis->Execute($update);
00171                         
00172                         
00173                         if ($rs) {
00174                                 if ($zthis->poorAffectedRows) {
00175                                 /*
00176                                  The Select count(*) wipes out any errors that the update would have returned. 
00177                                 http://phplens.com/lens/lensforum/msgs.php?id=5696
00178                                 */
00179                                         if ($zthis->ErrorNo()<>0) return 0;
00180                                         
00181                                 # affected_rows == 0 if update field values identical to old values
00182                                 # for mysql - which is silly. 
00183                         
00184                                         $cnt = $zthis->GetOne("select count(*) from $table where $where");
00185                                         if ($cnt > 0) return 1; // record already exists
00186                                 } else {
00187                                         if (($zthis->Affected_Rows()>0)) return 1;
00188                                 }
00189                         } else
00190                                 return 0;
00191                 }
00192                 
00193         //      print "<p>Error=".$this->ErrorNo().'<p>';
00194                 $first = true;
00195                 foreach($fieldArray as $k => $v) {
00196                         if ($has_autoinc && in_array($k,$keyCol)) continue; // skip autoinc col
00197                         
00198                         if ($first) {
00199                                 $first = false;                 
00200                                 $iCols = "$k";
00201                                 $iVals = "$v";
00202                         } else {
00203                                 $iCols .= ",$k";
00204                                 $iVals .= ",$v";
00205                         }                               
00206                 }
00207                 $insert = "INSERT INTO $table ($iCols) VALUES ($iVals)"; 
00208                 $rs = $zthis->Execute($insert);
00209                 return ($rs) ? 2 : 0;
00210 }
00211 
00212 // Requires $ADODB_FETCH_MODE = ADODB_FETCH_NUM
00213 function _adodb_getmenu(&$zthis, $name,$defstr='',$blank1stItem=true,$multiple=false,
00214                         $size=0, $selectAttr='',$compareFields0=true)
00215 {
00216         $hasvalue = false;
00217 
00218         if ($multiple or is_array($defstr)) {
00219                 if ($size==0) $size=5;
00220                 $attr = ' multiple size="'.$size.'"';
00221                 if (!strpos($name,'[]')) $name .= '[]';
00222         } else if ($size) $attr = ' size="'.$size.'"';
00223         else $attr ='';
00224         
00225         $s = '<select name="'.$name.'"'.$attr.' '.$selectAttr.'>';
00226         if ($blank1stItem) 
00227                 if (is_string($blank1stItem))  {
00228                         $barr = explode(':',$blank1stItem);
00229                         if (sizeof($barr) == 1) $barr[] = '';
00230                         $s .= "\n<option value=\"".$barr[0]."\">".$barr[1]."</option>";
00231                 } else $s .= "\n<option></option>";
00232 
00233         if ($zthis->FieldCount() > 1) $hasvalue=true;
00234         else $compareFields0 = true;
00235         
00236         $value = '';
00237     $optgroup = null;
00238     $firstgroup = true;
00239     $fieldsize = $zthis->FieldCount();
00240         while(!$zthis->EOF) {
00241                 $zval = rtrim(reset($zthis->fields));
00242 
00243                 if ($blank1stItem && $zval=="") {
00244                         $zthis->MoveNext();
00245                         continue;
00246                 }
00247 
00248         if ($fieldsize > 1) {
00249                         if (isset($zthis->fields[1]))
00250                                 $zval2 = rtrim($zthis->fields[1]);
00251                         else
00252                                 $zval2 = rtrim(next($zthis->fields));
00253                 }
00254                 $selected = ($compareFields0) ? $zval : $zval2;
00255                 
00256         $group = '';
00257                 if ($fieldsize > 2) {
00258             $group = rtrim($zthis->fields[2]);
00259         }
00260 /* 
00261         if ($optgroup != $group) {
00262             $optgroup = $group;
00263             if ($firstgroup) {
00264                 $firstgroup = false;
00265                 $s .="\n<optgroup label='". htmlspecialchars($group) ."'>";
00266             } else {
00267                 $s .="\n</optgroup>";
00268                 $s .="\n<optgroup label='". htmlspecialchars($group) ."'>";
00269             }
00270                 }
00271 */
00272                 if ($hasvalue) 
00273                         $value = " value='".htmlspecialchars($zval2)."'";
00274                 
00275                 if (is_array($defstr))  {
00276                         
00277                         if (in_array($selected,$defstr)) 
00278                                 $s .= "\n<option selected='selected'$value>".htmlspecialchars($zval).'</option>';
00279                         else 
00280                                 $s .= "\n<option".$value.'>'.htmlspecialchars($zval).'</option>';
00281                 }
00282                 else {
00283                         if (strcasecmp($selected,$defstr)==0) 
00284                                 $s .= "\n<option selected='selected'$value>".htmlspecialchars($zval).'</option>';
00285                         else
00286                                 $s .= "\n<option".$value.'>'.htmlspecialchars($zval).'</option>';
00287                 }
00288                 $zthis->MoveNext();
00289         } // while
00290         
00291     // closing last optgroup
00292     if($optgroup != null) {
00293         $s .= "\n</optgroup>";
00294         }
00295         return $s ."\n</select>\n";
00296 }
00297 
00298 // Requires $ADODB_FETCH_MODE = ADODB_FETCH_NUM
00299 function _adodb_getmenu_gp(&$zthis, $name,$defstr='',$blank1stItem=true,$multiple=false,
00300                         $size=0, $selectAttr='',$compareFields0=true)
00301 {
00302         $hasvalue = false;
00303 
00304         if ($multiple or is_array($defstr)) {
00305                 if ($size==0) $size=5;
00306                 $attr = ' multiple size="'.$size.'"';
00307                 if (!strpos($name,'[]')) $name .= '[]';
00308         } else if ($size) $attr = ' size="'.$size.'"';
00309         else $attr ='';
00310         
00311         $s = '<select name="'.$name.'"'.$attr.' '.$selectAttr.'>';
00312         if ($blank1stItem) 
00313                 if (is_string($blank1stItem))  {
00314                         $barr = explode(':',$blank1stItem);
00315                         if (sizeof($barr) == 1) $barr[] = '';
00316                         $s .= "\n<option value=\"".$barr[0]."\">".$barr[1]."</option>";
00317                 } else $s .= "\n<option></option>";
00318 
00319         if ($zthis->FieldCount() > 1) $hasvalue=true;
00320         else $compareFields0 = true;
00321         
00322         $value = '';
00323     $optgroup = null;
00324     $firstgroup = true;
00325     $fieldsize = sizeof($zthis->fields);
00326         while(!$zthis->EOF) {
00327                 $zval = rtrim(reset($zthis->fields));
00328 
00329                 if ($blank1stItem && $zval=="") {
00330                         $zthis->MoveNext();
00331                         continue;
00332                 }
00333 
00334         if ($fieldsize > 1) {
00335                         if (isset($zthis->fields[1]))
00336                                 $zval2 = rtrim($zthis->fields[1]);
00337                         else
00338                                 $zval2 = rtrim(next($zthis->fields));
00339                 }
00340                 $selected = ($compareFields0) ? $zval : $zval2;
00341                 
00342         $group = '';
00343                 if (isset($zthis->fields[2])) {
00344             $group = rtrim($zthis->fields[2]);
00345         }
00346  
00347         if ($optgroup != $group) {
00348             $optgroup = $group;
00349             if ($firstgroup) {
00350                 $firstgroup = false;
00351                 $s .="\n<optgroup label='". htmlspecialchars($group) ."'>";
00352             } else {
00353                 $s .="\n</optgroup>";
00354                 $s .="\n<optgroup label='". htmlspecialchars($group) ."'>";
00355             }
00356                 }
00357         
00358                 if ($hasvalue) 
00359                         $value = " value='".htmlspecialchars($zval2)."'";
00360                 
00361                 if (is_array($defstr))  {
00362                         
00363                         if (in_array($selected,$defstr)) 
00364                                 $s .= "\n<option selected='selected'$value>".htmlspecialchars($zval).'</option>';
00365                         else 
00366                                 $s .= "\n<option".$value.'>'.htmlspecialchars($zval).'</option>';
00367                 }
00368                 else {
00369                         if (strcasecmp($selected,$defstr)==0) 
00370                                 $s .= "\n<option selected='selected'$value>".htmlspecialchars($zval).'</option>';
00371                         else
00372                                 $s .= "\n<option".$value.'>'.htmlspecialchars($zval).'</option>';
00373                 }
00374                 $zthis->MoveNext();
00375         } // while
00376         
00377     // closing last optgroup
00378     if($optgroup != null) {
00379         $s .= "\n</optgroup>";
00380         }
00381         return $s ."\n</select>\n";
00382 }
00383 
00384 
00385 /*
00386         Count the number of records this sql statement will return by using
00387         query rewriting heuristics...
00388         
00389         Does not work with UNIONs, except with postgresql and oracle.
00390         
00391         Usage:
00392         
00393         $conn->Connect(...);
00394         $cnt = _adodb_getcount($conn, $sql);
00395         
00396 */
00397 function _adodb_getcount(&$zthis, $sql,$inputarr=false,$secs2cache=0) 
00398 {
00399         $qryRecs = 0;
00400         
00401          if (!empty($zthis->_nestedSQL) || preg_match("/^\s*SELECT\s+DISTINCT/is", $sql) || 
00402                 preg_match('/\s+GROUP\s+BY\s+/is',$sql) || 
00403                 preg_match('/\s+UNION\s+/is',$sql)) {
00404                 
00405                 $rewritesql = adodb_strip_order_by($sql);
00406                 
00407                 // ok, has SELECT DISTINCT or GROUP BY so see if we can use a table alias
00408                 // but this is only supported by oracle and postgresql...
00409                 if ($zthis->dataProvider == 'oci8') {
00410                         // Allow Oracle hints to be used for query optimization, Chris Wrye
00411                         if (preg_match('#/\\*+.*?\\*\\/#', $sql, $hint)) {
00412                                 $rewritesql = "SELECT ".$hint[0]." COUNT(*) FROM (".$rewritesql.")"; 
00413                         } else
00414                                 $rewritesql = "SELECT COUNT(*) FROM (".$rewritesql.")"; 
00415                         
00416                 } else if (strncmp($zthis->databaseType,'postgres',8) == 0 || strncmp($zthis->databaseType,'mysql',5) == 0)  {
00417                         $rewritesql = "SELECT COUNT(*) FROM ($rewritesql) _ADODB_ALIAS_";
00418                 } else {
00419                         $rewritesql = "SELECT COUNT(*) FROM ($rewritesql)";
00420                 }
00421         } else {
00422                 // now replace SELECT ... FROM with SELECT COUNT(*) FROM
00423                 $rewritesql = preg_replace(
00424                                         '/^\s*SELECT\s.*\s+FROM\s/Uis','SELECT COUNT(*) FROM ',$sql);
00425                 // fix by alexander zhukov, alex#unipack.ru, because count(*) and 'order by' fails 
00426                 // with mssql, access and postgresql. Also a good speedup optimization - skips sorting!
00427                 // also see http://phplens.com/lens/lensforum/msgs.php?id=12752
00428                 $rewritesql = adodb_strip_order_by($rewritesql);
00429         }
00430         
00431         if (isset($rewritesql) && $rewritesql != $sql) {
00432                 if (preg_match('/\sLIMIT\s+[0-9]+/i',$sql,$limitarr)) $rewritesql .= $limitarr[0];
00433                  
00434                 if ($secs2cache) {
00435                         // we only use half the time of secs2cache because the count can quickly
00436                         // become inaccurate if new records are added
00437                         $qryRecs = $zthis->CacheGetOne($secs2cache/2,$rewritesql,$inputarr);
00438                         
00439                 } else {
00440                         $qryRecs = $zthis->GetOne($rewritesql,$inputarr);
00441                 }
00442                 if ($qryRecs !== false) return $qryRecs;
00443         }
00444         //--------------------------------------------
00445         // query rewrite failed - so try slower way...
00446         
00447         
00448         // strip off unneeded ORDER BY if no UNION
00449         if (preg_match('/\s*UNION\s*/is', $sql)) $rewritesql = $sql;
00450         else $rewritesql = $rewritesql = adodb_strip_order_by($sql); 
00451         
00452         if (preg_match('/\sLIMIT\s+[0-9]+/i',$sql,$limitarr)) $rewritesql .= $limitarr[0];
00453                 
00454         if ($secs2cache) {
00455                 $rstest = $zthis->CacheExecute($secs2cache,$rewritesql,$inputarr);
00456                 if (!$rstest) $rstest = $zthis->CacheExecute($secs2cache,$sql,$inputarr);
00457         } else {
00458                 $rstest = $zthis->Execute($rewritesql,$inputarr);
00459                 if (!$rstest) $rstest = $zthis->Execute($sql,$inputarr);
00460         }
00461         if ($rstest) {
00462                         $qryRecs = $rstest->RecordCount();
00463                 if ($qryRecs == -1) { 
00464                 global $ADODB_EXTENSION;
00465                 // some databases will return -1 on MoveLast() - change to MoveNext()
00466                         if ($ADODB_EXTENSION) {
00467                                 while(!$rstest->EOF) {
00468                                         adodb_movenext($rstest);
00469                                 }
00470                         } else {
00471                                 while(!$rstest->EOF) {
00472                                         $rstest->MoveNext();
00473                                 }
00474                         }
00475                         $qryRecs = $rstest->_currentRow;
00476                 }
00477                 $rstest->Close();
00478                 if ($qryRecs == -1) return 0;
00479         }
00480         return $qryRecs;
00481 }
00482 
00483 /*
00484         Code originally from "Cornel G" <conyg@fx.ro>
00485 
00486         This code might not work with SQL that has UNION in it  
00487         
00488         Also if you are using CachePageExecute(), there is a strong possibility that
00489         data will get out of synch. use CachePageExecute() only with tables that
00490         rarely change.
00491 */
00492 function _adodb_pageexecute_all_rows(&$zthis, $sql, $nrows, $page, 
00493                                                 $inputarr=false, $secs2cache=0) 
00494 {
00495         $atfirstpage = false;
00496         $atlastpage = false;
00497         $lastpageno=1;
00498 
00499         // If an invalid nrows is supplied, 
00500         // we assume a default value of 10 rows per page
00501         if (!isset($nrows) || $nrows <= 0) $nrows = 10;
00502 
00503         $qryRecs = false; //count records for no offset
00504         
00505         $qryRecs = _adodb_getcount($zthis,$sql,$inputarr,$secs2cache);
00506         $lastpageno = (int) ceil($qryRecs / $nrows);
00507         $zthis->_maxRecordCount = $qryRecs;
00508         
00509 
00510 
00511         // ***** Here we check whether $page is the last page or 
00512         // whether we are trying to retrieve 
00513         // a page number greater than the last page number.
00514         if ($page >= $lastpageno) {
00515                 $page = $lastpageno;
00516                 $atlastpage = true;
00517         }
00518         
00519         // If page number <= 1, then we are at the first page
00520         if (empty($page) || $page <= 1) {       
00521                 $page = 1;
00522                 $atfirstpage = true;
00523         }
00524         
00525         // We get the data we want
00526         $offset = $nrows * ($page-1);
00527         if ($secs2cache > 0) 
00528                 $rsreturn = $zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $offset, $inputarr);
00529         else 
00530                 $rsreturn = $zthis->SelectLimit($sql, $nrows, $offset, $inputarr, $secs2cache);
00531 
00532         
00533         // Before returning the RecordSet, we set the pagination properties we need
00534         if ($rsreturn) {
00535                 $rsreturn->_maxRecordCount = $qryRecs;
00536                 $rsreturn->rowsPerPage = $nrows;
00537                 $rsreturn->AbsolutePage($page);
00538                 $rsreturn->AtFirstPage($atfirstpage);
00539                 $rsreturn->AtLastPage($atlastpage);
00540                 $rsreturn->LastPageNo($lastpageno);
00541         }
00542         return $rsreturn;
00543 }
00544 
00545 // Iván Oliva version
00546 function _adodb_pageexecute_no_last_page(&$zthis, $sql, $nrows, $page, $inputarr=false, $secs2cache=0) 
00547 {
00548 
00549         $atfirstpage = false;
00550         $atlastpage = false;
00551         
00552         if (!isset($page) || $page <= 1) {      // If page number <= 1, then we are at the first page
00553                 $page = 1;
00554                 $atfirstpage = true;
00555         }
00556         if ($nrows <= 0) $nrows = 10;   // If an invalid nrows is supplied, we assume a default value of 10 rows per page
00557         
00558         // ***** Here we check whether $page is the last page or whether we are trying to retrieve a page number greater than 
00559         // the last page number.
00560         $pagecounter = $page + 1;
00561         $pagecounteroffset = ($pagecounter * $nrows) - $nrows;
00562         if ($secs2cache>0) $rstest = $zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $pagecounteroffset, $inputarr);
00563         else $rstest = $zthis->SelectLimit($sql, $nrows, $pagecounteroffset, $inputarr, $secs2cache);
00564         if ($rstest) {
00565                 while ($rstest && $rstest->EOF && $pagecounter>0) {
00566                         $atlastpage = true;
00567                         $pagecounter--;
00568                         $pagecounteroffset = $nrows * ($pagecounter - 1);
00569                         $rstest->Close();
00570                         if ($secs2cache>0) $rstest = $zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $pagecounteroffset, $inputarr);
00571                         else $rstest = $zthis->SelectLimit($sql, $nrows, $pagecounteroffset, $inputarr, $secs2cache);
00572                 }
00573                 if ($rstest) $rstest->Close();
00574         }
00575         if ($atlastpage) {      // If we are at the last page or beyond it, we are going to retrieve it
00576                 $page = $pagecounter;
00577                 if ($page == 1) $atfirstpage = true;    // We have to do this again in case the last page is the same as the first
00578                         //... page, that is, the recordset has only 1 page.
00579         }
00580         
00581         // We get the data we want
00582         $offset = $nrows * ($page-1);
00583         if ($secs2cache > 0) $rsreturn = $zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $offset, $inputarr);
00584         else $rsreturn = $zthis->SelectLimit($sql, $nrows, $offset, $inputarr, $secs2cache);
00585         
00586         // Before returning the RecordSet, we set the pagination properties we need
00587         if ($rsreturn) {
00588                 $rsreturn->rowsPerPage = $nrows;
00589                 $rsreturn->AbsolutePage($page);
00590                 $rsreturn->AtFirstPage($atfirstpage);
00591                 $rsreturn->AtLastPage($atlastpage);
00592         }
00593         return $rsreturn;
00594 }
00595 
00596 function _adodb_getupdatesql(&$zthis,&$rs, $arrFields,$forceUpdate=false,$magicq=false,$force=2)
00597 {
00598         global $ADODB_QUOTE_FIELDNAMES;
00599 
00600                 if (!$rs) {
00601                         printf(ADODB_BAD_RS,'GetUpdateSQL');
00602                         return false;
00603                 }
00604         
00605                 $fieldUpdatedCount = 0;
00606                 $arrFields = _array_change_key_case($arrFields);
00607 
00608                 $hasnumeric = isset($rs->fields[0]);
00609                 $setFields = '';
00610                 
00611                 // Loop through all of the fields in the recordset
00612                 for ($i=0, $max=$rs->FieldCount(); $i < $max; $i++) {
00613                         // Get the field from the recordset
00614                         $field = $rs->FetchField($i);
00615 
00616                         // If the recordset field is one
00617                         // of the fields passed in then process.
00618                         $upperfname = strtoupper($field->name);
00619                         if (adodb_key_exists($upperfname,$arrFields,$force)) {
00620                                 
00621                                 // If the existing field value in the recordset
00622                                 // is different from the value passed in then
00623                                 // go ahead and append the field name and new value to
00624                                 // the update query.
00625                                 
00626                                 if ($hasnumeric) $val = $rs->fields[$i];
00627                                 else if (isset($rs->fields[$upperfname])) $val = $rs->fields[$upperfname];
00628                                 else if (isset($rs->fields[$field->name])) $val =  $rs->fields[$field->name];
00629                                 else if (isset($rs->fields[strtolower($upperfname)])) $val =  $rs->fields[strtolower($upperfname)];
00630                                 else $val = '';
00631                                 
00632                         
00633                                 if ($forceUpdate || strcmp($val, $arrFields[$upperfname])) {
00634                                         // Set the counter for the number of fields that will be updated.
00635                                         $fieldUpdatedCount++;
00636 
00637                                         // Based on the datatype of the field
00638                                         // Format the value properly for the database
00639                                         $type = $rs->MetaType($field->type);
00640                                                 
00641 
00642                                         if ($type == 'null') {
00643                                                 $type = 'C';
00644                                         }
00645                                         
00646                                         if ((strpos($upperfname,' ') !== false) || ($ADODB_QUOTE_FIELDNAMES)) {
00647                                                 switch (ADODB_QUOTE_FIELDNAMES) {
00648                                                 case 'LOWER':
00649                                                         $fnameq = $zthis->nameQuote.strtolower($field->name).$zthis->nameQuote;break;
00650                                                 case 'NATIVE':
00651                                                         $fnameq = $zthis->nameQuote.$field->name.$zthis->nameQuote;break;
00652                                                 case 'UPPER':
00653                                                 default:
00654                                                         $fnameq = $zthis->nameQuote.$upperfname.$zthis->nameQuote;break;
00655                                                 }
00656                                         } else
00657                                                 $fnameq = $upperfname;
00658                                         
00659                                         
00660                 // is_null requires php 4.0.4
00661                 //********************************************************//
00662                 if (is_null($arrFields[$upperfname])
00663                                         || (empty($arrFields[$upperfname]) && strlen($arrFields[$upperfname]) == 0)
00664                     || $arrFields[$upperfname] === $zthis->null2null
00665                     )
00666                 {
00667                     switch ($force) {
00668 
00669                         //case 0:
00670                         //    //Ignore empty values. This is allready handled in "adodb_key_exists" function.
00671                         //break;
00672 
00673                         case 1:
00674                             //Set null
00675                             $setFields .= $field->name . " = null, ";
00676                         break;
00677                                                         
00678                         case 2:
00679                             //Set empty
00680                             $arrFields[$upperfname] = "";
00681                             $setFields .= _adodb_column_sql($zthis, 'U', $type, $upperfname, $fnameq,$arrFields, $magicq);
00682                         break;
00683                                                 default:
00684                         case 3:
00685                             //Set the value that was given in array, so you can give both null and empty values
00686                             if (is_null($arrFields[$upperfname]) || $arrFields[$upperfname] === $zthis->null2null) {
00687                                 $setFields .= $field->name . " = null, ";
00688                             } else {
00689                                 $setFields .= _adodb_column_sql($zthis, 'U', $type, $upperfname, $fnameq,$arrFields, $magicq);
00690                             }
00691                         break;
00692                     }
00693                 //********************************************************//
00694                 } else {
00695                                                 //we do this so each driver can customize the sql for
00696                                                 //DB specific column types. 
00697                                                 //Oracle needs BLOB types to be handled with a returning clause
00698                                                 //postgres has special needs as well
00699                                                 $setFields .= _adodb_column_sql($zthis, 'U', $type, $upperfname, $fnameq,
00700                                                                                                                   $arrFields, $magicq);
00701                                         }
00702                                 }
00703                         }
00704                 }
00705 
00706                 // If there were any modified fields then build the rest of the update query.
00707                 if ($fieldUpdatedCount > 0 || $forceUpdate) {
00708                                         // Get the table name from the existing query.
00709                         if (!empty($rs->tableName)) $tableName = $rs->tableName;
00710                         else {
00711                                 preg_match("/FROM\s+".ADODB_TABLE_REGEX."/is", $rs->sql, $tableName);
00712                                 $tableName = $tableName[1];
00713                         }
00714                         // Get the full where clause excluding the word "WHERE" from
00715                         // the existing query.
00716                         preg_match('/\sWHERE\s(.*)/is', $rs->sql, $whereClause);
00717                         
00718                         $discard = false;
00719                         // not a good hack, improvements?
00720                         if ($whereClause) {
00721                         #var_dump($whereClause);
00722                                 if (preg_match('/\s(ORDER\s.*)/is', $whereClause[1], $discard));
00723                                 else if (preg_match('/\s(LIMIT\s.*)/is', $whereClause[1], $discard));
00724                                 else if (preg_match('/\s(FOR UPDATE.*)/is', $whereClause[1], $discard));
00725                                 else preg_match('/\s.*(\) WHERE .*)/is', $whereClause[1], $discard); # see http://sourceforge.net/tracker/index.php?func=detail&aid=1379638&group_id=42718&atid=433976
00726                         } else
00727                                 $whereClause = array(false,false);
00728                                 
00729                         if ($discard)
00730                                 $whereClause[1] = substr($whereClause[1], 0, strlen($whereClause[1]) - strlen($discard[1]));
00731                         
00732                         $sql = 'UPDATE '.$tableName.' SET '.substr($setFields, 0, -2);
00733                         if (strlen($whereClause[1]) > 0) 
00734                                 $sql .= ' WHERE '.$whereClause[1];
00735 
00736                         return $sql;
00737 
00738                 } else {
00739                         return false;
00740         }
00741 }
00742 
00743 function adodb_key_exists($key, &$arr,$force=2)
00744 {
00745         if ($force<=0) {
00746                 // the following is the old behaviour where null or empty fields are ignored
00747                 return (!empty($arr[$key])) || (isset($arr[$key]) && strlen($arr[$key])>0);
00748         }
00749 
00750         if (isset($arr[$key])) return true;
00751         ## null check below
00752         if (ADODB_PHPVER >= 0x4010) return array_key_exists($key,$arr);
00753         return false;
00754 }
00755 
00763 function _adodb_getinsertsql(&$zthis,&$rs,$arrFields,$magicq=false,$force=2)
00764 {
00765 static $cacheRS = false;
00766 static $cacheSig = 0;
00767 static $cacheCols;
00768         global $ADODB_QUOTE_FIELDNAMES;
00769 
00770         $tableName = '';
00771         $values = '';
00772         $fields = '';
00773         $recordSet = null;
00774         $arrFields = _array_change_key_case($arrFields);
00775         $fieldInsertedCount = 0;
00776         
00777         if (is_string($rs)) {
00778                 //ok we have a table name
00779                 //try and get the column info ourself.
00780                 $tableName = $rs;                       
00781         
00782                 //we need an object for the recordSet
00783                 //because we have to call MetaType.
00784                 //php can't do a $rsclass::MetaType()
00785                 $rsclass = $zthis->rsPrefix.$zthis->databaseType;
00786                 $recordSet = new $rsclass(-1,$zthis->fetchMode);
00787                 $recordSet->connection = $zthis;
00788                 
00789                 if (is_string($cacheRS) && $cacheRS == $rs) {
00790                         $columns = $cacheCols;
00791                 } else {
00792                         $columns = $zthis->MetaColumns( $tableName );
00793                         $cacheRS = $tableName;
00794                         $cacheCols = $columns;
00795                 }
00796         } else if (is_subclass_of($rs, 'adorecordset')) {
00797                 if (isset($rs->insertSig) && is_integer($cacheRS) && $cacheRS == $rs->insertSig) {
00798                         $columns = $cacheCols;
00799                 } else {
00800                         for ($i=0, $max=$rs->FieldCount(); $i < $max; $i++) 
00801                                 $columns[] = $rs->FetchField($i);
00802                         $cacheRS = $cacheSig;
00803                         $cacheCols = $columns;
00804                         $rs->insertSig = $cacheSig++;
00805                 }
00806                 $recordSet = $rs;
00807         
00808         } else {
00809                 printf(ADODB_BAD_RS,'GetInsertSQL');
00810                 return false;
00811         }
00812 
00813         // Loop through all of the fields in the recordset
00814         foreach( $columns as $field ) { 
00815                 $upperfname = strtoupper($field->name);
00816                 if (adodb_key_exists($upperfname,$arrFields,$force)) {
00817                         $bad = false;
00818                         if ((strpos($upperfname,' ') !== false) || ($ADODB_QUOTE_FIELDNAMES)) {
00819                                 switch (ADODB_QUOTE_FIELDNAMES) {
00820                                 case 'LOWER':
00821                                         $fnameq = $zthis->nameQuote.strtolower($field->name).$zthis->nameQuote;break;
00822                                 case 'NATIVE':
00823                                         $fnameq = $zthis->nameQuote.$field->name.$zthis->nameQuote;break;
00824                                 case 'UPPER':
00825                                 default:
00826                                         $fnameq = $zthis->nameQuote.$upperfname.$zthis->nameQuote;break;
00827                                 }
00828                         } else
00829                                 $fnameq = $upperfname;
00830                         
00831                         $type = $recordSet->MetaType($field->type);
00832                         
00833             /********************************************************/
00834             if (is_null($arrFields[$upperfname])
00835                 || (empty($arrFields[$upperfname]) && strlen($arrFields[$upperfname]) == 0)
00836                 || $arrFields[$upperfname] === $zthis->null2null
00837                                 )
00838                {
00839                     switch ($force) {
00840 
00841                         case 0: // we must always set null if missing
00842                                                         $bad = true;
00843                                                         break;
00844                                                         
00845                         case 1:
00846                             $values  .= "null, ";
00847                         break;
00848                 
00849                         case 2:
00850                             //Set empty
00851                             $arrFields[$upperfname] = "";
00852                             $values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq,$arrFields, $magicq);
00853                         break;
00854 
00855                                                 default:
00856                         case 3:
00857                             //Set the value that was given in array, so you can give both null and empty values
00858                                                         if (is_null($arrFields[$upperfname]) || $arrFields[$upperfname] === $zthis->null2null) { 
00859                                                                 $values  .= "null, ";
00860                                                         } else {
00861                                         $values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq, $arrFields, $magicq);
00862                                         }
00863                                 break;
00864                         } // switch
00865 
00866             /*********************************************************/
00867                         } else {
00868                                 //we do this so each driver can customize the sql for
00869                                 //DB specific column types. 
00870                                 //Oracle needs BLOB types to be handled with a returning clause
00871                                 //postgres has special needs as well
00872                                 $values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq,
00873                                                                                            $arrFields, $magicq);
00874                         }
00875                         
00876                         if ($bad) continue;
00877                         // Set the counter for the number of fields that will be inserted.
00878                         $fieldInsertedCount++;
00879                         
00880                         
00881                         // Get the name of the fields to insert
00882                         $fields .= $fnameq . ", ";
00883                 }
00884         }
00885 
00886 
00887         // If there were any inserted fields then build the rest of the insert query.
00888         if ($fieldInsertedCount <= 0)  return false;
00889         
00890         // Get the table name from the existing query.
00891         if (!$tableName) {
00892                 if (!empty($rs->tableName)) $tableName = $rs->tableName;
00893                 else if (preg_match("/FROM\s+".ADODB_TABLE_REGEX."/is", $rs->sql, $tableName))
00894                         $tableName = $tableName[1];
00895                 else 
00896                         return false;
00897         }               
00898 
00899         // Strip off the comma and space on the end of both the fields
00900         // and their values.
00901         $fields = substr($fields, 0, -2);
00902         $values = substr($values, 0, -2);
00903 
00904         // Append the fields and their values to the insert query.
00905         return 'INSERT INTO '.$tableName.' ( '.$fields.' ) VALUES ( '.$values.' )';
00906 }
00907 
00908 
00924 function _adodb_column_sql_oci8(&$zthis,$action, $type, $fname, $fnameq, $arrFields, $magicq) 
00925 {
00926     $sql = '';
00927     
00928     // Based on the datatype of the field
00929     // Format the value properly for the database
00930     switch($type) {
00931     case 'B':
00932         //in order to handle Blobs correctly, we need
00933         //to do some magic for Oracle
00934 
00935         //we need to create a new descriptor to handle 
00936         //this properly
00937         if (!empty($zthis->hasReturningInto)) {
00938             if ($action == 'I') {
00939                 $sql = 'empty_blob(), ';
00940             } else {
00941                 $sql = $fnameq. '=empty_blob(), ';
00942             }
00943             //add the variable to the returning clause array
00944             //so the user can build this later in
00945             //case they want to add more to it
00946             $zthis->_returningArray[$fname] = ':xx'.$fname.'xx';
00947         } else if (empty($arrFields[$fname])){
00948             if ($action == 'I') {
00949                 $sql = 'empty_blob(), ';
00950             } else {
00951                 $sql = $fnameq. '=empty_blob(), ';
00952             }            
00953         } else {
00954             //this is to maintain compatibility
00955             //with older adodb versions.
00956             $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq,false);
00957         }
00958         break;
00959 
00960     case "X":
00961         //we need to do some more magic here for long variables
00962         //to handle these correctly in oracle.
00963 
00964         //create a safe bind var name
00965         //to avoid conflicts w/ dupes.
00966        if (!empty($zthis->hasReturningInto)) {
00967             if ($action == 'I') {
00968                 $sql = ':xx'.$fname.'xx, ';                
00969             } else {
00970                 $sql = $fnameq.'=:xx'.$fname.'xx, ';
00971             }
00972             //add the variable to the returning clause array
00973             //so the user can build this later in
00974             //case they want to add more to it
00975             $zthis->_returningArray[$fname] = ':xx'.$fname.'xx';
00976         } else {
00977             //this is to maintain compatibility
00978             //with older adodb versions.
00979             $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq,false);
00980         }            
00981         break;
00982         
00983     default:
00984         $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq,  $arrFields, $magicq,false);
00985         break;
00986     }
00987     
00988     return $sql;
00989 }    
00990         
00991 function _adodb_column_sql(&$zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq, $recurse=true) 
00992 {
00993 
00994         if ($recurse) {
00995                 switch($zthis->dataProvider)  {
00996                 case 'postgres':
00997                         if ($type == 'L') $type = 'C';
00998                         break;
00999                 case 'oci8':
01000                         return _adodb_column_sql_oci8($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq);
01001                         
01002                 }
01003         }
01004                 
01005         switch($type) {
01006                 case "C":
01007                 case "X":
01008                 case 'B':
01009                         $val = $zthis->qstr($arrFields[$fname],$magicq);
01010                         break;
01011 
01012                 case "D":
01013                         $val = $zthis->DBDate($arrFields[$fname]);
01014                         break;
01015 
01016                 case "T":
01017                         $val = $zthis->DBTimeStamp($arrFields[$fname]);
01018                         break;
01019                         
01020                 case "N":
01021                     $val = $arrFields[$fname];
01022                         if (!is_numeric($val)) $val = str_replace(',', '.', (float)$val);
01023                     break;
01024 
01025                 case "I":
01026                 case "R":
01027                     $val = $arrFields[$fname];
01028                         if (!is_numeric($val)) $val = (integer) $val;
01029                     break;
01030 
01031                 default:
01032                         $val = str_replace(array("'"," ","("),"",$arrFields[$fname]); // basic sql injection defence
01033                         if (empty($val)) $val = '0';
01034                         break;
01035         }
01036 
01037         if ($action == 'I') return $val . ", ";
01038         
01039         
01040         return $fnameq . "=" . $val  . ", ";
01041         
01042 }
01043 
01044 
01045 
01046 function _adodb_debug_execute(&$zthis, $sql, $inputarr)
01047 {
01048         $ss = '';
01049         if ($inputarr) {
01050                 foreach($inputarr as $kk=>$vv) {
01051                         if (is_string($vv) && strlen($vv)>64) $vv = substr($vv,0,64).'...';
01052                         if (is_null($vv)) $ss .= "($kk=>null) ";
01053                         else $ss .= "($kk=>'$vv') ";
01054                 }
01055                 $ss = "[ $ss ]";
01056         }
01057         $sqlTxt = is_array($sql) ? $sql[0] : $sql;
01058         /*str_replace(', ','##1#__^LF',is_array($sql) ? $sql[0] : $sql);
01059         $sqlTxt = str_replace(',',', ',$sqlTxt);
01060         $sqlTxt = str_replace('##1#__^LF', ', ' ,$sqlTxt);
01061         */
01062         // check if running from browser or command-line
01063         $inBrowser = isset($_SERVER['HTTP_USER_AGENT']);
01064         
01065         $dbt = $zthis->databaseType;
01066         if (isset($zthis->dsnType)) $dbt .= '-'.$zthis->dsnType;
01067         if ($inBrowser) {
01068                 if ($ss) {
01069                         $ss = '<code>'.htmlspecialchars($ss).'</code>';
01070                 }
01071                 if ($zthis->debug === -1)
01072                         ADOConnection::outp( "<br>\n($dbt): ".htmlspecialchars($sqlTxt)." &nbsp; $ss\n<br>\n",false);
01073                 else if ($zthis->debug !== -99)
01074                         ADOConnection::outp( "<hr>\n($dbt): ".htmlspecialchars($sqlTxt)." &nbsp; $ss\n<hr>\n",false);
01075         } else {
01076                 $ss = "\n   ".$ss;
01077                 if ($zthis->debug !== -99)
01078                         ADOConnection::outp("-----<hr>\n($dbt): ".$sqlTxt." $ss\n-----<hr>\n",false);
01079         }
01080 
01081         $qID = $zthis->_query($sql,$inputarr);
01082         
01083         /* 
01084                 Alexios Fakios notes that ErrorMsg() must be called before ErrorNo() for mssql
01085                 because ErrorNo() calls Execute('SELECT @ERROR'), causing recursion
01086         */
01087         if ($zthis->databaseType == 'mssql') { 
01088         // ErrorNo is a slow function call in mssql, and not reliable in PHP 4.0.6
01089         
01090                 if($emsg = $zthis->ErrorMsg()) {
01091                         if ($err = $zthis->ErrorNo()) {
01092                                 if ($zthis->debug === -99) 
01093                                         ADOConnection::outp( "<hr>\n($dbt): ".htmlspecialchars($sqlTxt)." &nbsp; $ss\n<hr>\n",false);
01094                 
01095                                 ADOConnection::outp($err.': '.$emsg);
01096                         }
01097                 }
01098         } else if (!$qID) {
01099         
01100                 if ($zthis->debug === -99) 
01101                                 if ($inBrowser) ADOConnection::outp( "<hr>\n($dbt): ".htmlspecialchars($sqlTxt)." &nbsp; $ss\n<hr>\n",false);
01102                                 else ADOConnection::outp("-----<hr>\n($dbt): ".$sqlTxt."$ss\n-----<hr>\n",false);
01103                                 
01104                 ADOConnection::outp($zthis->ErrorNo() .': '. $zthis->ErrorMsg());
01105         }
01106         
01107         if ($zthis->debug === 99) _adodb_backtrace(true,9999,2);
01108         return $qID;
01109 }
01110 
01111 # pretty print the debug_backtrace function
01112 function _adodb_backtrace($printOrArr=true,$levels=9999,$skippy=0,$ishtml=null)
01113 {
01114         if (!function_exists('debug_backtrace')) return '';
01115          
01116         if ($ishtml === null) $html =  (isset($_SERVER['HTTP_USER_AGENT']));
01117         else $html = $ishtml;
01118         
01119         $fmt =  ($html) ? "</font><font color=#808080 size=-1> %% line %4d, file: <a href=\"file:/%s\">%s</a></font>" : "%% line %4d, file: %s";
01120 
01121         $MAXSTRLEN = 128;
01122 
01123         $s = ($html) ? '<pre align=left>' : '';
01124         
01125         if (is_array($printOrArr)) $traceArr = $printOrArr;
01126         else $traceArr = debug_backtrace();
01127         array_shift($traceArr);
01128         array_shift($traceArr);
01129         $tabs = sizeof($traceArr)-2;
01130         
01131         foreach ($traceArr as $arr) {
01132                 if ($skippy) {$skippy -= 1; continue;}
01133                 $levels -= 1;
01134                 if ($levels < 0) break;
01135                 
01136                 $args = array();
01137                 for ($i=0; $i < $tabs; $i++) $s .=  ($html) ? ' &nbsp; ' : "\t";
01138                 $tabs -= 1;
01139                 if ($html) $s .= '<font face="Courier New,Courier">';
01140                 if (isset($arr['class'])) $s .= $arr['class'].'.';
01141                 if (isset($arr['args']))
01142                  foreach($arr['args'] as $v) {
01143                         if (is_null($v)) $args[] = 'null';
01144                         else if (is_array($v)) $args[] = 'Array['.sizeof($v).']';
01145                         else if (is_object($v)) $args[] = 'Object:'.get_class($v);
01146                         else if (is_bool($v)) $args[] = $v ? 'true' : 'false';
01147                         else {
01148                                 $v = (string) @$v;
01149                                 $str = htmlspecialchars(str_replace(array("\r","\n"),' ',substr($v,0,$MAXSTRLEN)));
01150                                 if (strlen($v) > $MAXSTRLEN) $str .= '...';
01151                                 $args[] = $str;
01152                         }
01153                 }
01154                 $s .= $arr['function'].'('.implode(', ',$args).')';
01155                 
01156                 
01157                 $s .= @sprintf($fmt, $arr['line'],$arr['file'],basename($arr['file']));
01158                         
01159                 $s .= "\n";
01160         }       
01161         if ($html) $s .= '</pre>';
01162         if ($printOrArr) print $s;
01163         
01164         return $s;
01165 }
01166 /*
01167 function _adodb_find_from($sql) 
01168 {
01169 
01170         $sql = str_replace(array("\n","\r"), ' ', $sql);
01171         $charCount = strlen($sql);
01172         
01173         $inString = false;
01174         $quote = '';
01175         $parentheseCount = 0;
01176         $prevChars = '';
01177         $nextChars = '';
01178         
01179 
01180         for($i = 0; $i < $charCount; $i++) {
01181 
01182         $char = substr($sql,$i,1);
01183             $prevChars = substr($sql,0,$i);
01184         $nextChars = substr($sql,$i+1);
01185 
01186                 if((($char == "'" || $char == '"' || $char == '`') && substr($prevChars,-1,1) != '\\') && $inString === false) {
01187                         $quote = $char;
01188                         $inString = true;
01189                 }
01190 
01191                 elseif((($char == "'" || $char == '"' || $char == '`') && substr($prevChars,-1,1) != '\\') && $inString === true && $quote == $char) {
01192                         $quote = "";
01193                         $inString = false;
01194                 }
01195 
01196                 elseif($char == "(" && $inString === false)
01197                         $parentheseCount++;
01198 
01199                 elseif($char == ")" && $inString === false && $parentheseCount > 0)
01200                         $parentheseCount--;
01201 
01202                 elseif($parentheseCount <= 0 && $inString === false && $char == " " && strtoupper(substr($prevChars,-5,5)) == " FROM")
01203                         return $i;
01204 
01205         }
01206 }
01207 */
01208 
01209 ?>
 All Data Structures Namespaces Files Functions Variables Enumerations