Committed ADOdb extension as a sysext.
authorKarsten Dambekalns <karsten.dambekalns@typo3.org>
Tue, 27 Dec 2005 15:15:39 +0000 (15:15 +0000)
committerKarsten Dambekalns <karsten.dambekalns@typo3.org>
Tue, 27 Dec 2005 15:15:39 +0000 (15:15 +0000)
git-svn-id: https://svn.typo3.org/TYPO3v4/Core/trunk@946 709f56b5-9817-0410-a4d7-c38de5d9e867

185 files changed:
typo3/sysext/adodb/adodb/adodb-csvlib.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/adodb-datadict.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/adodb-error.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/adodb-errorhandler.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/adodb-errorpear.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/adodb-exceptions.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/adodb-iterator.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/adodb-lib.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/adodb-pager.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/adodb-pear.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/adodb-perf.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/adodb-php4.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/adodb-time.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/adodb-xmlschema.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/adodb.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/contrib/toxmlrpc.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/cute_icons_for_site/adodb.gif [new file with mode: 0644]
typo3/sysext/adodb/adodb/cute_icons_for_site/adodb2.gif [new file with mode: 0644]
typo3/sysext/adodb/adodb/datadict/datadict-access.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/datadict/datadict-db2.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/datadict/datadict-firebird.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/datadict/datadict-generic.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/datadict/datadict-ibase.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/datadict/datadict-informix.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/datadict/datadict-mssql.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/datadict/datadict-mysql.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/datadict/datadict-oci8.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/datadict/datadict-postgres.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/datadict/datadict-sapdb.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/datadict/datadict-sybase.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/docs/docs-adodb.htm [new file with mode: 0644]
typo3/sysext/adodb/adodb/docs/docs-datadict.htm [new file with mode: 0644]
typo3/sysext/adodb/adodb/docs/docs-oracle.htm [new file with mode: 0644]
typo3/sysext/adodb/adodb/docs/docs-perf.htm [new file with mode: 0644]
typo3/sysext/adodb/adodb/docs/docs-session.htm [new file with mode: 0644]
typo3/sysext/adodb/adodb/docs/old-changelog.htm [new file with mode: 0644]
typo3/sysext/adodb/adodb/docs/readme.htm [new file with mode: 0644]
typo3/sysext/adodb/adodb/docs/tips_portable_sql.htm [new file with mode: 0644]
typo3/sysext/adodb/adodb/docs/tute.htm [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-access.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-ado.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-ado5.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-ado_access.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-ado_mssql.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-borland_ibase.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-csv.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-db2.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-fbsql.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-firebird.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-ibase.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-informix.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-informix72.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-ldap.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-mssql.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-mssqlpo.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-mysql.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-mysqli.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-mysqlt.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-netezza.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-oci8.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-oci805.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-oci8po.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-odbc.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-odbc_mssql.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-odbc_oracle.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-odbtp.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-odbtp_unicode.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-oracle.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-pdo.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-pdo_mssql.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-pdo_mysql.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-pdo_oci.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-pdo_pgsql.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-postgres.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-postgres64.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-postgres7.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-postgres8.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-proxy.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-sapdb.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-sqlanywhere.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-sqlite.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-sqlitepo.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-sybase.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-sybase_ase.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/drivers/adodb-vfp.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/lang/adodb-ar.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/lang/adodb-bg.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/lang/adodb-bgutf8.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/lang/adodb-ca.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/lang/adodb-cn.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/lang/adodb-cz.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/lang/adodb-da.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/lang/adodb-de.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/lang/adodb-en.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/lang/adodb-es.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/lang/adodb-esperanto.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/lang/adodb-fr.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/lang/adodb-hu.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/lang/adodb-it.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/lang/adodb-nl.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/lang/adodb-pl.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/lang/adodb-pt-br.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/lang/adodb-ro.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/lang/adodb-ru1251.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/lang/adodb-sv.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/lang/adodb-uk1251.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/license.txt [new file with mode: 0644]
typo3/sysext/adodb/adodb/pear/Auth/Container/ADOdb.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/pear/readme.Auth.txt [new file with mode: 0644]
typo3/sysext/adodb/adodb/perf/perf-db2.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/perf/perf-informix.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/perf/perf-mssql.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/perf/perf-mysql.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/perf/perf-oci8.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/perf/perf-postgres.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/pivottable.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/readme.txt [new file with mode: 0644]
typo3/sysext/adodb/adodb/rsfilter.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/server.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/session/adodb-compress-bzip2.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/session/adodb-compress-gzip.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/session/adodb-cryptsession.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/session/adodb-encrypt-mcrypt.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/session/adodb-encrypt-md5.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/session/adodb-encrypt-secret.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/session/adodb-encrypt-sha1.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/session/adodb-sess.txt [new file with mode: 0644]
typo3/sysext/adodb/adodb/session/adodb-session-clob.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/session/adodb-session.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/session/adodb-sessions.mysql.sql [new file with mode: 0644]
typo3/sysext/adodb/adodb/session/adodb-sessions.oracle.clob.sql [new file with mode: 0644]
typo3/sysext/adodb/adodb/session/adodb-sessions.oracle.sql [new file with mode: 0644]
typo3/sysext/adodb/adodb/session/crypt.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/session/old/adodb-cryptsession.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/session/old/adodb-session-clob.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/session/old/adodb-session.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/session/old/crypt.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/session/session_schema.xml [new file with mode: 0644]
typo3/sysext/adodb/adodb/tests/benchmark.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/tests/cf~testsessions.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/tests/client.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/tests/pdo.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/tests/rr.htm [new file with mode: 0644]
typo3/sysext/adodb/adodb/tests/test-datadict.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/tests/test-perf.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/tests/test-pgblob.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/tests/test-php5.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/tests/test-xmlschema.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/tests/test.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/tests/test2.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/tests/test3.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/tests/test4.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/tests/test5.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/tests/test_rs_array.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/tests/testcache.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/tests/testdatabases.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/tests/testgenid.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/tests/testmssql.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/tests/testoci8.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/tests/testoci8cursor.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/tests/testpaging.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/tests/testpear.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/tests/testsessions.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/tests/time.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/tests/tmssql.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/tests/xmlschema-mssql.xml [new file with mode: 0644]
typo3/sysext/adodb/adodb/tests/xmlschema.xml [new file with mode: 0644]
typo3/sysext/adodb/adodb/toexport.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/tohtml.inc.php [new file with mode: 0644]
typo3/sysext/adodb/adodb/xmlschema.dtd [new file with mode: 0644]
typo3/sysext/adodb/adodb/xsl/convert-0.1-0.2.xsl [new file with mode: 0644]
typo3/sysext/adodb/adodb/xsl/convert-0.2-0.1.xsl [new file with mode: 0644]
typo3/sysext/adodb/adodb/xsl/remove-0.2.xsl [new file with mode: 0644]
typo3/sysext/adodb/checkconnectionwizard.php [new file with mode: 0644]
typo3/sysext/adodb/class.tx_adodb_tceforms.php [new file with mode: 0644]
typo3/sysext/adodb/datasource_flexform_ds.xml [new file with mode: 0644]
typo3/sysext/adodb/doc/468.DBAL.patch [new file with mode: 0644]
typo3/sysext/adodb/doc/README [new file with mode: 0644]
typo3/sysext/adodb/ext_emconf.php [new file with mode: 0644]
typo3/sysext/adodb/ext_icon.gif [new file with mode: 0644]
typo3/sysext/adodb/ext_localconf.php [new file with mode: 0644]
typo3/sysext/adodb/locallang_datasource_config.xml [new file with mode: 0644]
typo3/sysext/adodb/locallang_wizard.xml [new file with mode: 0644]
typo3/sysext/adodb/pi1/class.tx_adodb_pi1.php [new file with mode: 0644]
typo3/sysext/adodb/res/checkconnection.gif [new file with mode: 0644]

diff --git a/typo3/sysext/adodb/adodb/adodb-csvlib.inc.php b/typo3/sysext/adodb/adodb/adodb-csvlib.inc.php
new file mode 100644 (file)
index 0000000..fb62bfc
--- /dev/null
@@ -0,0 +1,312 @@
+<?php
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+global $ADODB_INCLUDED_CSV;
+$ADODB_INCLUDED_CSV = 1;
+
+/* 
+
+  V4.68 25 Nov 2005  (c) 2000-2005 John Lim (jlim@natsoft.com.my). All rights reserved.
+  Released under both BSD license and Lesser GPL library license. 
+  Whenever there is any discrepancy between the two licenses, 
+  the BSD license will take precedence. See License.txt. 
+  Set tabs to 4 for best viewing.
+  
+  Latest version is available at http://adodb.sourceforge.net
+  
+  Library for CSV serialization. This is used by the csv/proxy driver and is the 
+  CacheExecute() serialization format. 
+  
+  ==== NOTE ====
+  Format documented at http://php.weblogs.com/ADODB_CSV
+  ==============
+*/
+
+       /**
+        * convert a recordset into special format
+        *
+        * @param rs    the recordset
+        *
+        * @return      the CSV formated data
+        */
+       function _rs2serialize(&$rs,$conn=false,$sql='')
+       {
+               $max = ($rs) ? $rs->FieldCount() : 0;
+               
+               if ($sql) $sql = urlencode($sql);
+               // metadata setup
+               
+               if ($max <= 0 || $rs->dataProvider == 'empty') { // is insert/update/delete
+                       if (is_object($conn)) {
+                               $sql .= ','.$conn->Affected_Rows();
+                               $sql .= ','.$conn->Insert_ID();
+                       } else
+                               $sql .= ',,';
+                       
+                       $text = "====-1,0,$sql\n";
+                       return $text;
+               }
+               $tt = ($rs->timeCreated) ? $rs->timeCreated : time();
+               
+               ## changed format from ====0 to ====1
+               $line = "====1,$tt,$sql\n";
+               
+               if ($rs->databaseType == 'array') {
+                       $rows =& $rs->_array;
+               } else {
+                       $rows = array();
+                       while (!$rs->EOF) {     
+                               $rows[] = $rs->fields;
+                               $rs->MoveNext();
+                       } 
+               }
+               
+               for($i=0; $i < $max; $i++) {
+                       $o =& $rs->FetchField($i);
+                       $flds[] = $o;
+               }
+       
+               $savefetch = isset($rs->adodbFetchMode) ? $rs->adodbFetchMode : $rs->fetchMode;
+               $class = $rs->connection->arrayClass;
+               $rs2 = new $class();
+               $rs2->sql = $rs->sql;
+               $rs2->oldProvider = $rs->dataProvider; 
+               $rs2->InitArrayFields($rows,$flds);
+               $rs2->fetchMode = $savefetch;
+               return $line.serialize($rs2);
+       }
+
+       
+/**
+* Open CSV file and convert it into Data. 
+*
+* @param url           file/ftp/http url
+* @param err           returns the error message
+* @param timeout       dispose if recordset has been alive for $timeout secs
+*
+* @return              recordset, or false if error occured. If no
+*                      error occurred in sql INSERT/UPDATE/DELETE, 
+*                      empty recordset is returned
+*/
+       function &csv2rs($url,&$err,$timeout=0, $rsclass='ADORecordSet_array')
+       {
+               $false = false;
+               $err = false;
+               $fp = @fopen($url,'rb');
+               if (!$fp) {
+                       $err = $url.' file/URL not found';
+                       return $false;
+               }
+               @flock($fp, LOCK_SH);
+               $arr = array();
+               $ttl = 0;
+               
+               if ($meta = fgetcsv($fp, 32000, ",")) {
+                       // check if error message
+                       if (strncmp($meta[0],'****',4) === 0) {
+                               $err = trim(substr($meta[0],4,1024));
+                               fclose($fp);
+                               return $false;
+                       }
+                       // check for meta data
+                       // $meta[0] is -1 means return an empty recordset
+                       // $meta[1] contains a time 
+       
+                       if (strncmp($meta[0], '====',4) === 0) {
+                       
+                               if ($meta[0] == "====-1") {
+                                       if (sizeof($meta) < 5) {
+                                               $err = "Corrupt first line for format -1";
+                                               fclose($fp);
+                                               return $false;
+                                       }
+                                       fclose($fp);
+                                       
+                                       if ($timeout > 0) {
+                                               $err = " Illegal Timeout $timeout ";
+                                               return $false;
+                                       }
+                                       
+                                       $rs = new $rsclass($val=true);
+                                       $rs->fields = array();
+                                       $rs->timeCreated = $meta[1];
+                                       $rs->EOF = true;
+                                       $rs->_numOfFields = 0;
+                                       $rs->sql = urldecode($meta[2]);
+                                       $rs->affectedrows = (integer)$meta[3];
+                                       $rs->insertid = $meta[4];       
+                                       return $rs;
+                               } 
+                       # Under high volume loads, we want only 1 thread/process to _write_file
+                       # so that we don't have 50 processes queueing to write the same data.
+                       # We use probabilistic timeout, ahead of time.
+                       #
+                       # -4 sec before timeout, give processes 1/32 chance of timing out
+                       # -2 sec before timeout, give processes 1/16 chance of timing out
+                       # -1 sec after timeout give processes 1/4 chance of timing out
+                       # +0 sec after timeout, give processes 100% chance of timing out
+                               if (sizeof($meta) > 1) {
+                                       if($timeout >0){ 
+                                               $tdiff = (integer)( $meta[1]+$timeout - time());
+                                               if ($tdiff <= 2) {
+                                                       switch($tdiff) {
+                                                       case 4:
+                                                       case 3:
+                                                               if ((rand() & 31) == 0) {
+                                                                       fclose($fp);
+                                                                       $err = "Timeout 3";
+                                                                       return $false;
+                                                               }
+                                                               break;
+                                                       case 2: 
+                                                               if ((rand() & 15) == 0) {
+                                                                       fclose($fp);
+                                                                       $err = "Timeout 2";
+                                                                       return $false;
+                                                               }
+                                                               break;
+                                                       case 1:
+                                                               if ((rand() & 3) == 0) {
+                                                                       fclose($fp);
+                                                                       $err = "Timeout 1";
+                                                                       return $false;
+                                                               }
+                                                               break;
+                                                       default: 
+                                                               fclose($fp);
+                                                               $err = "Timeout 0";
+                                                               return $false;
+                                                       } // switch
+                                                       
+                                               } // if check flush cache
+                                       }// (timeout>0)
+                                       $ttl = $meta[1];
+                               }
+                               //================================================
+                               // new cache format - use serialize extensively...
+                               if ($meta[0] === '====1') {
+                                       // slurp in the data
+                                       $MAXSIZE = 128000;
+                                       
+                                       $text = fread($fp,$MAXSIZE);
+                                       if (strlen($text)) {
+                                               while ($txt = fread($fp,$MAXSIZE)) {
+                                                       $text .= $txt;
+                                               }
+                                       }
+                                       fclose($fp);
+                                       $rs = unserialize($text);
+                                       if (is_object($rs)) $rs->timeCreated = $ttl;
+                                       else {
+                                               $err = "Unable to unserialize recordset";
+                                               //echo htmlspecialchars($text),' !--END--!<p>';
+                                       }
+                                       return $rs;
+                               }
+                               
+                               $meta = false;
+                               $meta = fgetcsv($fp, 32000, ",");
+                               if (!$meta) {
+                                       fclose($fp);
+                                       $err = "Unexpected EOF 1";
+                                       return $false;
+                               }
+                       }
+
+                       // Get Column definitions
+                       $flds = array();
+                       foreach($meta as $o) {
+                               $o2 = explode(':',$o);
+                               if (sizeof($o2)!=3) {
+                                       $arr[] = $meta;
+                                       $flds = false;
+                                       break;
+                               }
+                               $fld = new ADOFieldObject();
+                               $fld->name = urldecode($o2[0]);
+                               $fld->type = $o2[1];
+                               $fld->max_length = $o2[2];
+                               $flds[] = $fld;
+                       }
+               } else {
+                       fclose($fp);
+                       $err = "Recordset had unexpected EOF 2";
+                       return $false;
+               }
+               
+               // slurp in the data
+               $MAXSIZE = 128000;
+               
+               $text = '';
+               while ($txt = fread($fp,$MAXSIZE)) {
+                       $text .= $txt;
+               }
+                       
+               fclose($fp);
+               @$arr = unserialize($text);
+               //var_dump($arr);
+               if (!is_array($arr)) {
+                       $err = "Recordset had unexpected EOF (in serialized recordset)";
+                       if (get_magic_quotes_runtime()) $err .= ". Magic Quotes Runtime should be disabled!";
+                       return $false;
+               }
+               $rs = new $rsclass();
+               $rs->timeCreated = $ttl;
+               $rs->InitArrayFields($arr,$flds);
+               return $rs;
+       }
+       
+
+       /**
+       * Save a file $filename and its $contents (normally for caching) with file locking
+       */
+       function adodb_write_file($filename, $contents,$debug=false)
+       { 
+       # http://www.php.net/bugs.php?id=9203 Bug that flock fails on Windows
+       # So to simulate locking, we assume that rename is an atomic operation.
+       # First we delete $filename, then we create a $tempfile write to it and 
+       # rename to the desired $filename. If the rename works, then we successfully 
+       # modified the file exclusively.
+       # What a stupid need - having to simulate locking.
+       # Risks:
+       # 1. $tempfile name is not unique -- very very low
+       # 2. unlink($filename) fails -- ok, rename will fail
+       # 3. adodb reads stale file because unlink fails -- ok, $rs timeout occurs
+       # 4. another process creates $filename between unlink() and rename() -- ok, rename() fails and  cache updated
+               if (strncmp(PHP_OS,'WIN',3) === 0) {
+                       // skip the decimal place
+                       $mtime = substr(str_replace(' ','_',microtime()),2); 
+                       // getmypid() actually returns 0 on Win98 - never mind!
+                       $tmpname = $filename.uniqid($mtime).getmypid();
+                       if (!($fd = @fopen($tmpname,'a'))) return false;
+                       $ok = ftruncate($fd,0);                 
+                       if (!fwrite($fd,$contents)) $ok = false;
+                       fclose($fd);
+                       chmod($tmpname,0644);
+                       // the tricky moment
+                       @unlink($filename);
+                       if (!@rename($tmpname,$filename)) {
+                               unlink($tmpname);
+                               $ok = false;
+                       }
+                       if (!$ok) {
+                               if ($debug) ADOConnection::outp( " Rename $tmpname ".($ok? 'ok' : 'failed'));
+                       }
+                       return $ok;
+               }
+               if (!($fd = @fopen($filename, 'a'))) return false;
+               if (flock($fd, LOCK_EX) && ftruncate($fd, 0)) {
+                       $ok = fwrite( $fd, $contents );
+                       fclose($fd);
+                       chmod($filename,0644);
+               }else {
+                       fclose($fd);
+                       if ($debug)ADOConnection::outp( " Failed acquiring lock for $filename<br>\n");
+                       $ok = false;
+               }
+       
+               return $ok;
+       }
+?>
\ No newline at end of file
diff --git a/typo3/sysext/adodb/adodb/adodb-datadict.inc.php b/typo3/sysext/adodb/adodb/adodb-datadict.inc.php
new file mode 100644 (file)
index 0000000..d7014b6
--- /dev/null
@@ -0,0 +1,783 @@
+<?php
+
+/**
+  V4.68 25 Nov 2005  (c) 2000-2005 John Lim (jlim@natsoft.com.my). All rights reserved.
+  Released under both BSD license and Lesser GPL library license. 
+  Whenever there is any discrepancy between the two licenses, 
+  the BSD license will take precedence.
+       
+  Set tabs to 4 for best viewing.
+       DOCUMENTATION:
+       
+               See adodb/tests/test-datadict.php for docs and examples.
+*/
+
+/*
+       Test script for parser
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+function Lens_ParseTest()
+{
+$str = "`zcol ACOL` NUMBER(32,2) DEFAULT 'The \"cow\" (and Jim''s dog) jumps over the moon' PRIMARY, INTI INT AUTO DEFAULT 0, zcol2\"afs ds";
+print "<p>$str</p>";
+$a= Lens_ParseArgs($str);
+print "<pre>";
+print_r($a);
+print "</pre>";
+}
+
+
+if (!function_exists('ctype_alnum')) {
+       function ctype_alnum($text) {
+               return preg_match('/^[a-z0-9]*$/i', $text);
+       }
+}
+
+//Lens_ParseTest();
+
+/**
+       Parse arguments, treat "text" (text) and 'text' as quotation marks.
+       To escape, use "" or '' or ))
+       
+       Will read in "abc def" sans quotes, as: abc def
+       Same with 'abc def'.
+       However if `abc def`, then will read in as `abc def`
+       
+       @param endstmtchar    Character that indicates end of statement
+       @param tokenchars     Include the following characters in tokens apart from A-Z and 0-9 
+       @returns 2 dimensional array containing parsed tokens.
+*/
+function Lens_ParseArgs($args,$endstmtchar=',',$tokenchars='_.-')
+{
+       $pos = 0;
+       $intoken = false;
+       $stmtno = 0;
+       $endquote = false;
+       $tokens = array();
+       $tokens[$stmtno] = array();
+       $max = strlen($args);
+       $quoted = false;
+       
+       while ($pos < $max) {
+               $ch = substr($args,$pos,1);
+               switch($ch) {
+               case ' ':
+               case "\t":
+               case "\n":
+               case "\r":
+                       if (!$quoted) {
+                               if ($intoken) {
+                                       $intoken = false;
+                                       $tokens[$stmtno][] = implode('',$tokarr);
+                               }
+                               break;
+                       }
+                       
+                       $tokarr[] = $ch;
+                       break;
+               
+               case '`':
+                       if ($intoken) $tokarr[] = $ch;
+               case '(':
+               case ')':       
+               case '"':
+               case "'":
+                       
+                       if ($intoken) {
+                               if (empty($endquote)) {
+                                       $tokens[$stmtno][] = implode('',$tokarr);
+                                       if ($ch == '(') $endquote = ')';
+                                       else $endquote = $ch;
+                                       $quoted = true;
+                                       $intoken = true;
+                                       $tokarr = array();
+                               } else if ($endquote == $ch) {
+                                       $ch2 = substr($args,$pos+1,1);
+                                       if ($ch2 == $endquote) {
+                                               $pos += 1;
+                                               $tokarr[] = $ch2;
+                                       } else {
+                                               $quoted = false;
+                                               $intoken = false;
+                                               $tokens[$stmtno][] = implode('',$tokarr);
+                                               $endquote = '';
+                                       }
+                               } else
+                                       $tokarr[] = $ch;
+                                       
+                       }else {
+                       
+                               if ($ch == '(') $endquote = ')';
+                               else $endquote = $ch;
+                               $quoted = true;
+                               $intoken = true;
+                               $tokarr = array();
+                               if ($ch == '`') $tokarr[] = '`';
+                       }
+                       break;
+                       
+               default:
+                       
+                       if (!$intoken) {
+                               if ($ch == $endstmtchar) {
+                                       $stmtno += 1;
+                                       $tokens[$stmtno] = array();
+                                       break;
+                               }
+                       
+                               $intoken = true;
+                               $quoted = false;
+                               $endquote = false;
+                               $tokarr = array();
+       
+                       }
+                       
+                       if ($quoted) $tokarr[] = $ch;
+                       else if (ctype_alnum($ch) || strpos($tokenchars,$ch) !== false) $tokarr[] = $ch;
+                       else {
+                               if ($ch == $endstmtchar) {                      
+                                       $tokens[$stmtno][] = implode('',$tokarr);
+                                       $stmtno += 1;
+                                       $tokens[$stmtno] = array();
+                                       $intoken = false;
+                                       $tokarr = array();
+                                       break;
+                               }
+                               $tokens[$stmtno][] = implode('',$tokarr);
+                               $tokens[$stmtno][] = $ch;
+                               $intoken = false;
+                       }
+               }
+               $pos += 1;
+       }
+       if ($intoken) $tokens[$stmtno][] = implode('',$tokarr);
+       
+       return $tokens;
+}
+
+
+class ADODB_DataDict {
+       var $connection;
+       var $debug = false;
+       var $dropTable = 'DROP TABLE %s';
+       var $renameTable = 'RENAME TABLE %s TO %s'; 
+       var $dropIndex = 'DROP INDEX %s';
+       var $addCol = ' ADD';
+       var $alterCol = ' ALTER COLUMN';
+       var $dropCol = ' DROP COLUMN';
+       var $renameColumn = 'ALTER TABLE %s RENAME COLUMN %s TO %s';    // table, old-column, new-column, column-definitions (not used by default)
+       var $nameRegex = '\w';
+       var $nameRegexBrackets = 'a-zA-Z0-9_\(\)';
+       var $schema = false;
+       var $serverInfo = array();
+       var $autoIncrement = false;
+       var $dataProvider;
+       var $invalidResizeTypes4 = array('CLOB','BLOB','TEXT','DATE','TIME'); // for changetablesql
+       var $blobSize = 100;    /// any varchar/char field this size or greater is treated as a blob
+                                                       /// in other words, we use a text area for editting.
+       
+       function GetCommentSQL($table,$col)
+       {
+               return false;
+       }
+       
+       function SetCommentSQL($table,$col,$cmt)
+       {
+               return false;
+       }
+       
+       function MetaTables()
+       {
+               if (!$this->connection->IsConnected()) return array();
+               return $this->connection->MetaTables();
+       }
+       
+       function MetaColumns($tab, $upper=true, $schema=false)
+       {
+               if (!$this->connection->IsConnected()) return array();
+               return $this->connection->MetaColumns($this->TableName($tab), $upper, $schema);
+       }
+       
+       function MetaPrimaryKeys($tab,$owner=false,$intkey=false)
+       {
+               if (!$this->connection->IsConnected()) return array();
+               return $this->connection->MetaPrimaryKeys($this->TableName($tab), $owner, $intkey);
+       }
+       
+       function MetaIndexes($table, $primary = false, $owner = false)
+       {
+               if (!$this->connection->IsConnected()) return array();
+               return $this->connection->MetaIndexes($this->TableName($table), $primary, $owner);
+       }
+       
+       function MetaType($t,$len=-1,$fieldobj=false)
+       {
+               return ADORecordSet::MetaType($t,$len,$fieldobj);
+       }
+       
+       function NameQuote($name = NULL,$allowBrackets=false)
+       {
+               if (!is_string($name)) {
+                       return FALSE;
+               }
+               
+               $name = trim($name);
+               
+               if ( !is_object($this->connection) ) {
+                       return $name;
+               }
+               
+               $quote = $this->connection->nameQuote;
+               
+               // if name is of the form `name`, quote it
+               if ( preg_match('/^`(.+)`$/', $name, $matches) ) {
+                       return $quote . $matches[1] . $quote;
+               }
+               
+               // if name contains special characters, quote it
+               $regex = ($allowBrackets) ? $this->nameRegexBrackets : $this->nameRegex;
+               
+               if ( !preg_match('/^[' . $regex . ']+$/', $name) ) {
+                       return $quote . $name . $quote;
+               }
+               
+               return $name;
+       }
+       
+       function TableName($name)
+       {
+               if ( $this->schema ) {
+                       return $this->NameQuote($this->schema) .'.'. $this->NameQuote($name);
+               }
+               return $this->NameQuote($name);
+       }
+       
+       // Executes the sql array returned by GetTableSQL and GetIndexSQL
+       function ExecuteSQLArray($sql, $continueOnError = true)
+       {
+               $rez = 2;
+               $conn = &$this->connection;
+               $saved = $conn->debug;
+               foreach($sql as $line) {
+                       
+                       if ($this->debug) $conn->debug = true;
+                       $ok = $conn->Execute($line);
+                       $conn->debug = $saved;
+                       if (!$ok) {
+                               if ($this->debug) ADOConnection::outp($conn->ErrorMsg());
+                               if (!$continueOnError) return 0;
+                               $rez = 1;
+                       }
+               }
+               return $rez;
+       }
+       
+       /*
+               Returns the actual type given a character code.
+               
+               C:  varchar
+               X:  CLOB (character large object) or largest varchar size if CLOB is not supported
+               C2: Multibyte varchar
+               X2: Multibyte CLOB
+               
+               B:  BLOB (binary large object)
+               
+               D:  Date
+               T:  Date-time 
+               L:  Integer field suitable for storing booleans (0 or 1)
+               I:  Integer
+               F:  Floating point number
+               N:  Numeric or decimal number
+       */
+       
+       function ActualType($meta)
+       {
+               return $meta;
+       }
+       
+       function CreateDatabase($dbname,$options=false)
+       {
+               $options = $this->_Options($options);
+               $sql = array();
+               
+               $s = 'CREATE DATABASE ' . $this->NameQuote($dbname);
+               if (isset($options[$this->upperName]))
+                       $s .= ' '.$options[$this->upperName];
+               
+               $sql[] = $s;
+               return $sql;
+       }
+       
+       /*
+        Generates the SQL to create index. Returns an array of sql strings.
+       */
+       function CreateIndexSQL($idxname, $tabname, $flds, $idxoptions = false)
+       {
+               if (!is_array($flds)) {
+                       $flds = explode(',',$flds);
+               }
+               
+               foreach($flds as $key => $fld) {
+                       # some indexes can use partial fields, eg. index first 32 chars of "name" with NAME(32)
+                       $flds[$key] = $this->NameQuote($fld,$allowBrackets=true);
+               }
+               
+               return $this->_IndexSQL($this->NameQuote($idxname), $this->TableName($tabname), $flds, $this->_Options($idxoptions));
+       }
+       
+       function DropIndexSQL ($idxname, $tabname = NULL)
+       {
+               return array(sprintf($this->dropIndex, $this->NameQuote($idxname), $this->TableName($tabname)));
+       }
+       
+       function SetSchema($schema)
+       {
+               $this->schema = $schema;
+       }
+       
+       function AddColumnSQL($tabname, $flds)
+       {
+               $tabname = $this->TableName ($tabname);
+               $sql = array();
+               list($lines,$pkey) = $this->_GenFields($flds);
+               $alter = 'ALTER TABLE ' . $tabname . $this->addCol . ' ';
+               foreach($lines as $v) {
+                       $sql[] = $alter . $v;
+               }
+               return $sql;
+       }
+       
+       /**
+        * Change the definition of one column
+        *
+        * As some DBM's can't do that on there own, you need to supply the complete defintion of the new table,
+        * to allow, recreating the table and copying the content over to the new table
+        * @param string $tabname table-name
+        * @param string $flds column-name and type for the changed column
+        * @param string $tableflds='' complete defintion of the new table, eg. for postgres, default ''
+        * @param array/string $tableoptions='' options for the new table see CreateTableSQL, default ''
+        * @return array with SQL strings
+        */
+       function AlterColumnSQL($tabname, $flds, $tableflds='',$tableoptions='')
+       {
+               $tabname = $this->TableName ($tabname);
+               $sql = array();
+               list($lines,$pkey) = $this->_GenFields($flds);
+               $alter = 'ALTER TABLE ' . $tabname . $this->alterCol . ' ';
+               foreach($lines as $v) {
+                       $sql[] = $alter . $v;
+               }
+               return $sql;
+       }
+       
+       /**
+        * Rename one column
+        *
+        * Some DBM's can only do this together with changeing the type of the column (even if that stays the same, eg. mysql)
+        * @param string $tabname table-name
+        * @param string $oldcolumn column-name to be renamed
+        * @param string $newcolumn new column-name
+        * @param string $flds='' complete column-defintion-string like for AddColumnSQL, only used by mysql atm., default=''
+        * @return array with SQL strings
+        */
+       function RenameColumnSQL($tabname,$oldcolumn,$newcolumn,$flds='')
+       {
+               $tabname = $this->TableName ($tabname);
+               if ($flds) {
+                       list($lines,$pkey) = $this->_GenFields($flds);
+                       list(,$first) = each($lines);
+                       list(,$column_def) = split("[\t ]+",$first,2);
+               }
+               return array(sprintf($this->renameColumn,$tabname,$this->NameQuote($oldcolumn),$this->NameQuote($newcolumn),$column_def));
+       }
+               
+       /**
+        * Drop one column
+        *
+        * Some DBM's can't do that on there own, you need to supply the complete defintion of the new table,
+        * to allow, recreating the table and copying the content over to the new table
+        * @param string $tabname table-name
+        * @param string $flds column-name and type for the changed column
+        * @param string $tableflds='' complete defintion of the new table, eg. for postgres, default ''
+        * @param array/string $tableoptions='' options for the new table see CreateTableSQL, default ''
+        * @return array with SQL strings
+        */
+       function DropColumnSQL($tabname, $flds, $tableflds='',$tableoptions='')
+       {
+               $tabname = $this->TableName ($tabname);
+               if (!is_array($flds)) $flds = explode(',',$flds);
+               $sql = array();
+               $alter = 'ALTER TABLE ' . $tabname . $this->dropCol . ' ';
+               foreach($flds as $v) {
+                       $sql[] = $alter . $this->NameQuote($v);
+               }
+               return $sql;
+       }
+       
+       function DropTableSQL($tabname)
+       {
+               return array (sprintf($this->dropTable, $this->TableName($tabname)));
+       }
+       
+       function RenameTableSQL($tabname,$newname)
+       {
+               return array (sprintf($this->renameTable, $this->TableName($tabname),$this->TableName($newname)));
+       }       
+       
+       /*
+        Generate the SQL to create table. Returns an array of sql strings.
+       */
+       function CreateTableSQL($tabname, $flds, $tableoptions=false)
+       {
+               if (!$tableoptions) $tableoptions = array();
+               
+               list($lines,$pkey) = $this->_GenFields($flds, true);
+               
+               $taboptions = $this->_Options($tableoptions);
+               $tabname = $this->TableName ($tabname);
+               $sql = $this->_TableSQL($tabname,$lines,$pkey,$taboptions);
+               
+               $tsql = $this->_Triggers($tabname,$taboptions);
+               foreach($tsql as $s) $sql[] = $s;
+               
+               return $sql;
+       }
+       
+       function _GenFields($flds,$widespacing=false)
+       {
+               if (is_string($flds)) {
+                       $padding = '     ';
+                       $txt = $flds.$padding;
+                       $flds = array();
+                       $flds0 = Lens_ParseArgs($txt,',');
+                       $hasparam = false;
+                       foreach($flds0 as $f0) {
+                               $f1 = array();
+                               foreach($f0 as $token) {
+                                       switch (strtoupper($token)) {
+                                       case 'CONSTRAINT':
+                                       case 'DEFAULT': 
+                                               $hasparam = $token;
+                                               break;
+                                       default:
+                                               if ($hasparam) $f1[$hasparam] = $token;
+                                               else $f1[] = $token;
+                                               $hasparam = false;
+                                               break;
+                                       }
+                               }
+                               $flds[] = $f1;
+                               
+                       }
+               }
+               $this->autoIncrement = false;
+               $lines = array();
+               $pkey = array();
+               foreach($flds as $fld) {
+                       $fld = _array_change_key_case($fld);
+               
+                       $fname = false;
+                       $fdefault = false;
+                       $fautoinc = false;
+                       $ftype = false;
+                       $fsize = false;
+                       $fprec = false;
+                       $fprimary = false;
+                       $fnoquote = false;
+                       $fdefts = false;
+                       $fdefdate = false;
+                       $fconstraint = false;
+                       $fnotnull = false;
+                       $funsigned = false;
+                       
+                       //-----------------
+                       // Parse attributes
+                       foreach($fld as $attr => $v) {
+                               if ($attr == 2 && is_numeric($v)) $attr = 'SIZE';
+                               else if (is_numeric($attr) && $attr > 1 && !is_numeric($v)) $attr = strtoupper($v);
+                               
+                               switch($attr) {
+                               case '0':
+                               case 'NAME':    $fname = $v; break;
+                               case '1':
+                               case 'TYPE':    $ty = $v; $ftype = $this->ActualType(strtoupper($v)); break;
+                               
+                               case 'SIZE':    
+                                                               $dotat = strpos($v,'.'); if ($dotat === false) $dotat = strpos($v,',');
+                                                               if ($dotat === false) $fsize = $v;
+                                                               else {
+                                                                       $fsize = substr($v,0,$dotat);
+                                                                       $fprec = substr($v,$dotat+1);
+                                                               }
+                                                               break;
+                               case 'UNSIGNED': $funsigned = true; break;
+                               case 'AUTOINCREMENT':
+                               case 'AUTO':    $fautoinc = true; $fnotnull = true; break;
+                               case 'KEY':
+                               case 'PRIMARY': $fprimary = $v; $fnotnull = true; break;
+                               case 'DEF':
+                               case 'DEFAULT': $fdefault = $v; break;
+                               case 'NOTNULL': $fnotnull = $v; break;
+                               case 'NOQUOTE': $fnoquote = $v; break;
+                               case 'DEFDATE': $fdefdate = $v; break;
+                               case 'DEFTIMESTAMP': $fdefts = $v; break;
+                               case 'CONSTRAINT': $fconstraint = $v; break;
+                               } //switch
+                       } // foreach $fld
+                       
+                       //--------------------
+                       // VALIDATE FIELD INFO
+                       if (!strlen($fname)) {
+                               if ($this->debug) ADOConnection::outp("Undefined NAME");
+                               return false;
+                       }
+                       
+                       $fid = strtoupper(preg_replace('/^`(.+)`$/', '$1', $fname));
+                       $fname = $this->NameQuote($fname);
+                       
+                       if (!strlen($ftype)) {
+                               if ($this->debug) ADOConnection::outp("Undefined TYPE for field '$fname'");
+                               return false;
+                       } else {
+                               $ftype = strtoupper($ftype);
+                       }
+                       
+                       $ftype = $this->_GetSize($ftype, $ty, $fsize, $fprec);
+                       
+                       if ($ty == 'X' || $ty == 'X2' || $ty == 'B') $fnotnull = false; // some blob types do not accept nulls
+                       
+                       if ($fprimary) $pkey[] = $fname;
+                       
+                       // some databases do not allow blobs to have defaults
+                       if ($ty == 'X') $fdefault = false;
+                       
+                       //--------------------
+                       // CONSTRUCT FIELD SQL
+                       if ($fdefts) {
+                               if (substr($this->connection->databaseType,0,5) == 'mysql') {
+                                       $ftype = 'TIMESTAMP';
+                               } else {
+                                       $fdefault = $this->connection->sysTimeStamp;
+                               }
+                       } else if ($fdefdate) {
+                               if (substr($this->connection->databaseType,0,5) == 'mysql') {
+                                       $ftype = 'TIMESTAMP';
+                               } else {
+                                       $fdefault = $this->connection->sysDate;
+                               }
+                       } else if ($fdefault !== false && !$fnoquote)
+                               if ($ty == 'C' or $ty == 'X' or 
+                                       ( substr($fdefault,0,1) != "'" && !is_numeric($fdefault)))
+                                       if (strlen($fdefault) != 1 && substr($fdefault,0,1) == ' ' && substr($fdefault,strlen($fdefault)-1) == ' ') 
+                                               $fdefault = trim($fdefault);
+                                       else if (strtolower($fdefault) != 'null')
+                                               $fdefault = $this->connection->qstr($fdefault);
+                       $suffix = $this->_CreateSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned);
+                       
+                       if ($widespacing) $fname = str_pad($fname,24);
+                       $lines[$fid] = $fname.' '.$ftype.$suffix;
+                       
+                       if ($fautoinc) $this->autoIncrement = true;
+               } // foreach $flds
+               
+               return array($lines,$pkey);
+       }
+       /*
+                GENERATE THE SIZE PART OF THE DATATYPE
+                       $ftype is the actual type
+                       $ty is the type defined originally in the DDL
+       */
+       function _GetSize($ftype, $ty, $fsize, $fprec)
+       {
+               if (strlen($fsize) && $ty != 'X' && $ty != 'B' && strpos($ftype,'(') === false) {
+                       $ftype .= "(".$fsize;
+                       if (strlen($fprec)) $ftype .= ",".$fprec;
+                       $ftype .= ')';
+               }
+               return $ftype;
+       }
+       
+       
+       // return string must begin with space
+       function _CreateSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint)
+       {       
+               $suffix = '';
+               if (strlen($fdefault)) $suffix .= " DEFAULT $fdefault";
+               if ($fnotnull) $suffix .= ' NOT NULL';
+               if ($fconstraint) $suffix .= ' '.$fconstraint;
+               return $suffix;
+       }
+       
+       function _IndexSQL($idxname, $tabname, $flds, $idxoptions)
+       {
+               $sql = array();
+               
+               if ( isset($idxoptions['REPLACE']) || isset($idxoptions['DROP']) ) {
+                       $sql[] = sprintf ($this->dropIndex, $idxname);
+                       if ( isset($idxoptions['DROP']) )
+                               return $sql;
+               }
+               
+               if ( empty ($flds) ) {
+                       return $sql;
+               }
+               
+               $unique = isset($idxoptions['UNIQUE']) ? ' UNIQUE' : '';
+       
+               $s = 'CREATE' . $unique . ' INDEX ' . $idxname . ' ON ' . $tabname . ' ';
+               
+               if ( isset($idxoptions[$this->upperName]) )
+                       $s .= $idxoptions[$this->upperName];
+               
+               if ( is_array($flds) )
+                       $flds = implode(', ',$flds);
+               $s .= '(' . $flds . ')';
+               $sql[] = $s;
+               
+               return $sql;
+       }
+       
+       function _DropAutoIncrement($tabname)
+       {
+               return false;
+       }
+       
+       function _TableSQL($tabname,$lines,$pkey,$tableoptions)
+       {
+               $sql = array();
+               
+               if (isset($tableoptions['REPLACE']) || isset ($tableoptions['DROP'])) {
+                       $sql[] = sprintf($this->dropTable,$tabname);
+                       if ($this->autoIncrement) {
+                               $sInc = $this->_DropAutoIncrement($tabname);
+                               if ($sInc) $sql[] = $sInc;
+                       }
+                       if ( isset ($tableoptions['DROP']) ) {
+                               return $sql;
+                       }
+               }
+               $s = "CREATE TABLE $tabname (\n";
+               $s .= implode(",\n", $lines);
+               if (sizeof($pkey)>0) {
+                       $s .= ",\n                 PRIMARY KEY (";
+                       $s .= implode(", ",$pkey).")";
+               }
+               if (isset($tableoptions['CONSTRAINTS'])) 
+                       $s .= "\n".$tableoptions['CONSTRAINTS'];
+               
+               if (isset($tableoptions[$this->upperName.'_CONSTRAINTS'])) 
+                       $s .= "\n".$tableoptions[$this->upperName.'_CONSTRAINTS'];
+               
+               $s .= "\n)";
+               if (isset($tableoptions[$this->upperName])) $s .= $tableoptions[$this->upperName];
+               $sql[] = $s;
+               
+               return $sql;
+       }
+       
+       /*
+               GENERATE TRIGGERS IF NEEDED
+               used when table has auto-incrementing field that is emulated using triggers
+       */
+       function _Triggers($tabname,$taboptions)
+       {
+               return array();
+       }
+       
+       /*
+               Sanitize options, so that array elements with no keys are promoted to keys
+       */
+       function _Options($opts)
+       {
+               if (!is_array($opts)) return array();
+               $newopts = array();
+               foreach($opts as $k => $v) {
+                       if (is_numeric($k)) $newopts[strtoupper($v)] = $v;
+                       else $newopts[strtoupper($k)] = $v;
+               }
+               return $newopts;
+       }
+       
+       /*
+       "Florian Buzin [ easywe ]" <florian.buzin#easywe.de>
+       
+       This function changes/adds new fields to your table. You don't
+       have to know if the col is new or not. It will check on its own.
+       */
+       function ChangeTableSQL($tablename, $flds, $tableoptions = false)
+       {
+       global $ADODB_FETCH_MODE;
+       
+               $save = $ADODB_FETCH_MODE;
+               $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
+               if ($this->connection->fetchMode !== false) $savem = $this->connection->SetFetchMode(false);
+               
+               // check table exists
+               $save_handler = $this->connection->raiseErrorFn;
+               $this->connection->raiseErrorFn = '';
+               $cols = $this->MetaColumns($tablename);
+               $this->connection->raiseErrorFn = $save_handler;
+               
+               if (isset($savem)) $this->connection->SetFetchMode($savem);
+               $ADODB_FETCH_MODE = $save;
+               
+               if ( empty($cols)) { 
+                       return $this->CreateTableSQL($tablename, $flds, $tableoptions);
+               }
+               
+               if (is_array($flds)) {
+               // Cycle through the update fields, comparing
+               // existing fields to fields to update.
+               // if the Metatype and size is exactly the
+               // same, ignore - by Mark Newham
+                       $holdflds = array();
+                       foreach($flds as $k=>$v) {
+                               if ( isset($cols[$k]) && is_object($cols[$k]) ) {
+                                       // If already not allowing nulls, then don't change
+                                       $obj = $cols[$k];
+                                       if (isset($obj->not_null) && $obj->not_null)
+                                               $v = str_replace('NOT NULL','',$v);
+
+                                       $c = $cols[$k];
+                                       $ml = $c->max_length;
+                                       $mt = $this->MetaType($c->type,$ml);
+                                       if ($ml == -1) $ml = '';
+                                       if ($mt == 'X') $ml = $v['SIZE'];
+                                       if (($mt != $v['TYPE']) ||  $ml != $v['SIZE']) {
+                                               $holdflds[$k] = $v;
+                                       }
+                               } else {
+                                       $holdflds[$k] = $v;
+                               }               
+                       }
+                       $flds = $holdflds;
+               }
+       
+
+               // already exists, alter table instead
+               list($lines,$pkey) = $this->_GenFields($flds);
+               $alter = 'ALTER TABLE ' . $this->TableName($tablename);
+               $sql = array();
+
+               foreach ( $lines as $id => $v ) {
+                       if ( isset($cols[$id]) && is_object($cols[$id]) ) {
+                       
+                               $flds = Lens_ParseArgs($v,',');
+                               
+                               //  We are trying to change the size of the field, if not allowed, simply ignore the request.
+                               if ($flds && in_array(strtoupper(substr($flds[0][1],0,4)),$this->invalidResizeTypes4)) continue;         
+                       
+                               $sql[] = $alter . $this->alterCol . ' ' . $v;
+                       } else {
+                               $sql[] = $alter . $this->addCol . ' ' . $v;
+                       }
+               }
+               
+               return $sql;
+       }
+} // class
+?>
\ No newline at end of file
diff --git a/typo3/sysext/adodb/adodb/adodb-error.inc.php b/typo3/sysext/adodb/adodb/adodb-error.inc.php
new file mode 100644 (file)
index 0000000..ad9973a
--- /dev/null
@@ -0,0 +1,258 @@
+<?php
+/** 
+ * @version V4.68 25 Nov 2005 (c) 2000-2005 John Lim (jlim@natsoft.com.my). All rights reserved.
+ * Released under both BSD license and Lesser GPL library license. 
+ * Whenever there is any discrepancy between the two licenses, 
+ * the BSD license will take precedence. 
+ *
+ * Set tabs to 4 for best viewing.
+ * 
+ * The following code is adapted from the PEAR DB error handling code.
+ * Portions (c)1997-2002 The PHP Group.
+ */
+
+
+if (!defined("DB_ERROR")) define("DB_ERROR",-1);
+
+if (!defined("DB_ERROR_SYNTAX")) {
+       define("DB_ERROR_SYNTAX",              -2);
+       define("DB_ERROR_CONSTRAINT",          -3);
+       define("DB_ERROR_NOT_FOUND",           -4);
+       define("DB_ERROR_ALREADY_EXISTS",      -5);
+       define("DB_ERROR_UNSUPPORTED",         -6);
+       define("DB_ERROR_MISMATCH",            -7);
+       define("DB_ERROR_INVALID",             -8);
+       define("DB_ERROR_NOT_CAPABLE",         -9);
+       define("DB_ERROR_TRUNCATED",          -10);
+       define("DB_ERROR_INVALID_NUMBER",     -11);
+       define("DB_ERROR_INVALID_DATE",       -12);
+       define("DB_ERROR_DIVZERO",            -13);
+       define("DB_ERROR_NODBSELECTED",       -14);
+       define("DB_ERROR_CANNOT_CREATE",      -15);
+       define("DB_ERROR_CANNOT_DELETE",      -16);
+       define("DB_ERROR_CANNOT_DROP",        -17);
+       define("DB_ERROR_NOSUCHTABLE",        -18);
+       define("DB_ERROR_NOSUCHFIELD",        -19);
+       define("DB_ERROR_NEED_MORE_DATA",     -20);
+       define("DB_ERROR_NOT_LOCKED",         -21);
+       define("DB_ERROR_VALUE_COUNT_ON_ROW", -22);
+       define("DB_ERROR_INVALID_DSN",        -23);
+       define("DB_ERROR_CONNECT_FAILED",     -24);
+       define("DB_ERROR_EXTENSION_NOT_FOUND",-25);
+       define("DB_ERROR_NOSUCHDB",           -25);
+       define("DB_ERROR_ACCESS_VIOLATION",   -26);
+}
+
+function adodb_errormsg($value)
+{
+global $ADODB_LANG,$ADODB_LANG_ARRAY;
+
+       if (empty($ADODB_LANG)) $ADODB_LANG = 'en';
+       if (isset($ADODB_LANG_ARRAY['LANG']) && $ADODB_LANG_ARRAY['LANG'] == $ADODB_LANG) ;
+       else {
+               include_once(ADODB_DIR."/lang/adodb-$ADODB_LANG.inc.php");
+    }
+       return isset($ADODB_LANG_ARRAY[$value]) ? $ADODB_LANG_ARRAY[$value] : $ADODB_LANG_ARRAY[DB_ERROR];
+}
+
+function adodb_error($provider,$dbType,$errno)
+{
+       //var_dump($errno);
+       if (is_numeric($errno) && $errno == 0) return 0;
+       switch($provider) { 
+       case 'mysql': $map = adodb_error_mysql(); break;
+       
+       case 'oracle':
+       case 'oci8': $map = adodb_error_oci8(); break;
+       
+       case 'ibase': $map = adodb_error_ibase(); break;
+       
+       case 'odbc': $map = adodb_error_odbc(); break;
+       
+       case 'mssql':
+       case 'sybase': $map = adodb_error_mssql(); break;
+       
+       case 'informix': $map = adodb_error_ifx(); break;
+       
+       case 'postgres': return adodb_error_pg($errno); break;
+       
+       case 'sqlite': return $map = adodb_error_sqlite(); break;
+       default:
+               return DB_ERROR;
+       }       
+       //print_r($map);
+       //var_dump($errno);
+       if (isset($map[$errno])) return $map[$errno];
+       return DB_ERROR;
+}
+
+//**************************************************************************************
+
+function adodb_error_pg($errormsg)
+{
+       if (is_numeric($errormsg)) return (integer) $errormsg;
+    static $error_regexps = array(
+            '/(Table does not exist\.|Relation [\"\'].*[\"\'] does not exist|sequence does not exist|class ".+" not found)$/' => DB_ERROR_NOSUCHTABLE,
+            '/Relation [\"\'].*[\"\'] already exists|Cannot insert a duplicate key into (a )?unique index.*/'      => DB_ERROR_ALREADY_EXISTS,
+            '/divide by zero$/'                     => DB_ERROR_DIVZERO,
+            '/pg_atoi: error in .*: can\'t parse /' => DB_ERROR_INVALID_NUMBER,
+            '/ttribute [\"\'].*[\"\'] not found|Relation [\"\'].*[\"\'] does not have attribute [\"\'].*[\"\']/' => DB_ERROR_NOSUCHFIELD,
+            '/parser: parse error at or near \"/'   => DB_ERROR_SYNTAX,
+            '/referential integrity violation/'     => DB_ERROR_CONSTRAINT,
+                       '/Relation [\"\'].*[\"\'] already exists|Cannot insert a duplicate key into (a )?unique index.*|duplicate key violates unique constraint/'     
+                                => DB_ERROR_ALREADY_EXISTS
+        );
+       reset($error_regexps);
+    while (list($regexp,$code) = each($error_regexps)) {
+        if (preg_match($regexp, $errormsg)) {
+            return $code;
+        }
+    }
+    // Fall back to DB_ERROR if there was no mapping.
+    return DB_ERROR;
+}
+       
+function adodb_error_odbc()
+{
+static $MAP = array(
+            '01004' => DB_ERROR_TRUNCATED,
+            '07001' => DB_ERROR_MISMATCH,
+            '21S01' => DB_ERROR_MISMATCH,
+            '21S02' => DB_ERROR_MISMATCH,
+            '22003' => DB_ERROR_INVALID_NUMBER,
+            '22008' => DB_ERROR_INVALID_DATE,
+            '22012' => DB_ERROR_DIVZERO,
+            '23000' => DB_ERROR_CONSTRAINT,
+            '24000' => DB_ERROR_INVALID,
+            '34000' => DB_ERROR_INVALID,
+            '37000' => DB_ERROR_SYNTAX,
+            '42000' => DB_ERROR_SYNTAX,
+            'IM001' => DB_ERROR_UNSUPPORTED,
+            'S0000' => DB_ERROR_NOSUCHTABLE,
+            'S0001' => DB_ERROR_NOT_FOUND,
+            'S0002' => DB_ERROR_NOSUCHTABLE,
+            'S0011' => DB_ERROR_ALREADY_EXISTS,
+            'S0012' => DB_ERROR_NOT_FOUND,
+            'S0021' => DB_ERROR_ALREADY_EXISTS,
+            'S0022' => DB_ERROR_NOT_FOUND,
+                       'S1000' => DB_ERROR_NOSUCHTABLE,
+            'S1009' => DB_ERROR_INVALID,
+            'S1090' => DB_ERROR_INVALID,
+            'S1C00' => DB_ERROR_NOT_CAPABLE
+        );
+               return $MAP;
+}
+
+function adodb_error_ibase()
+{
+static $MAP = array(
+            -104 => DB_ERROR_SYNTAX,
+            -150 => DB_ERROR_ACCESS_VIOLATION,
+            -151 => DB_ERROR_ACCESS_VIOLATION,
+            -155 => DB_ERROR_NOSUCHTABLE,
+            -157 => DB_ERROR_NOSUCHFIELD,
+            -158 => DB_ERROR_VALUE_COUNT_ON_ROW,
+            -170 => DB_ERROR_MISMATCH,
+            -171 => DB_ERROR_MISMATCH,
+            -172 => DB_ERROR_INVALID,
+            -204 => DB_ERROR_INVALID,
+            -205 => DB_ERROR_NOSUCHFIELD,
+            -206 => DB_ERROR_NOSUCHFIELD,
+            -208 => DB_ERROR_INVALID,
+            -219 => DB_ERROR_NOSUCHTABLE,
+            -297 => DB_ERROR_CONSTRAINT,
+            -530 => DB_ERROR_CONSTRAINT,
+            -803 => DB_ERROR_CONSTRAINT,
+            -551 => DB_ERROR_ACCESS_VIOLATION,
+            -552 => DB_ERROR_ACCESS_VIOLATION,
+            -922 => DB_ERROR_NOSUCHDB,
+            -923 => DB_ERROR_CONNECT_FAILED,
+            -924 => DB_ERROR_CONNECT_FAILED
+        );
+               
+               return $MAP;
+}
+
+function adodb_error_ifx()
+{
+static $MAP = array(
+            '-201'    => DB_ERROR_SYNTAX,
+            '-206'    => DB_ERROR_NOSUCHTABLE,
+            '-217'    => DB_ERROR_NOSUCHFIELD,
+            '-329'    => DB_ERROR_NODBSELECTED,
+            '-1204'   => DB_ERROR_INVALID_DATE,
+            '-1205'   => DB_ERROR_INVALID_DATE,
+            '-1206'   => DB_ERROR_INVALID_DATE,
+            '-1209'   => DB_ERROR_INVALID_DATE,
+            '-1210'   => DB_ERROR_INVALID_DATE,
+            '-1212'   => DB_ERROR_INVALID_DATE
+       );
+          
+          return $MAP;
+}
+
+function adodb_error_oci8()
+{
+static $MAP = array(
+                        1 => DB_ERROR_ALREADY_EXISTS,
+            900 => DB_ERROR_SYNTAX,
+            904 => DB_ERROR_NOSUCHFIELD,
+            923 => DB_ERROR_SYNTAX,
+            942 => DB_ERROR_NOSUCHTABLE,
+            955 => DB_ERROR_ALREADY_EXISTS,
+            1476 => DB_ERROR_DIVZERO,
+            1722 => DB_ERROR_INVALID_NUMBER,
+            2289 => DB_ERROR_NOSUCHTABLE,
+            2291 => DB_ERROR_CONSTRAINT,
+            2449 => DB_ERROR_CONSTRAINT
+        );
+          
+       return $MAP;
+}
+
+function adodb_error_mssql()
+{
+static $MAP = array(
+                 208 => DB_ERROR_NOSUCHTABLE,
+          2601 => DB_ERROR_ALREADY_EXISTS
+       );
+          
+       return $MAP;
+}
+
+function adodb_error_sqlite()
+{
+static $MAP = array(
+                 1 => DB_ERROR_SYNTAX
+       );
+          
+       return $MAP;
+}
+
+function adodb_error_mysql()
+{
+static $MAP = array(
+           1004 => DB_ERROR_CANNOT_CREATE,
+           1005 => DB_ERROR_CANNOT_CREATE,
+           1006 => DB_ERROR_CANNOT_CREATE,
+           1007 => DB_ERROR_ALREADY_EXISTS,
+           1008 => DB_ERROR_CANNOT_DROP,
+                  1045 => DB_ERROR_ACCESS_VIOLATION,
+           1046 => DB_ERROR_NODBSELECTED,
+                  1049 => DB_ERROR_NOSUCHDB,
+           1050 => DB_ERROR_ALREADY_EXISTS,
+           1051 => DB_ERROR_NOSUCHTABLE,
+           1054 => DB_ERROR_NOSUCHFIELD,
+           1062 => DB_ERROR_ALREADY_EXISTS,
+           1064 => DB_ERROR_SYNTAX,
+           1100 => DB_ERROR_NOT_LOCKED,
+           1136 => DB_ERROR_VALUE_COUNT_ON_ROW,
+           1146 => DB_ERROR_NOSUCHTABLE,
+           1048 => DB_ERROR_CONSTRAINT,
+                   2002 => DB_ERROR_CONNECT_FAILED,
+                       2005 => DB_ERROR_CONNECT_FAILED
+       );
+          
+       return $MAP;
+}
+?>
\ No newline at end of file
diff --git a/typo3/sysext/adodb/adodb/adodb-errorhandler.inc.php b/typo3/sysext/adodb/adodb/adodb-errorhandler.inc.php
new file mode 100644 (file)
index 0000000..9f827ad
--- /dev/null
@@ -0,0 +1,79 @@
+<?php
+/**
+ * @version V4.68 25 Nov 2005  (c) 2000-2005 John Lim (jlim@natsoft.com.my). All rights reserved.
+ * Released under both BSD license and Lesser GPL library license.
+ * Whenever there is any discrepancy between the two licenses,
+ * the BSD license will take precedence.
+ *
+ * Set tabs to 4 for best viewing.
+ *
+ * Latest version is available at http://php.weblogs.com
+ *
+*/
+
+
+// added Claudio Bustos  clbustos#entelchile.net
+if (!defined('ADODB_ERROR_HANDLER_TYPE')) define('ADODB_ERROR_HANDLER_TYPE',E_USER_ERROR); 
+
+if (!defined('ADODB_ERROR_HANDLER')) define('ADODB_ERROR_HANDLER','ADODB_Error_Handler');
+
+/**
+* Default Error Handler. This will be called with the following params
+*
+* @param $dbms         the RDBMS you are connecting to
+* @param $fn           the name of the calling function (in uppercase)
+* @param $errno                the native error number from the database
+* @param $errmsg       the native error msg from the database
+* @param $p1           $fn specific parameter - see below
+* @param $p2           $fn specific parameter - see below
+* @param $thisConn     $current connection object - can be false if no connection object created
+*/
+function ADODB_Error_Handler($dbms, $fn, $errno, $errmsg, $p1, $p2, &$thisConnection)
+{
+       if (error_reporting() == 0) return; // obey @ protocol
+       switch($fn) {
+       case 'EXECUTE':
+               $sql = $p1;
+               $inputparams = $p2;
+
+               $s = "$dbms error: [$errno: $errmsg] in $fn(\"$sql\")\n";
+               break;
+
+       case 'PCONNECT':
+       case 'CONNECT':
+               $host = $p1;
+               $database = $p2;
+
+               $s = "$dbms error: [$errno: $errmsg] in $fn($host, '****', '****', $database)\n";
+               break;
+       default:
+               $s = "$dbms error: [$errno: $errmsg] in $fn($p1, $p2)\n";
+               break;
+       }
+       /*
+       * Log connection error somewhere
+       *       0 message is sent to PHP's system logger, using the Operating System's system
+       *               logging mechanism or a file, depending on what the error_log configuration
+       *               directive is set to.
+       *       1 message is sent by email to the address in the destination parameter.
+       *               This is the only message type where the fourth parameter, extra_headers is used.
+       *               This message type uses the same internal function as mail() does.
+       *       2 message is sent through the PHP debugging connection.
+       *               This option is only available if remote debugging has been enabled.
+       *               In this case, the destination parameter specifies the host name or IP address
+       *               and optionally, port number, of the socket receiving the debug information.
+       *       3 message is appended to the file destination
+       */
+       if (defined('ADODB_ERROR_LOG_TYPE')) {
+               $t = date('Y-m-d H:i:s');
+               if (defined('ADODB_ERROR_LOG_DEST'))
+                       error_log("($t) $s", ADODB_ERROR_LOG_TYPE, ADODB_ERROR_LOG_DEST);
+               else
+                       error_log("($t) $s", ADODB_ERROR_LOG_TYPE);
+       }
+
+
+       //print "<p>$s</p>";
+       trigger_error($s,ADODB_ERROR_HANDLER_TYPE); 
+}
+?>
diff --git a/typo3/sysext/adodb/adodb/adodb-errorpear.inc.php b/typo3/sysext/adodb/adodb/adodb-errorpear.inc.php
new file mode 100644 (file)
index 0000000..78441b5
--- /dev/null
@@ -0,0 +1,88 @@
+<?php
+/** 
+ * @version V4.68 25 Nov 2005 (c) 2000-2005 John Lim (jlim@natsoft.com.my). All rights reserved.
+ * Released under both BSD license and Lesser GPL library license. 
+  Whenever there is any discrepancy between the two licenses, 
+  the BSD license will take precedence. 
+ *
+ * Set tabs to 4 for best viewing.
+ * 
+ * Latest version is available at http://php.weblogs.com
+ * 
+*/
+include_once('PEAR.php');
+
+if (!defined('ADODB_ERROR_HANDLER')) define('ADODB_ERROR_HANDLER','ADODB_Error_PEAR');
+
+/*
+* Enabled the following if you want to terminate scripts when an error occurs
+*/
+//PEAR::setErrorHandling (PEAR_ERROR_DIE);
+
+/*
+* Name of the PEAR_Error derived class to call.
+*/
+if (!defined('ADODB_PEAR_ERROR_CLASS')) define('ADODB_PEAR_ERROR_CLASS','PEAR_Error');
+
+/*
+* Store the last PEAR_Error object here
+*/
+global $ADODB_Last_PEAR_Error; $ADODB_Last_PEAR_Error = false;
+
+  /**
+* Error Handler with PEAR support. This will be called with the following params
+*
+* @param $dbms         the RDBMS you are connecting to
+* @param $fn           the name of the calling function (in uppercase)
+* @param $errno                the native error number from the database 
+* @param $errmsg       the native error msg from the database
+* @param $p1           $fn specific parameter - see below
+* @param $P2           $fn specific parameter - see below
+       */
+function ADODB_Error_PEAR($dbms, $fn, $errno, $errmsg, $p1=false, $p2=false)
+{
+global $ADODB_Last_PEAR_Error;
+       
+       if (error_reporting() == 0) return; // obey @ protocol
+       switch($fn) {
+       case 'EXECUTE':
+               $sql = $p1;
+               $inputparams = $p2;
+               
+               $s = "$dbms error: [$errno: $errmsg] in $fn(\"$sql\")";
+               break;
+               
+       case 'PCONNECT':
+       case 'CONNECT':
+               $host = $p1;
+               $database = $p2;
+               
+               $s = "$dbms error: [$errno: $errmsg] in $fn('$host', ?, ?, '$database')";
+               break;
+               
+       default:
+               $s = "$dbms error: [$errno: $errmsg] in $fn($p1, $p2)";
+               break;
+       }
+       
+       $class = ADODB_PEAR_ERROR_CLASS;
+       $ADODB_Last_PEAR_Error = new $class($s, $errno,
+               $GLOBALS['_PEAR_default_error_mode'],
+               $GLOBALS['_PEAR_default_error_options'], 
+               $errmsg);
+               
+       //print "<p>!$s</p>";
+}
+
+/**
+* Returns last PEAR_Error object. This error might be for an error that
+* occured several sql statements ago.
+*/
+function &ADODB_PEAR_Error()
+{
+global $ADODB_Last_PEAR_Error;
+
+       return $ADODB_Last_PEAR_Error;
+}
+               
+?>
\ No newline at end of file
diff --git a/typo3/sysext/adodb/adodb/adodb-exceptions.inc.php b/typo3/sysext/adodb/adodb/adodb-exceptions.inc.php
new file mode 100644 (file)
index 0000000..af7ab57
--- /dev/null
@@ -0,0 +1,80 @@
+<?php
+
+/**
+ * @version V4.68 25 Nov 2005  (c) 2000-2005 John Lim (jlim@natsoft.com.my). All rights reserved.
+ * Released under both BSD license and Lesser GPL library license.
+ * Whenever there is any discrepancy between the two licenses,
+ * the BSD license will take precedence.
+ *
+ * Set tabs to 4 for best viewing.
+ *
+ * Latest version is available at http://php.weblogs.com
+ *
+ * Exception-handling code using PHP5 exceptions (try-catch-throw).
+ */
+
+
+if (!defined('ADODB_ERROR_HANDLER_TYPE')) define('ADODB_ERROR_HANDLER_TYPE',E_USER_ERROR); 
+define('ADODB_ERROR_HANDLER','adodb_throw');
+
+class ADODB_Exception extends Exception {
+var $dbms;
+var $fn;
+var $sql = '';
+var $params = '';
+var $host = '';
+var $database = '';
+       
+       function __construct($dbms, $fn, $errno, $errmsg, $p1, $p2, $thisConnection)
+       {
+               switch($fn) {
+               case 'EXECUTE':
+                       $this->sql = $p1;
+                       $this->params = $p2;
+                       $s = "$dbms error: [$errno: $errmsg] in $fn(\"$p1\")\n";
+                       break;
+       
+               case 'PCONNECT':
+               case 'CONNECT':
+                       $user = $thisConnection->user;
+                       $s = "$dbms error: [$errno: $errmsg] in $fn($p1, '$user', '****', $p2)\n";
+                       break;
+               default:
+                       $s = "$dbms error: [$errno: $errmsg] in $fn($p1, $p2)\n";
+                       break;
+               }
+       
+               $this->dbms = $dbms;
+               $this->host = $thisConnection->host;
+               $this->database = $thisConnection->database;
+               $this->fn = $fn;
+               $this->msg = $errmsg;
+                               
+               if (!is_numeric($errno)) $errno = -1;
+               parent::__construct($s,$errno);
+       }
+}
+
+/**
+* Default Error Handler. This will be called with the following params
+*
+* @param $dbms         the RDBMS you are connecting to
+* @param $fn           the name of the calling function (in uppercase)
+* @param $errno                the native error number from the database
+* @param $errmsg       the native error msg from the database
+* @param $p1           $fn specific parameter - see below
+* @param $P2           $fn specific parameter - see below
+*/
+
+function adodb_throw($dbms, $fn, $errno, $errmsg, $p1, $p2, $thisConnection)
+{
+global $ADODB_EXCEPTION;
+       
+       if (error_reporting() == 0) return; // obey @ protocol
+       if (is_string($ADODB_EXCEPTION)) $errfn = $ADODB_EXCEPTION;
+       else $errfn = 'ADODB_EXCEPTION';
+       throw new $errfn($dbms, $fn, $errno, $errmsg, $p1, $p2, $thisConnection);
+}
+
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/adodb/adodb/adodb-iterator.inc.php b/typo3/sysext/adodb/adodb/adodb-iterator.inc.php
new file mode 100644 (file)
index 0000000..24a24c4
--- /dev/null
@@ -0,0 +1,84 @@
+<?php
+
+/*
+  V4.68 25 Nov 2005  (c) 2000-2005 John Lim (jlim@natsoft.com.my). All rights reserved.
+  Released under both BSD license and Lesser GPL library license. 
+  Whenever there is any discrepancy between the two licenses, 
+  the BSD license will take precedence.
+  
+  Set tabs to 4.
+  
+  Declares the ADODB Base Class for PHP5 "ADODB_BASE_RS", and supports iteration with 
+  the ADODB_Iterator class.
+  
+               $rs = $db->Execute("select * from adoxyz");
+               foreach($rs as $k => $v) {
+                       echo $k; print_r($v); echo "<br>";
+               }
+               
+               
+       Iterator code based on http://cvs.php.net/cvs.php/php-src/ext/spl/examples/cachingiterator.inc?login=2
+ */
+
+ class ADODB_Iterator implements Iterator {
+
+    private $rs;
+
+    function __construct($rs) 
+       {
+        $this->rs = $rs;
+    }
+    function rewind() 
+       {
+        $this->rs->MoveFirst();
+    }
+
+       function valid() 
+       {
+        return !$this->rs->EOF;
+    }
+       
+    function key() 
+       {
+        return $this->rs->_currentRow;
+    }
+       
+    function current() 
+       {
+        return $this->rs->fields;
+    }
+       
+    function next() 
+       {
+        $this->rs->MoveNext();
+    }
+       
+       function __call($func, $params)
+       {
+               return call_user_func_array(array($this->rs, $func), $params);
+       }
+
+       
+       function hasMore()
+       {
+               return !$this->rs->EOF;
+       }
+
+}
+
+
+class ADODB_BASE_RS implements IteratorAggregate {
+    function getIterator() {
+        return new ADODB_Iterator($this);
+    }
+       
+       /* this is experimental - i don't really know what to return... */
+       function __toString()
+       {
+               include_once(ADODB_DIR.'/toexport.inc.php');
+               return _adodb_export($this,',',',',false,true);
+       }
+} 
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/adodb/adodb/adodb-lib.inc.php b/typo3/sysext/adodb/adodb/adodb-lib.inc.php
new file mode 100644 (file)
index 0000000..2de3291
--- /dev/null
@@ -0,0 +1,1008 @@
+<?php
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+global $ADODB_INCLUDED_LIB;
+$ADODB_INCLUDED_LIB = 1;
+
+/* 
+ @version V4.68 25 Nov 2005 (c) 2000-2005 John Lim (jlim\@natsoft.com.my). All rights reserved.
+  Released under both BSD license and Lesser GPL library license. 
+  Whenever there is any discrepancy between the two licenses, 
+  the BSD license will take precedence. See License.txt. 
+  Set tabs to 4 for best viewing.
+  
+  Less commonly used functions are placed here to reduce size of adodb.inc.php. 
+*/ 
+
+
+// Force key to upper. 
+// See also http://www.php.net/manual/en/function.array-change-key-case.php
+function _array_change_key_case($an_array)
+{
+       if (is_array($an_array)) {
+               $new_array = array();
+               foreach($an_array as $key=>$value)
+                       $new_array[strtoupper($key)] = $value;
+
+               return $new_array;
+   }
+
+       return $an_array;
+}
+
+function _adodb_replace(&$zthis, $table, $fieldArray, $keyCol, $autoQuote, $has_autoinc)
+{
+               if (count($fieldArray) == 0) return 0;
+               $first = true;
+               $uSet = '';
+               
+               if (!is_array($keyCol)) {
+                       $keyCol = array($keyCol);
+               }
+               foreach($fieldArray as $k => $v) {
+                       if ($autoQuote && !is_numeric($v) and strncmp($v,"'",1) !== 0 and strcasecmp($v,'null')!=0) {
+                               $v = $zthis->qstr($v);
+                               $fieldArray[$k] = $v;
+                       }
+                       if (in_array($k,$keyCol)) continue; // skip UPDATE if is key
+                       
+                       if ($first) {
+                               $first = false;                 
+                               $uSet = "$k=$v";
+                       } else
+                               $uSet .= ",$k=$v";
+               }
+                
+               $where = false;
+               foreach ($keyCol as $v) {
+                       if (isset($fieldArray[$v])) {
+                               if ($where) $where .= ' and '.$v.'='.$fieldArray[$v];
+                               else $where = $v.'='.$fieldArray[$v];
+                       }
+               }
+               
+               if ($uSet && $where) {
+                       $update = "UPDATE $table SET $uSet WHERE $where";
+
+                       $rs = $zthis->Execute($update);
+                       
+                       
+                       if ($rs) {
+                               if ($zthis->poorAffectedRows) {
+                               /*
+                                The Select count(*) wipes out any errors that the update would have returned. 
+                               http://phplens.com/lens/lensforum/msgs.php?id=5696
+                               */
+                                       if ($zthis->ErrorNo()<>0) return 0;
+                                       
+                               # affected_rows == 0 if update field values identical to old values
+                               # for mysql - which is silly. 
+                       
+                                       $cnt = $zthis->GetOne("select count(*) from $table where $where");
+                                       if ($cnt > 0) return 1; // record already exists
+                               } else {
+                                       if (($zthis->Affected_Rows()>0)) return 1;
+                               }
+                       } else
+                               return 0;
+               }
+               
+       //      print "<p>Error=".$this->ErrorNo().'<p>';
+               $first = true;
+               foreach($fieldArray as $k => $v) {
+                       if ($has_autoinc && in_array($k,$keyCol)) continue; // skip autoinc col
+                       
+                       if ($first) {
+                               $first = false;                 
+                               $iCols = "$k";
+                               $iVals = "$v";
+                       } else {
+                               $iCols .= ",$k";
+                               $iVals .= ",$v";
+                       }                               
+               }
+               $insert = "INSERT INTO $table ($iCols) VALUES ($iVals)"; 
+               $rs = $zthis->Execute($insert);
+               return ($rs) ? 2 : 0;
+}
+
+// Requires $ADODB_FETCH_MODE = ADODB_FETCH_NUM
+function _adodb_getmenu(&$zthis, $name,$defstr='',$blank1stItem=true,$multiple=false,
+                       $size=0, $selectAttr='',$compareFields0=true)
+{
+       $hasvalue = false;
+
+       if ($multiple or is_array($defstr)) {
+               if ($size==0) $size=5;
+               $attr = ' multiple size="'.$size.'"';
+               if (!strpos($name,'[]')) $name .= '[]';
+       } else if ($size) $attr = ' size="'.$size.'"';
+       else $attr ='';
+       
+       $s = '<select name="'.$name.'"'.$attr.' '.$selectAttr.'>';
+       if ($blank1stItem) 
+               if (is_string($blank1stItem))  {
+                       $barr = explode(':',$blank1stItem);
+                       if (sizeof($barr) == 1) $barr[] = '';
+                       $s .= "\n<option value=\"".$barr[0]."\">".$barr[1]."</option>";
+               } else $s .= "\n<option></option>";
+
+       if ($zthis->FieldCount() > 1) $hasvalue=true;
+       else $compareFields0 = true;
+       
+       $value = '';
+    $optgroup = null;
+    $firstgroup = true;
+    $fieldsize = $zthis->FieldCount();
+       while(!$zthis->EOF) {
+               $zval = rtrim(reset($zthis->fields));
+
+               if ($blank1stItem && $zval=="") {
+                       $zthis->MoveNext();
+                       continue;
+               }
+
+        if ($fieldsize > 1) {
+                       if (isset($zthis->fields[1]))
+                               $zval2 = rtrim($zthis->fields[1]);
+                       else
+                               $zval2 = rtrim(next($zthis->fields));
+               }
+               $selected = ($compareFields0) ? $zval : $zval2;
+               
+        $group = '';
+               if ($fieldsize > 2) {
+            $group = rtrim($zthis->fields[2]);
+        }
+        if ($optgroup != $group) {
+            $optgroup = $group;
+            if ($firstgroup) {
+                $firstgroup = false;
+                $s .="\n<optgroup label='". htmlspecialchars($group) ."'>";
+            } else {
+                $s .="\n</optgroup>";
+                $s .="\n<optgroup label='". htmlspecialchars($group) ."'>";
+            }
+               }
+       
+               if ($hasvalue) 
+                       $value = " value='".htmlspecialchars($zval2)."'";
+               
+               if (is_array($defstr))  {
+                       
+                       if (in_array($selected,$defstr)) 
+                               $s .= "\n<option selected='selected'$value>".htmlspecialchars($zval).'</option>';
+                       else 
+                               $s .= "\n<option".$value.'>'.htmlspecialchars($zval).'</option>';
+               }
+               else {
+                       if (strcasecmp($selected,$defstr)==0) 
+                               $s .= "\n<option selected='selected'$value>".htmlspecialchars($zval).'</option>';
+                       else
+                               $s .= "\n<option".$value.'>'.htmlspecialchars($zval).'</option>';
+               }
+               $zthis->MoveNext();
+       } // while
+       
+    // closing last optgroup
+    if($optgroup != null) {
+        $s .= "\n</optgroup>";
+       }
+       return $s ."\n</select>\n";
+}
+
+// Requires $ADODB_FETCH_MODE = ADODB_FETCH_NUM
+function _adodb_getmenu_gp(&$zthis, $name,$defstr='',$blank1stItem=true,$multiple=false,
+                       $size=0, $selectAttr='',$compareFields0=true)
+{
+       $hasvalue = false;
+
+       if ($multiple or is_array($defstr)) {
+               if ($size==0) $size=5;
+               $attr = ' multiple size="'.$size.'"';
+               if (!strpos($name,'[]')) $name .= '[]';
+       } else if ($size) $attr = ' size="'.$size.'"';
+       else $attr ='';
+       
+       $s = '<select name="'.$name.'"'.$attr.' '.$selectAttr.'>';
+       if ($blank1stItem) 
+               if (is_string($blank1stItem))  {
+                       $barr = explode(':',$blank1stItem);
+                       if (sizeof($barr) == 1) $barr[] = '';
+                       $s .= "\n<option value=\"".$barr[0]."\">".$barr[1]."</option>";
+               } else $s .= "\n<option></option>";
+
+       if ($zthis->FieldCount() > 1) $hasvalue=true;
+       else $compareFields0 = true;
+       
+       $value = '';
+    $optgroup = null;
+    $firstgroup = true;
+    $fieldsize = sizeof($zthis->fields);
+       while(!$zthis->EOF) {
+               $zval = rtrim(reset($zthis->fields));
+
+               if ($blank1stItem && $zval=="") {
+                       $zthis->MoveNext();
+                       continue;
+               }
+
+        if ($fieldsize > 1) {
+                       if (isset($zthis->fields[1]))
+                               $zval2 = rtrim($zthis->fields[1]);
+                       else
+                               $zval2 = rtrim(next($zthis->fields));
+               }
+               $selected = ($compareFields0) ? $zval : $zval2;
+               
+        $group = '';
+               if (isset($zthis->fields[2])) {
+            $group = rtrim($zthis->fields[2]);
+        }
+        if ($optgroup != $group) {
+            $optgroup = $group;
+            if ($firstgroup) {
+                $firstgroup = false;
+                $s .="\n<optgroup label='". htmlspecialchars($group) ."'>";
+            } else {
+                $s .="\n</optgroup>";
+                $s .="\n<optgroup label='". htmlspecialchars($group) ."'>";
+            }
+               }
+       
+               if ($hasvalue) 
+                       $value = " value='".htmlspecialchars($zval2)."'";
+               
+               if (is_array($defstr))  {
+                       
+                       if (in_array($selected,$defstr)) 
+                               $s .= "\n<option selected='selected'$value>".htmlspecialchars($zval).'</option>';
+                       else 
+                               $s .= "\n<option".$value.'>'.htmlspecialchars($zval).'</option>';
+               }
+               else {
+                       if (strcasecmp($selected,$defstr)==0) 
+                               $s .= "\n<option selected='selected'$value>".htmlspecialchars($zval).'</option>';
+                       else
+                               $s .= "\n<option".$value.'>'.htmlspecialchars($zval).'</option>';
+               }
+               $zthis->MoveNext();
+       } // while
+       
+    // closing last optgroup
+    if($optgroup != null) {
+        $s .= "\n</optgroup>";
+       }
+       return $s ."\n</select>\n";
+}
+
+
+/*
+       Count the number of records this sql statement will return by using
+       query rewriting techniques...
+       
+       Does not work with UNIONs, except with postgresql and oracle.
+*/
+function _adodb_getcount(&$zthis, $sql,$inputarr=false,$secs2cache=0) 
+{
+       $qryRecs = 0;
+       
+        if (preg_match("/^\s*SELECT\s+DISTINCT/is", $sql) || 
+               preg_match('/\s+GROUP\s+BY\s+/is',$sql) || 
+               preg_match('/\s+UNION\s+/is',$sql)) {
+               // ok, has SELECT DISTINCT or GROUP BY so see if we can use a table alias
+               // but this is only supported by oracle and postgresql...
+               if ($zthis->dataProvider == 'oci8') {
+                       
+                       $rewritesql = preg_replace('/(\sORDER\s+BY\s.*)/is','',$sql);
+                       
+                       // Allow Oracle hints to be used for query optimization, Chris Wrye
+                       if (preg_match('#/\\*+.*?\\*\\/#', $sql, $hint)) {
+                               $rewritesql = "SELECT ".$hint[0]." COUNT(*) FROM (".$rewritesql.")"; 
+                       } else
+                               $rewritesql = "SELECT COUNT(*) FROM (".$rewritesql.")"; 
+                       
+               } else if (strncmp($zthis->databaseType,'postgres',8) == 0)  {
+                       
+                       $info = $zthis->ServerInfo();
+                       if (substr($info['version'],0,3) >= 7.1) { // good till version 999
+                               $rewritesql = preg_replace('/(\sORDER\s+BY\s[^)]*)/is','',$sql);
+                               $rewritesql = "SELECT COUNT(*) FROM ($rewritesql) _ADODB_ALIAS_";
+                       }
+               }
+       } else {
+               // now replace SELECT ... FROM with SELECT COUNT(*) FROM
+               $rewritesql = preg_replace(
+                                       '/^\s*SELECT\s.*\s+FROM\s/Uis','SELECT COUNT(*) FROM ',$sql);
+
+               // fix by alexander zhukov, alex#unipack.ru, because count(*) and 'order by' fails 
+               // with mssql, access and postgresql. Also a good speedup optimization - skips sorting!
+               $rewritesql = preg_replace('/(\sORDER\s+BY\s[^)]*)/is','',$rewritesql);
+       }
+       
+       if (isset($rewritesql) && $rewritesql != $sql) {
+               if ($secs2cache) {
+                       // we only use half the time of secs2cache because the count can quickly
+                       // become inaccurate if new records are added
+                       $qryRecs = $zthis->CacheGetOne($secs2cache/2,$rewritesql,$inputarr);
+                       
+               } else {
+                       $qryRecs = $zthis->GetOne($rewritesql,$inputarr);
+               }
+               if ($qryRecs !== false) return $qryRecs;
+       }
+       //--------------------------------------------
+       // query rewrite failed - so try slower way...
+       
+       
+       // strip off unneeded ORDER BY if no UNION
+       if (preg_match('/\s*UNION\s*/is', $sql)) $rewritesql = $sql;
+       else $rewritesql = preg_replace('/(\sORDER\s+BY\s.*)/is','',$sql); 
+       
+       $rstest = &$zthis->Execute($rewritesql,$inputarr);
+       if (!$rstest) $rstest = $zthis->Execute($sql,$inputarr);
+       
+       if ($rstest) {
+                       $qryRecs = $rstest->RecordCount();
+               if ($qryRecs == -1) { 
+               global $ADODB_EXTENSION;
+               // some databases will return -1 on MoveLast() - change to MoveNext()
+                       if ($ADODB_EXTENSION) {
+                               while(!$rstest->EOF) {
+                                       adodb_movenext($rstest);
+                               }
+                       } else {
+                               while(!$rstest->EOF) {
+                                       $rstest->MoveNext();
+                               }
+                       }
+                       $qryRecs = $rstest->_currentRow;
+               }
+               $rstest->Close();
+               if ($qryRecs == -1) return 0;
+       }
+       
+       return $qryRecs;
+}
+
+/*
+       Code originally from "Cornel G" <conyg@fx.ro>
+
+       This code might not work with SQL that has UNION in it  
+       
+       Also if you are using CachePageExecute(), there is a strong possibility that
+       data will get out of synch. use CachePageExecute() only with tables that
+       rarely change.
+*/
+function &_adodb_pageexecute_all_rows(&$zthis, $sql, $nrows, $page, 
+                                               $inputarr=false, $secs2cache=0) 
+{
+       $atfirstpage = false;
+       $atlastpage = false;
+       $lastpageno=1;
+
+       // If an invalid nrows is supplied, 
+       // we assume a default value of 10 rows per page
+       if (!isset($nrows) || $nrows <= 0) $nrows = 10;
+
+       $qryRecs = false; //count records for no offset
+       
+       $qryRecs = _adodb_getcount($zthis,$sql,$inputarr,$secs2cache);
+       $lastpageno = (int) ceil($qryRecs / $nrows);
+       $zthis->_maxRecordCount = $qryRecs;
+       
+
+
+       // ***** Here we check whether $page is the last page or 
+       // whether we are trying to retrieve 
+       // a page number greater than the last page number.
+       if ($page >= $lastpageno) {
+               $page = $lastpageno;
+               $atlastpage = true;
+       }
+       
+       // If page number <= 1, then we are at the first page
+       if (empty($page) || $page <= 1) {       
+               $page = 1;
+               $atfirstpage = true;
+       }
+       
+       // We get the data we want
+       $offset = $nrows * ($page-1);
+       if ($secs2cache > 0) 
+               $rsreturn = &$zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $offset, $inputarr);
+       else 
+               $rsreturn = &$zthis->SelectLimit($sql, $nrows, $offset, $inputarr, $secs2cache);
+
+       
+       // Before returning the RecordSet, we set the pagination properties we need
+       if ($rsreturn) {
+               $rsreturn->_maxRecordCount = $qryRecs;
+               $rsreturn->rowsPerPage = $nrows;
+               $rsreturn->AbsolutePage($page);
+               $rsreturn->AtFirstPage($atfirstpage);
+               $rsreturn->AtLastPage($atlastpage);
+               $rsreturn->LastPageNo($lastpageno);
+       }
+       return $rsreturn;
+}
+
+// Iv├ín Oliva version
+function &_adodb_pageexecute_no_last_page(&$zthis, $sql, $nrows, $page, $inputarr=false, $secs2cache=0) 
+{
+
+       $atfirstpage = false;
+       $atlastpage = false;
+       
+       if (!isset($page) || $page <= 1) {      // If page number <= 1, then we are at the first page
+               $page = 1;
+               $atfirstpage = true;
+       }
+       if ($nrows <= 0) $nrows = 10;   // If an invalid nrows is supplied, we assume a default value of 10 rows per page
+       
+       // ***** Here we check whether $page is the last page or whether we are trying to retrieve a page number greater than 
+       // the last page number.
+       $pagecounter = $page + 1;
+       $pagecounteroffset = ($pagecounter * $nrows) - $nrows;
+       if ($secs2cache>0) $rstest = &$zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $pagecounteroffset, $inputarr);
+       else $rstest = &$zthis->SelectLimit($sql, $nrows, $pagecounteroffset, $inputarr, $secs2cache);
+       if ($rstest) {
+               while ($rstest && $rstest->EOF && $pagecounter>0) {
+                       $atlastpage = true;
+                       $pagecounter--;
+                       $pagecounteroffset = $nrows * ($pagecounter - 1);
+                       $rstest->Close();
+                       if ($secs2cache>0) $rstest = &$zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $pagecounteroffset, $inputarr);
+                       else $rstest = &$zthis->SelectLimit($sql, $nrows, $pagecounteroffset, $inputarr, $secs2cache);
+               }
+               if ($rstest) $rstest->Close();
+       }
+       if ($atlastpage) {      // If we are at the last page or beyond it, we are going to retrieve it
+               $page = $pagecounter;
+               if ($page == 1) $atfirstpage = true;    // We have to do this again in case the last page is the same as the first
+                       //... page, that is, the recordset has only 1 page.
+       }
+       
+       // We get the data we want
+       $offset = $nrows * ($page-1);
+       if ($secs2cache > 0) $rsreturn = &$zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $offset, $inputarr);
+       else $rsreturn = &$zthis->SelectLimit($sql, $nrows, $offset, $inputarr, $secs2cache);
+       
+       // Before returning the RecordSet, we set the pagination properties we need
+       if ($rsreturn) {
+               $rsreturn->rowsPerPage = $nrows;
+               $rsreturn->AbsolutePage($page);
+               $rsreturn->AtFirstPage($atfirstpage);
+               $rsreturn->AtLastPage($atlastpage);
+       }
+       return $rsreturn;
+}
+
+function _adodb_getupdatesql(&$zthis,&$rs, $arrFields,$forceUpdate=false,$magicq=false,$force=2)
+{
+               if (!$rs) {
+                       printf(ADODB_BAD_RS,'GetUpdateSQL');
+                       return false;
+               }
+       
+               $fieldUpdatedCount = 0;
+               $arrFields = _array_change_key_case($arrFields);
+
+               $hasnumeric = isset($rs->fields[0]);
+               $setFields = '';
+               
+               // Loop through all of the fields in the recordset
+               for ($i=0, $max=$rs->FieldCount(); $i < $max; $i++) {
+                       // Get the field from the recordset
+                       $field = $rs->FetchField($i);
+
+                       // If the recordset field is one
+                       // of the fields passed in then process.
+                       $upperfname = strtoupper($field->name);
+                       if (adodb_key_exists($upperfname,$arrFields,$force)) {
+                               
+                               // If the existing field value in the recordset
+                               // is different from the value passed in then
+                               // go ahead and append the field name and new value to
+                               // the update query.
+                               
+                               if ($hasnumeric) $val = $rs->fields[$i];
+                               else if (isset($rs->fields[$upperfname])) $val = $rs->fields[$upperfname];
+                               else if (isset($rs->fields[$field->name])) $val =  $rs->fields[$field->name];
+                               else if (isset($rs->fields[strtolower($upperfname)])) $val =  $rs->fields[strtolower($upperfname)];
+                               else $val = '';
+                               
+                       
+                               if ($forceUpdate || strcmp($val, $arrFields[$upperfname])) {
+                                       // Set the counter for the number of fields that will be updated.
+                                       $fieldUpdatedCount++;
+
+                                       // Based on the datatype of the field
+                                       // Format the value properly for the database
+                                       $type = $rs->MetaType($field->type);
+                                               
+
+                                       if ($type == 'null') {
+                                               $type = 'C';
+                                       }
+                                       
+                                       if (strpos($upperfname,' ') !== false)
+                                               $fnameq = $zthis->nameQuote.$upperfname.$zthis->nameQuote;
+                                       else
+                                               $fnameq = $upperfname;
+                                       
+                                       
+                // is_null requires php 4.0.4
+                //********************************************************//
+                if (is_null($arrFields[$upperfname])
+                                       || (empty($arrFields[$upperfname]) && strlen($arrFields[$upperfname]) == 0)
+                    || $arrFields[$upperfname] === 'null'
+                    )
+                {
+                    switch ($force) {
+
+                        //case 0:
+                        //    //Ignore empty values. This is allready handled in "adodb_key_exists" function.
+                        //break;
+
+                        case 1:
+                            //Set null
+                            $setFields .= $field->name . " = null, ";
+                        break;
+                                                       
+                        case 2:
+                            //Set empty
+                            $arrFields[$upperfname] = "";
+                            $setFields .= _adodb_column_sql($zthis, 'U', $type, $upperfname, $fnameq,$arrFields, $magicq);
+                        break;
+                                               default:
+                        case 3:
+                            //Set the value that was given in array, so you can give both null and empty values
+                            if (is_null($arrFields[$upperfname]) || $arrFields[$upperfname] === 'null') {
+                                $setFields .= $field->name . " = null, ";
+                            } else {
+                                $setFields .= _adodb_column_sql($zthis, 'U', $type, $upperfname, $fnameq,$arrFields, $magicq);
+                            }
+                        break;
+                    }
+                //********************************************************//
+                } else {
+                                               //we do this so each driver can customize the sql for
+                                               //DB specific column types. 
+                                               //Oracle needs BLOB types to be handled with a returning clause
+                                               //postgres has special needs as well
+                                               $setFields .= _adodb_column_sql($zthis, 'U', $type, $upperfname, $fnameq,
+                                                                                                                 $arrFields, $magicq);
+                                       }
+                               }
+                       }
+               }
+
+               // If there were any modified fields then build the rest of the update query.
+               if ($fieldUpdatedCount > 0 || $forceUpdate) {
+                                       // Get the table name from the existing query.
+                       if (!empty($rs->tableName)) $tableName = $rs->tableName;
+                       else {
+                               preg_match("/FROM\s+".ADODB_TABLE_REGEX."/is", $rs->sql, $tableName);
+                               $tableName = $tableName[1];
+                       }
+                       // Get the full where clause excluding the word "WHERE" from
+                       // the existing query.
+                       preg_match('/\sWHERE\s(.*)/is', $rs->sql, $whereClause);
+                       
+                       $discard = false;
+                       // not a good hack, improvements?
+                       if ($whereClause) {
+                               if (preg_match('/\s(ORDER\s.*)/is', $whereClause[1], $discard));
+                               else if (preg_match('/\s(LIMIT\s.*)/is', $whereClause[1], $discard));
+                               else preg_match('/\s(FOR UPDATE.*)/is', $whereClause[1], $discard);
+                       } else
+                               $whereClause = array(false,false);
+                               
+                       if ($discard)
+                               $whereClause[1] = substr($whereClause[1], 0, strlen($whereClause[1]) - strlen($discard[1]));
+                       
+                       $sql = 'UPDATE '.$tableName.' SET '.substr($setFields, 0, -2);
+                       if (strlen($whereClause[1]) > 0) 
+                               $sql .= ' WHERE '.$whereClause[1];
+
+                       return $sql;
+
+               } else {
+                       return false;
+       }
+}
+
+function adodb_key_exists($key, &$arr,$force=2)
+{
+       if ($force<=0) {
+               // the following is the old behaviour where null or empty fields are ignored
+               return (!empty($arr[$key])) || (isset($arr[$key]) && strlen($arr[$key])>0);
+       }
+
+       if (isset($arr[$key])) return true;
+       ## null check below
+       if (ADODB_PHPVER >= 0x4010) return array_key_exists($key,$arr);
+       return false;
+}
+
+/**
+ * There is a special case of this function for the oci8 driver.
+ * The proper way to handle an insert w/ a blob in oracle requires
+ * a returning clause with bind variables and a descriptor blob.
+ * 
+ * 
+ */
+function _adodb_getinsertsql(&$zthis,&$rs,$arrFields,$magicq=false,$force=2)
+{
+static $cacheRS = false;
+static $cacheSig = 0;
+static $cacheCols;
+
+       $tableName = '';
+       $values = '';
+       $fields = '';
+       $recordSet = null;
+       $arrFields = _array_change_key_case($arrFields);
+       $fieldInsertedCount = 0;
+       
+       if (is_string($rs)) {
+               //ok we have a table name
+               //try and get the column info ourself.
+               $tableName = $rs;                       
+       
+               //we need an object for the recordSet
+               //because we have to call MetaType.
+               //php can't do a $rsclass::MetaType()
+               $rsclass = $zthis->rsPrefix.$zthis->databaseType;
+               $recordSet = new $rsclass(-1,$zthis->fetchMode);
+               $recordSet->connection = &$zthis;
+               
+               if (is_string($cacheRS) && $cacheRS == $rs) {
+                       $columns =& $cacheCols;
+               } else {
+                       $columns = $zthis->MetaColumns( $tableName );
+                       $cacheRS = $tableName;
+                       $cacheCols = $columns;
+               }
+       } else if (is_subclass_of($rs, 'adorecordset')) {
+               if (isset($rs->insertSig) && is_integer($cacheRS) && $cacheRS == $rs->insertSig) {
+                       $columns =& $cacheCols;
+               } else {
+                       for ($i=0, $max=$rs->FieldCount(); $i < $max; $i++) 
+                               $columns[] = $rs->FetchField($i);
+                       $cacheRS = $cacheSig;
+                       $cacheCols = $columns;
+                       $rs->insertSig = $cacheSig++;
+               }
+               $recordSet =& $rs;
+       
+       } else {
+               printf(ADODB_BAD_RS,'GetInsertSQL');
+               return false;
+       }
+
+       // Loop through all of the fields in the recordset
+       foreach( $columns as $field ) { 
+               $upperfname = strtoupper($field->name);
+               if (adodb_key_exists($upperfname,$arrFields,$force)) {
+                       $bad = false;
+                       if (strpos($upperfname,' ') !== false)
+                               $fnameq = $zthis->nameQuote.$upperfname.$zthis->nameQuote;
+                       else
+                               $fnameq = $upperfname;
+                       
+                       $type = $recordSet->MetaType($field->type);
+                       
+            /********************************************************/
+            if (is_null($arrFields[$upperfname])
+                || (empty($arrFields[$upperfname]) && strlen($arrFields[$upperfname]) == 0)
+                || $arrFields[$upperfname] === 'null'
+                               )
+               {
+                    switch ($force) {
+
+                        case 0: // we must always set null if missing
+                                                       $bad = true;
+                                                       break;
+                                                       
+                        case 1:
+                            $values  .= "null, ";
+                        break;
+               
+                        case 2:
+                            //Set empty
+                            $arrFields[$upperfname] = "";
+                            $values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq,$arrFields, $magicq);
+                        break;
+
+                                               default:
+                        case 3:
+                            //Set the value that was given in array, so you can give both null and empty values
+                                                       if (is_null($arrFields[$upperfname]) || $arrFields[$upperfname] === 'null') { 
+                                                               $values  .= "null, ";
+                                                       } else {
+                                       $values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq, $arrFields, $magicq);
+                                       }
+                               break;
+                       } // switch
+
+            /*********************************************************/
+                       } else {
+                               //we do this so each driver can customize the sql for
+                               //DB specific column types. 
+                               //Oracle needs BLOB types to be handled with a returning clause
+                               //postgres has special needs as well
+                               $values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq,
+                                                                                          $arrFields, $magicq);
+                       }
+                       
+                       if ($bad) continue;
+                       // Set the counter for the number of fields that will be inserted.
+                       $fieldInsertedCount++;
+                       
+                       
+                       // Get the name of the fields to insert
+                       $fields .= $fnameq . ", ";
+               }
+       }
+
+
+       // If there were any inserted fields then build the rest of the insert query.
+       if ($fieldInsertedCount <= 0)  return false;
+       
+       // Get the table name from the existing query.
+       if (!$tableName) {
+               if (!empty($rs->tableName)) $tableName = $rs->tableName;
+               else if (preg_match("/FROM\s+".ADODB_TABLE_REGEX."/is", $rs->sql, $tableName))
+                       $tableName = $tableName[1];
+               else 
+                       return false;
+       }               
+
+       // Strip off the comma and space on the end of both the fields
+       // and their values.
+       $fields = substr($fields, 0, -2);
+       $values = substr($values, 0, -2);
+
+       // Append the fields and their values to the insert query.
+       return 'INSERT INTO '.$zthis->nameQuote.$tableName.$zthis->nameQuote.' ( '.$fields.' ) VALUES ( '.$values.' )';
+}
+
+
+/**
+ * This private method is used to help construct
+ * the update/sql which is generated by GetInsertSQL and GetUpdateSQL.
+ * It handles the string construction of 1 column -> sql string based on
+ * the column type.  We want to do 'safe' handling of BLOBs
+ * 
+ * @param string the type of sql we are trying to create
+ *                'I' or 'U'. 
+ * @param string column data type from the db::MetaType() method  
+ * @param string the column name
+ * @param array the column value
+ * 
+ * @return string
+ * 
+ */
+function _adodb_column_sql_oci8(&$zthis,$action, $type, $fname, $fnameq, $arrFields, $magicq) 
+{
+    $sql = '';
+    
+    // Based on the datatype of the field
+    // Format the value properly for the database
+    switch($type) {
+    case 'B':
+        //in order to handle Blobs correctly, we need
+        //to do some magic for Oracle
+
+        //we need to create a new descriptor to handle 
+        //this properly
+        if (!empty($zthis->hasReturningInto)) {
+            if ($action == 'I') {
+                $sql = 'empty_blob(), ';
+            } else {
+                $sql = $fnameq. '=empty_blob(), ';
+            }
+            //add the variable to the returning clause array
+            //so the user can build this later in
+            //case they want to add more to it
+            $zthis->_returningArray[$fname] = ':xx'.$fname.'xx';
+        } else if (empty($arrFields[$fname])){
+            if ($action == 'I') {
+                $sql = 'empty_blob(), ';
+            } else {
+                $sql = $fnameq. '=empty_blob(), ';
+            }            
+        } else {
+            //this is to maintain compatibility
+            //with older adodb versions.
+            $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq,false);
+        }
+        break;
+
+    case "X":
+        //we need to do some more magic here for long variables
+        //to handle these correctly in oracle.
+
+        //create a safe bind var name
+        //to avoid conflicts w/ dupes.
+       if (!empty($zthis->hasReturningInto)) {
+            if ($action == 'I') {
+                $sql = ':xx'.$fname.'xx, ';                
+            } else {
+                $sql = $fnameq.'=:xx'.$fname.'xx, ';
+            }
+            //add the variable to the returning clause array
+            //so the user can build this later in
+            //case they want to add more to it
+            $zthis->_returningArray[$fname] = ':xx'.$fname.'xx';
+        } else {
+            //this is to maintain compatibility
+            //with older adodb versions.
+            $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq,false);
+        }            
+        break;
+        
+    default:
+        $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq,  $arrFields, $magicq,false);
+        break;
+    }
+    
+    return $sql;
+}    
+       
+function _adodb_column_sql(&$zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq, $recurse=true) 
+{
+
+       if ($recurse) {
+               switch($zthis->dataProvider)  {
+               case 'postgres':
+                       if ($type == 'L') $type = 'C';
+                       break;
+               case 'oci8':
+                       return _adodb_column_sql_oci8($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq);
+                       
+               }
+       }
+               
+       switch($type) {
+               case "C":
+               case "X":
+               case 'B':
+                       $val = $zthis->qstr($arrFields[$fname],$magicq);
+                       break;
+
+               case "D":
+                       $val = $zthis->DBDate($arrFields[$fname]);
+                       break;
+
+               case "T":
+                       $val = $zthis->DBTimeStamp($arrFields[$fname]);
+                       break;
+
+               default:
+                       $val = $arrFields[$fname];
+                       if (empty($val)) $val = '0';
+                       break;
+       }
+
+       if ($action == 'I') return $val . ", ";
+       
+       
+       return $fnameq . "=" . $val  . ", ";
+       
+}
+
+
+
+function _adodb_debug_execute(&$zthis, $sql, $inputarr)
+{
+       $ss = '';
+       if ($inputarr) {
+               foreach($inputarr as $kk=>$vv) {
+                       if (is_string($vv) && strlen($vv)>64) $vv = substr($vv,0,64).'...';
+                       $ss .= "($kk=>'$vv') ";
+               }
+               $ss = "[ $ss ]";
+       }
+       $sqlTxt = is_array($sql) ? $sql[0] : $sql;
+       /*str_replace(', ','##1#__^LF',is_array($sql) ? $sql[0] : $sql);
+       $sqlTxt = str_replace(',',', ',$sqlTxt);
+       $sqlTxt = str_replace('##1#__^LF', ', ' ,$sqlTxt);
+       */
+       // check if running from browser or command-line
+       $inBrowser = isset($_SERVER['HTTP_USER_AGENT']);
+       
+       $dbt = $zthis->databaseType;
+       if (isset($zthis->dsnType)) $dbt .= '-'.$zthis->dsnType;
+       if ($inBrowser) {
+               if ($ss) {
+                       $ss = '<code>'.htmlspecialchars($ss).'</code>';
+               }
+               if ($zthis->debug === -1)
+                       ADOConnection::outp( "<br />\n($dbt): ".htmlspecialchars($sqlTxt)." &nbsp; $ss\n<br />\n",false);
+               else 
+                       ADOConnection::outp( "<hr />\n($dbt): ".htmlspecialchars($sqlTxt)." &nbsp; $ss\n<hr />\n",false);
+       } else {
+               ADOConnection::outp("-----\n($dbt): ".$sqlTxt."\n-----\n",false);
+       }
+
+       $qID = $zthis->_query($sql,$inputarr);
+       
+       /* 
+               Alexios Fakios notes that ErrorMsg() must be called before ErrorNo() for mssql
+               because ErrorNo() calls Execute('SELECT @ERROR'), causing recursion
+       */
+       if ($zthis->databaseType == 'mssql') { 
+       // ErrorNo is a slow function call in mssql, and not reliable in PHP 4.0.6
+               if($emsg = $zthis->ErrorMsg()) {
+                       if ($err = $zthis->ErrorNo()) ADOConnection::outp($err.': '.$emsg);
+               }
+       } else if (!$qID) {
+               ADOConnection::outp($zthis->ErrorNo() .': '. $zthis->ErrorMsg());
+       }
+       
+       if ($zthis->debug === 99) _adodb_backtrace(true,9999,2);
+       return $qID;
+}
+
+# pretty print the debug_backtrace function
+function _adodb_backtrace($printOrArr=true,$levels=9999,$skippy=0)
+{
+       if (!function_exists('debug_backtrace')) return '';
+        
+       $html =  (isset($_SERVER['HTTP_USER_AGENT']));
+       $fmt =  ($html) ? "</font><font color=#808080 size=-1> %% line %4d, file: <a href=\"file:/%s\">%s</a></font>" : "%% line %4d, file: %s";
+
+       $MAXSTRLEN = 128;
+
+       $s = ($html) ? '<pre align=left>' : '';
+       
+       if (is_array($printOrArr)) $traceArr = $printOrArr;
+       else $traceArr = debug_backtrace();
+       array_shift($traceArr);
+       array_shift($traceArr);
+       $tabs = sizeof($traceArr)-2;
+       
+       foreach ($traceArr as $arr) {
+               if ($skippy) {$skippy -= 1; continue;}
+               $levels -= 1;
+               if ($levels < 0) break;
+               
+               $args = array();
+               for ($i=0; $i < $tabs; $i++) $s .=  ($html) ? ' &nbsp; ' : "\t";
+               $tabs -= 1;
+               if ($html) $s .= '<font face="Courier New,Courier">';
+               if (isset($arr['class'])) $s .= $arr['class'].'.';
+               if (isset($arr['args']))
+                foreach($arr['args'] as $v) {
+                       if (is_null($v)) $args[] = 'null';
+                       else if (is_array($v)) $args[] = 'Array['.sizeof($v).']';
+                       else if (is_object($v)) $args[] = 'Object:'.get_class($v);
+                       else if (is_bool($v)) $args[] = $v ? 'true' : 'false';
+                       else {
+                               $v = (string) @$v;
+                               $str = htmlspecialchars(substr($v,0,$MAXSTRLEN));
+                               if (strlen($v) > $MAXSTRLEN) $str .= '...';
+                               $args[] = $str;
+                       }
+               }
+               $s .= $arr['function'].'('.implode(', ',$args).')';
+               
+               
+               $s .= @sprintf($fmt, $arr['line'],$arr['file'],basename($arr['file']));
+                       
+               $s .= "\n";
+       }       
+       if ($html) $s .= '</pre>';
+       if ($printOrArr) print $s;
+       
+       return $s;
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/adodb/adodb/adodb-pager.inc.php b/typo3/sysext/adodb/adodb/adodb-pager.inc.php
new file mode 100644 (file)
index 0000000..7029e42
--- /dev/null
@@ -0,0 +1,289 @@
+<?php
+
+/*
+       V4.68 25 Nov 2005  (c) 2000-2005 John Lim (jlim@natsoft.com.my). All rights reserved.
+         Released under both BSD license and Lesser GPL library license. 
+         Whenever there is any discrepancy between the two licenses, 
+         the BSD license will take precedence. 
+         Set tabs to 4 for best viewing.
+
+       This class provides recordset pagination with 
+       First/Prev/Next/Last links. 
+       
+       Feel free to modify this class for your own use as
+       it is very basic. To learn how to use it, see the 
+       example in adodb/tests/testpaging.php.
+       
+       "Pablo Costa" <pablo@cbsp.com.br> implemented Render_PageLinks().
+       
+       Please note, this class is entirely unsupported, 
+       and no free support requests except for bug reports
+       will be entertained by the author.
+
+*/
+class ADODB_Pager {
+       var $id;        // unique id for pager (defaults to 'adodb')
+       var $db;        // ADODB connection object
+       var $sql;       // sql used
+       var $rs;        // recordset generated
+       var $curr_page; // current page number before Render() called, calculated in constructor
+       var $rows;              // number of rows per page
+    var $linksPerPage=10; // number of links per page in navigation bar
+    var $showPageLinks; 
+
+       var $gridAttributes = 'width=100% border=1 bgcolor=white';
+       
+       // Localize text strings here
+       var $first = '<code>|&lt;</code>';
+       var $prev = '<code>&lt;&lt;</code>';
+       var $next = '<code>>></code>';
+       var $last = '<code>>|</code>';
+       var $moreLinks = '...';
+       var $startLinks = '...';
+       var $gridHeader = false;
+       var $htmlSpecialChars = true;
+       var $page = 'Page';
+       var $linkSelectedColor = 'red';
+       var $cache = 0;  #secs to cache with CachePageExecute()
+       
+       //----------------------------------------------
+       // constructor
+       //
+       // $db  adodb connection object
+       // $sql sql statement
+       // $id  optional id to identify which pager, 
+       //              if you have multiple on 1 page. 
+       //              $id should be only be [a-z0-9]*
+       //
+       function ADODB_Pager(&$db,$sql,$id = 'adodb', $showPageLinks = false)
+       {
+       global $PHP_SELF;
+       
+               $curr_page = $id.'_curr_page';
+               if (empty($PHP_SELF)) $PHP_SELF = $_SERVER['PHP_SELF'];
+               
+               $this->sql = $sql;
+               $this->id = $id;
+               $this->db = $db;
+               $this->showPageLinks = $showPageLinks;
+               
+               $next_page = $id.'_next_page';  
+               
+               if (isset($_GET[$next_page])) {
+                       $_SESSION[$curr_page] = $_GET[$next_page];
+               }
+               if (empty($_SESSION[$curr_page])) $_SESSION[$curr_page] = 1; ## at first page
+               
+               $this->curr_page = $_SESSION[$curr_page];
+               
+       }
+       
+       //---------------------------
+       // Display link to first page
+       function Render_First($anchor=true)
+       {
+       global $PHP_SELF;
+               if ($anchor) {
+       ?>
+               <a href="<?php echo $PHP_SELF,'?',$this->id;?>_next_page=1"><?php echo $this->first;?></a> &nbsp; 
+       <?php
+               } else {
+                       print "$this->first &nbsp; ";
+               }
+       }
+       
+       //--------------------------
+       // Display link to next page
+       function render_next($anchor=true)
+       {
+       global $PHP_SELF;
+       
+               if ($anchor) {
+               ?>
+               <a href="<?php echo $PHP_SELF,'?',$this->id,'_next_page=',$this->rs->AbsolutePage() + 1 ?>"><?php echo $this->next;?></a> &nbsp; 
+               <?php
+               } else {
+                       print "$this->next &nbsp; ";
+               }
+       }
+       
+       //------------------
+       // Link to last page
+       // 
+       // for better performance with large recordsets, you can set
+       // $this->db->pageExecuteCountRows = false, which disables
+       // last page counting.
+       function render_last($anchor=true)
+       {
+       global $PHP_SELF;
+       
+               if (!$this->db->pageExecuteCountRows) return;
+               
+               if ($anchor) {
+               ?>
+                       <a href="<?php echo $PHP_SELF,'?',$this->id,'_next_page=',$this->rs->LastPageNo() ?>"><?php echo $this->last;?></a> &nbsp; 
+               <?php
+               } else {
+                       print "$this->last &nbsp; ";
+               }
+       }
+       
+       //---------------------------------------------------
+       // original code by "Pablo Costa" <pablo@cbsp.com.br> 
+        function render_pagelinks()
+        {
+        global $PHP_SELF;
+            $pages        = $this->rs->LastPageNo();
+            $linksperpage = $this->linksPerPage ? $this->linksPerPage : $pages;
+            for($i=1; $i <= $pages; $i+=$linksperpage)
+            {
+                if($this->rs->AbsolutePage() >= $i)
+                {
+                    $start = $i;
+                }
+            }
+                       $numbers = '';
+            $end = $start+$linksperpage-1;
+                       $link = $this->id . "_next_page";
+            if($end > $pages) $end = $pages;
+                       
+                       
+                       if ($this->startLinks && $start > 1) {
+                               $pos = $start - 1;
+                               $numbers .= "<a href=$PHP_SELF?$link=$pos>$this->startLinks</a>  ";
+            } 
+                       
+                       for($i=$start; $i <= $end; $i++) {
+                if ($this->rs->AbsolutePage() == $i)
+                    $numbers .= "<font color=$this->linkSelectedColor><b>$i</b></font>  ";
+                else 
+                     $numbers .= "<a href=$PHP_SELF?$link=$i>$i</a>  ";
+            
+            }
+                       if ($this->moreLinks && $end < $pages) 
+                               $numbers .= "<a href=$PHP_SELF?$link=$i>$this->moreLinks</a>  ";
+            print $numbers . ' &nbsp; ';
+        }
+       // Link to previous page
+       function render_prev($anchor=true)
+       {
+       global $PHP_SELF;
+               if ($anchor) {
+       ?>
+               <a href="<?php echo $PHP_SELF,'?',$this->id,'_next_page=',$this->rs->AbsolutePage() - 1 ?>"><?php echo $this->prev;?></a> &nbsp; 
+       <?php 
+               } else {
+                       print "$this->prev &nbsp; ";
+               }
+       }
+       
+       //--------------------------------------------------------
+       // Simply rendering of grid. You should override this for
+       // better control over the format of the grid
+       //
+       // We use output buffering to keep code clean and readable.
+       function RenderGrid()
+       {
+       global $gSQLBlockRows; // used by rs2html to indicate how many rows to display
+               include_once(ADODB_DIR.'/tohtml.inc.php');
+               ob_start();
+               $gSQLBlockRows = $this->rows;
+               rs2html($this->rs,$this->gridAttributes,$this->gridHeader,$this->htmlSpecialChars);
+               $s = ob_get_contents();
+               ob_end_clean();
+               return $s;
+       }
+       
+       //-------------------------------------------------------
+       // Navigation bar
+       //
+       // we use output buffering to keep the code easy to read.
+       function RenderNav()
+       {
+               ob_start();
+               if (!$this->rs->AtFirstPage()) {
+                       $this->Render_First();
+                       $this->Render_Prev();
+               } else {
+                       $this->Render_First(false);
+                       $this->Render_Prev(false);
+               }
+        if ($this->showPageLinks){
+            $this->Render_PageLinks();
+        }
+               if (!$this->rs->AtLastPage()) {
+                       $this->Render_Next();
+                       $this->Render_Last();
+               } else {
+                       $this->Render_Next(false);
+                       $this->Render_Last(false);
+               }
+               $s = ob_get_contents();
+               ob_end_clean();
+               return $s;
+       }
+       
+       //-------------------
+       // This is the footer
+       function RenderPageCount()
+       {
+               if (!$this->db->pageExecuteCountRows) return '';
+               $lastPage = $this->rs->LastPageNo();
+               if ($lastPage == -1) $lastPage = 1; // check for empty rs.
+               if ($this->curr_page > $lastPage) $this->curr_page = 1;
+               return "<font size=-1>$this->page ".$this->curr_page."/".$lastPage."</font>";
+       }
+       
+       //-----------------------------------
+       // Call this class to draw everything.
+       function Render($rows=10)
+       {
+       global $ADODB_COUNTRECS;
+       
+               $this->rows = $rows;
+               
+               if ($this->db->dataProvider == 'informix') $this->db->cursorType = IFX_SCROLL;
+               
+               $savec = $ADODB_COUNTRECS;
+               if ($this->db->pageExecuteCountRows) $ADODB_COUNTRECS = true;
+               if ($this->cache)
+                       $rs = &$this->db->CachePageExecute($this->cache,$this->sql,$rows,$this->curr_page);
+               else
+                       $rs = &$this->db->PageExecute($this->sql,$rows,$this->curr_page);
+               $ADODB_COUNTRECS = $savec;
+               
+               $this->rs = &$rs;
+               if (!$rs) {
+                       print "<h3>Query failed: $this->sql</h3>";
+                       return;
+               }
+               
+               if (!$rs->EOF && (!$rs->AtFirstPage() || !$rs->AtLastPage())) 
+                       $header = $this->RenderNav();
+               else
+                       $header = "&nbsp;";
+               
+               $grid = $this->RenderGrid();
+               $footer = $this->RenderPageCount();
+               $rs->Close();
+               $this->rs = false;
+               
+               $this->RenderLayout($header,$grid,$footer);
+       }
+       
+       //------------------------------------------------------
+       // override this to control overall layout and formating
+       function RenderLayout($header,$grid,$footer,$attributes='border=1 bgcolor=beige')
+       {
+               echo "<table ".$attributes."><tr><td>",
+                               $header,
+                       "</td></tr><tr><td>",
+                               $grid,
+                       "</td></tr><tr><td>",
+                               $footer,
+                       "</td></tr></table>";
+       }
+}
+
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/adodb/adodb/adodb-pear.inc.php b/typo3/sysext/adodb/adodb/adodb-pear.inc.php
new file mode 100644 (file)
index 0000000..e8c8172
--- /dev/null
@@ -0,0 +1,374 @@
+<?php
+/** 
+ * @version V4.68 25 Nov 2005 (c) 2000-2005 John Lim (jlim@natsoft.com.my). All rights reserved.
+ * Released under both BSD license and Lesser GPL library license. 
+ * Whenever there is any discrepancy between the two licenses, 
+ * the BSD license will take precedence. 
+ *
+ * Set tabs to 4 for best viewing.
+ * 
+ * PEAR DB Emulation Layer for ADODB.
+ *
+ * The following code is modelled on PEAR DB code by Stig Bakken <ssb@fast.no>                                                            |
+ * and Tomas V.V.Cox <cox@idecnet.com>.        Portions (c)1997-2002 The PHP Group.
+ */
+
+ /*
+ We support:
+ DB_Common
+ ---------
+       query - returns PEAR_Error on error
+       limitQuery - return PEAR_Error on error
+       prepare - does not return PEAR_Error on error
+       execute - does not return PEAR_Error on error
+       setFetchMode - supports ASSOC and ORDERED
+       errorNative
+       quote
+       nextID
+       disconnect
+       
+       getOne
+       getAssoc
+       getRow
+       getCol
+       getAll
+       
+ DB_Result
+ ---------
+       numRows - returns -1 if not supported
+       numCols
+       fetchInto - does not support passing of fetchmode
+       fetchRows - does not support passing of fetchmode
+       free
+ */
+define('ADODB_PEAR',dirname(__FILE__));
+include_once "PEAR.php";
+include_once ADODB_PEAR."/adodb-errorpear.inc.php";
+include_once ADODB_PEAR."/adodb.inc.php";
+
+if (!defined('DB_OK')) {
+define("DB_OK",        1);
+define("DB_ERROR",-1);
+
+// autoExecute constants
+define('DB_AUTOQUERY_INSERT', 1);
+define('DB_AUTOQUERY_UPDATE', 2);
+
+/**
+ * This is a special constant that tells DB the user hasn't specified
+ * any particular get mode, so the default should be used.
+ */
+
+define('DB_FETCHMODE_DEFAULT', 0);
+
+/**
+ * Column data indexed by numbers, ordered from 0 and up
+ */
+
+define('DB_FETCHMODE_ORDERED', 1);
+
+/**
+ * Column data indexed by column names
+ */
+
+define('DB_FETCHMODE_ASSOC', 2);
+
+/* for compatibility */
+
+define('DB_GETMODE_ORDERED', DB_FETCHMODE_ORDERED);
+define('DB_GETMODE_ASSOC',   DB_FETCHMODE_ASSOC);
+
+/**
+ * these are constants for the tableInfo-function
+ * they are bitwised or'ed. so if there are more constants to be defined
+ * in the future, adjust DB_TABLEINFO_FULL accordingly
+ */
+
+define('DB_TABLEINFO_ORDER', 1);
+define('DB_TABLEINFO_ORDERTABLE', 2);
+define('DB_TABLEINFO_FULL', 3);
+}
+
+/**
+ * The main "DB" class is simply a container class with some static
+ * methods for creating DB objects as well as some utility functions
+ * common to all parts of DB.
+ *
+ */
+
+class DB
+{
+       /**
+        * Create a new DB object for the specified database type
+        *
+        * @param $type string database type, for example "mysql"
+        *
+        * @return object a newly created DB object, or a DB error code on
+        * error
+        */
+
+       function &factory($type)
+       {
+               include_once(ADODB_DIR."/drivers/adodb-$type.inc.php");
+               $obj = &NewADOConnection($type);
+               if (!is_object($obj)) $obj =& new PEAR_Error('Unknown Database Driver: '.$dsninfo['phptype'],-1);
+               return $obj;
+       }
+
+       /**
+        * Create a new DB object and connect to the specified database
+        *
+        * @param $dsn mixed "data source name", see the DB::parseDSN
+        * method for a description of the dsn format.  Can also be
+        * specified as an array of the format returned by DB::parseDSN.
+        *
+        * @param $options mixed if boolean (or scalar), tells whether
+        * this connection should be persistent (for backends that support
+        * this).  This parameter can also be an array of options, see
+        * DB_common::setOption for more information on connection
+        * options.
+        *
+        * @return object a newly created DB connection object, or a DB
+        * error object on error
+        *
+        * @see DB::parseDSN
+        * @see DB::isError
+        */
+       function &connect($dsn, $options = false)
+       {
+               if (is_array($dsn)) {
+                       $dsninfo = $dsn;
+               } else {
+                       $dsninfo = DB::parseDSN($dsn);
+               }
+               switch ($dsninfo["phptype"]) {
+                       case 'pgsql':   $type = 'postgres7'; break;
+                       case 'ifx':             $type = 'informix9'; break;
+                       default:                $type = $dsninfo["phptype"]; break;
+               }
+
+               if (is_array($options) && isset($options["debug"]) &&
+                       $options["debug"] >= 2) {
+                       // expose php errors with sufficient debug level
+                        @include_once("adodb-$type.inc.php");
+               } else {
+                        @include_once("adodb-$type.inc.php");
+               }
+
+               @$obj =& NewADOConnection($type);
+               if (!is_object($obj)) {
+                       $obj =& new PEAR_Error('Unknown Database Driver: '.$dsninfo['phptype'],-1);
+                       return $obj;
+               }
+               if (is_array($options)) {
+                       foreach($options as $k => $v) {
+                               switch(strtolower($k)) {
+                               case 'persist':
+                               case 'persistent':      $persist = $v; break;
+                               #ibase
+                               case 'dialect':         $obj->dialect = $v; break;
+                               case 'charset':         $obj->charset = $v; break;
+                               case 'buffers':         $obj->buffers = $v; break;
+                               #ado
+                               case 'charpage':        $obj->charPage = $v; break;
+                               #mysql
+                               case 'clientflags': $obj->clientFlags = $v; break;
+                               }
+                       }
+               } else {
+                       $persist = false;
+               }
+
+               if (isset($dsninfo['socket'])) $dsninfo['hostspec'] .= ':'.$dsninfo['socket'];
+               else if (isset($dsninfo['port'])) $dsninfo['hostspec'] .= ':'.$dsninfo['port'];
+               
+               if($persist) $ok = $obj->PConnect($dsninfo['hostspec'], $dsninfo['username'],$dsninfo['password'],$dsninfo['database']);
+               else  $ok = $obj->Connect($dsninfo['hostspec'], $dsninfo['username'],$dsninfo['password'],$dsninfo['database']);
+               
+               if (!$ok) $obj = ADODB_PEAR_Error();
+               return $obj;
+       }
+
+       /**
+        * Return the DB API version
+        *
+        * @return int the DB API version number
+        */
+       function apiVersion()
+       {
+               return 2;
+       }
+
+       /**
+        * Tell whether a result code from a DB method is an error
+        *
+        * @param $value int result code
+        *
+        * @return bool whether $value is an error
+        */
+       function isError($value)
+       {
+               if (!is_object($value)) return false;
+               $class = get_class($value);
+               return $class == 'pear_error' || is_subclass_of($value, 'pear_error') || 
+                               $class == 'db_error' || is_subclass_of($value, 'db_error');
+       }
+
+
+       /**
+        * Tell whether a result code from a DB method is a warning.
+        * Warnings differ from errors in that they are generated by DB,
+        * and are not fatal.
+        *
+        * @param $value mixed result value
+        *
+        * @return bool whether $value is a warning
+        */
+       function isWarning($value)
+       {
+               return false;
+               /*
+               return is_object($value) &&
+                       (get_class( $value ) == "db_warning" ||
+                        is_subclass_of($value, "db_warning"));*/
+       }
+
+       /**
+        * Parse a data source name
+        *
+        * @param $dsn string Data Source Name to be parsed
+        *
+        * @return array an associative array with the following keys:
+        *
+        *  phptype: Database backend used in PHP (mysql, odbc etc.)
+        *  dbsyntax: Database used with regards to SQL syntax etc.
+        *  protocol: Communication protocol to use (tcp, unix etc.)
+        *  hostspec: Host specification (hostname[:port])
+        *  database: Database to use on the DBMS server
+        *  username: User name for login
+        *  password: Password for login
+        *
+        * The format of the supplied DSN is in its fullest form:
+        *
+        *  phptype(dbsyntax)://username:password@protocol+hostspec/database
+        *
+        * Most variations are allowed:
+        *
+        *  phptype://username:password@protocol+hostspec:110//usr/db_file.db
+        *  phptype://username:password@hostspec/database_name
+        *  phptype://username:password@hostspec
+        *  phptype://username@hostspec
+        *  phptype://hostspec/database
+        *  phptype://hostspec
+        *  phptype(dbsyntax)
+        *  phptype
+        *
+        * @author Tomas V.V.Cox <cox@idecnet.com>
+        */
+       function parseDSN($dsn)
+       {
+               if (is_array($dsn)) {
+                       return $dsn;
+               }
+
+               $parsed = array(
+                       'phptype'  => false,
+                       'dbsyntax' => false,
+                       'protocol' => false,
+                       'hostspec' => false,
+                       'database' => false,
+                       'username' => false,
+                       'password' => false
+               );
+
+               // Find phptype and dbsyntax
+               if (($pos = strpos($dsn, '://')) !== false) {
+                       $str = substr($dsn, 0, $pos);
+                       $dsn = substr($dsn, $pos + 3);
+               } else {
+                       $str = $dsn;
+                       $dsn = NULL;
+               }
+
+               // Get phptype and dbsyntax
+               // $str => phptype(dbsyntax)
+               if (preg_match('|^(.+?)\((.*?)\)$|', $str, $arr)) {
+                       $parsed['phptype'] = $arr[1];
+                       $parsed['dbsyntax'] = (empty($arr[2])) ? $arr[1] : $arr[2];
+               } else {
+                       $parsed['phptype'] = $str;
+                       $parsed['dbsyntax'] = $str;
+               }
+
+               if (empty($dsn)) {
+                       return $parsed;
+               }
+
+               // Get (if found): username and password
+               // $dsn => username:password@protocol+hostspec/database
+               if (($at = strpos($dsn,'@')) !== false) {
+                       $str = substr($dsn, 0, $at);
+                       $dsn = substr($dsn, $at + 1);
+                       if (($pos = strpos($str, ':')) !== false) {
+                               $parsed['username'] = urldecode(substr($str, 0, $pos));
+                               $parsed['password'] = urldecode(substr($str, $pos + 1));
+                       } else {
+                               $parsed['username'] = urldecode($str);
+                       }
+               }
+
+               // Find protocol and hostspec
+               // $dsn => protocol+hostspec/database
+               if (($pos=strpos($dsn, '/')) !== false) {
+                       $str = substr($dsn, 0, $pos);
+                       $dsn = substr($dsn, $pos + 1);
+               } else {
+                       $str = $dsn;
+                       $dsn = NULL;
+               }
+
+               // Get protocol + hostspec
+               // $str => protocol+hostspec
+               if (($pos=strpos($str, '+')) !== false) {
+                       $parsed['protocol'] = substr($str, 0, $pos);
+                       $parsed['hostspec'] = urldecode(substr($str, $pos + 1));
+               } else {
+                       $parsed['hostspec'] = urldecode($str);
+               }
+
+               // Get dabase if any
+               // $dsn => database
+               if (!empty($dsn)) {
+                       $parsed['database'] = $dsn;
+               }
+
+               return $parsed;
+       }
+
+       /**
+        * Load a PHP database extension if it is not loaded already.
+        *
+        * @access public
+        *
+        * @param $name the base name of the extension (without the .so or
+        * .dll suffix)
+        *
+        * @return bool true if the extension was already or successfully
+        * loaded, false if it could not be loaded
+        */
+       function assertExtension($name)
+       {
+               if (!extension_loaded($name)) {
+                       $dlext = (strncmp(PHP_OS,'WIN',3) === 0) ? '.dll' : '.so';
+                       @dl($name . $dlext);
+               }
+               if (!extension_loaded($name)) {
+                       return false;
+               }
+               return true;
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/adodb/adodb/adodb-perf.inc.php b/typo3/sysext/adodb/adodb/adodb-perf.inc.php
new file mode 100644 (file)
index 0000000..ff376be
--- /dev/null
@@ -0,0 +1,1053 @@
+<?php
+/* 
+V4.68 25 Nov 2005  (c) 2000-2005 John Lim (jlim@natsoft.com.my). All rights reserved.
+  Released under both BSD license and Lesser GPL library license. 
+  Whenever there is any discrepancy between the two licenses, 
+  the BSD license will take precedence. See License.txt. 
+  Set tabs to 4 for best viewing.
+  
+  Latest version is available at http://adodb.sourceforge.net
+  
+  Library for basic performance monitoring and tuning.
+  
+  My apologies if you see code mixed with presentation. The presentation suits
+  my needs. If you want to separate code from presentation, be my guest. Patches
+  are welcome.
+  
+*/
+
+if (!defined(ADODB_DIR)) include_once(dirname(__FILE__).'/adodb.inc.php');
+include_once(ADODB_DIR.'/tohtml.inc.php');
+
+define( 'ADODB_OPT_HIGH', 2);
+define( 'ADODB_OPT_LOW', 1);
+
+// returns in K the memory of current process, or 0 if not known
+function adodb_getmem()
+{
+       if (function_exists('memory_get_usage'))
+               return (integer) ((memory_get_usage()+512)/1024);
+       
+       $pid = getmypid();
+       
+       if ( strncmp(strtoupper(PHP_OS),'WIN',3)==0) {
+               $output = array();
+       
+               exec('tasklist /FI "PID eq ' . $pid. '" /FO LIST', $output); 
+               return substr($output[5], strpos($output[5], ':') + 1);
+       } 
+       
+       /* Hopefully UNIX */
+       exec("ps --pid $pid --no-headers -o%mem,size", $output);
+       if (sizeof($output) == 0) return 0;
+       
+       $memarr = explode(' ',$output[0]);
+       if (sizeof($memarr)>=2) return (integer) $memarr[1];
+       
+       return 0;
+}
+
+// avoids localization problems where , is used instead of .
+function adodb_round($n,$prec)
+{
+       return number_format($n, $prec, '.', '');
+}
+
+/* return microtime value as a float */
+function adodb_microtime()
+{
+       $t = microtime();
+       $t = explode(' ',$t);
+       return (float)$t[1]+ (float)$t[0];
+}
+
+/* sql code timing */
+function& adodb_log_sql(&$conn,$sql,$inputarr)
+{
+       
+    $perf_table = adodb_perf::table();
+       $conn->fnExecute = false;
+       $t0 = microtime();
+       $rs =& $conn->Execute($sql,$inputarr);
+       $t1 = microtime();
+
+       if (!empty($conn->_logsql)) {
+               $conn->_logsql = false; // disable logsql error simulation
+               $dbT = $conn->databaseType;
+               
+               $a0 = split(' ',$t0);
+               $a0 = (float)$a0[1]+(float)$a0[0];
+               
+               $a1 = split(' ',$t1);
+               $a1 = (float)$a1[1]+(float)$a1[0];
+               
+               $time = $a1 - $a0;
+       
+               if (!$rs) {
+                       $errM = $conn->ErrorMsg();
+                       $errN = $conn->ErrorNo();
+                       $conn->lastInsID = 0;
+                       $tracer = substr('ERROR: '.htmlspecialchars($errM),0,250);
+               } else {
+                       $tracer = '';
+                       $errM = '';
+                       $errN = 0;
+                       $dbg = $conn->debug;
+                       $conn->debug = false;
+                       if (!is_object($rs) || $rs->dataProvider == 'empty') 
+                               $conn->_affected = $conn->affected_rows(true);
+                       $conn->lastInsID = @$conn->Insert_ID();
+                       $conn->debug = $dbg;
+               }
+               if (isset($_SERVER['HTTP_HOST'])) {
+                       $tracer .= '<br>'.$_SERVER['HTTP_HOST'];
+                       if (isset($_SERVER['PHP_SELF'])) $tracer .= $_SERVER['PHP_SELF'];
+               } else 
+                       if (isset($_SERVER['PHP_SELF'])) $tracer .= '<br>'.$_SERVER['PHP_SELF'];
+               //$tracer .= (string) adodb_backtrace(false);
+               
+               $tracer = (string) substr($tracer,0,500);
+               
+               if (is_array($inputarr)) {
+                       if (is_array(reset($inputarr))) $params = 'Array sizeof='.sizeof($inputarr);
+                       else {
+                               // Quote string parameters so we can see them in the
+                               // performance stats. This helps spot disabled indexes.
+                               $xar_params = $inputarr;
+                               foreach ($xar_params as $xar_param_key => $xar_param) {
+                                       if (gettype($xar_param) == 'string')
+                                       $xar_params[$xar_param_key] = '"' . $xar_param . '"';
+                               }
+                               $params = implode(', ', $xar_params);
+                               if (strlen($params) >= 3000) $params = substr($params, 0, 3000);
+                       }
+               } else {
+                       $params = '';
+               }
+               
+               if (is_array($sql)) $sql = $sql[0];
+               $arr = array('b'=>strlen($sql).'.'.crc32($sql),
+                                       'c'=>substr($sql,0,3900), 'd'=>$params,'e'=>$tracer,'f'=>adodb_round($time,6));
+               //var_dump($arr);
+               $saved = $conn->debug;
+               $conn->debug = 0;
+               
+               $d = $conn->sysTimeStamp;
+               if (empty($d)) $d = date("'Y-m-d H:i:s'");
+               if ($conn->dataProvider == 'oci8' && $dbT != 'oci8po') {
+                       $isql = "insert into $perf_table values($d,:b,:c,:d,:e,:f)";
+               } else if ($dbT == 'odbc_mssql' || $dbT == 'informix' || $dbT == 'odbtp') {
+                       $timer = $arr['f'];
+                       if ($dbT == 'informix') $sql2 = substr($sql2,0,230);
+
+                       $sql1 = $conn->qstr($arr['b']);
+                       $sql2 = $conn->qstr($arr['c']);
+                       $params = $conn->qstr($arr['d']);
+                       $tracer = $conn->qstr($arr['e']);
+                       
+                       $isql = "insert into $perf_table (created,sql0,sql1,params,tracer,timer) values($d,$sql1,$sql2,$params,$tracer,$timer)";
+                       if ($dbT == 'informix') $isql = str_replace(chr(10),' ',$isql);
+                       $arr = false;
+               } else {
+                       $isql = "insert into $perf_table (created,sql0,sql1,params,tracer,timer) values( $d,?,?,?,?,?)";
+               }
+
+               $ok = $conn->Execute($isql,$arr);
+               $conn->debug = $saved;
+               
+               if ($ok) {
+                       $conn->_logsql = true; 
+               } else {
+                       $err2 = $conn->ErrorMsg();
+                       $conn->_logsql = true; // enable logsql error simulation
+                       $perf =& NewPerfMonitor($conn);
+                       if ($perf) {
+                               if ($perf->CreateLogTable()) $ok = $conn->Execute($isql,$arr);
+                       } else {
+                               $ok = $conn->Execute("create table $perf_table (
+                               created varchar(50),
+                               sql0 varchar(250), 
+                               sql1 varchar(4000),
+                               params varchar(3000),
+                               tracer varchar(500),
+                               timer decimal(16,6))");
+                       }
+                       if (!$ok) {
+                               ADOConnection::outp( "<p><b>LOGSQL Insert Failed</b>: $isql<br>$err2</p>");
+                               $conn->_logsql = false;
+                       }
+               }
+               $conn->_errorMsg = $errM;
+               $conn->_errorCode = $errN;
+       } 
+       $conn->fnExecute = 'adodb_log_sql';
+       return $rs;
+}
+
+       
+/*
+The settings data structure is an associative array that database parameter per element.
+
+Each database parameter element in the array is itself an array consisting of:
+
+0: category code, used to group related db parameters
+1: either
+       a. sql string to retrieve value, eg. "select value from v\$parameter where name='db_block_size'", 
+       b. array holding sql string and field to look for, e.g. array('show variables','table_cache'),
+       c. a string prefixed by =, then a PHP method of the class is invoked, 
+               e.g. to invoke $this->GetIndexValue(), set this array element to '=GetIndexValue',
+2: description of the database parameter
+*/
+
+class adodb_perf {
+       var $conn;
+       var $color = '#F0F0F0';
+       var $table = '<table border=1 bgcolor=white>';
+       var $titles = '<tr><td><b>Parameter</b></td><td><b>Value</b></td><td><b>Description</b></td></tr>';
+       var $warnRatio = 90;
+       var $tablesSQL = false;
+       var $cliFormat = "%32s => %s \r\n";
+       var $sql1 = 'sql1';  // used for casting sql1 to text for mssql
+       var $explain = true;
+       var $helpurl = "<a href=http://phplens.com/adodb/reference.functions.fnexecute.and.fncacheexecute.properties.html#logsql>LogSQL help</a>";
+       var $createTableSQL = false;
+       var $maxLength = 2000;
+       
+    // Sets the tablename to be used            
+    function table($newtable = false)
+    {
+        static $_table;
+
+        if (!empty($newtable))  $_table = $newtable;
+               if (empty($_table)) $_table = 'adodb_logsql';
+        return $_table;
+    }
+
+       // returns array with info to calculate CPU Load
+       function _CPULoad()
+       {
+/*
+
+cpu  524152 2662 2515228 336057010
+cpu0 264339 1408 1257951 168025827
+cpu1 259813 1254 1257277 168031181
+page 622307 25475680
+swap 24 1891
+intr 890153570 868093576 6 0 4 4 0 6 1 2 0 0 0 124 0 8098760 2 13961053 0 0 0 0 0 0 0 0 0 0 0 0 0 16 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+disk_io: (3,0):(3144904,54369,610378,3090535,50936192) (3,1):(3630212,54097,633016,3576115,50951320)
+ctxt 66155838
+btime 1062315585
+processes 69293
+
+*/
+               // Algorithm is taken from
+               // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/example__obtaining_raw_performance_data.asp
+               if (strncmp(PHP_OS,'WIN',3)==0) {
+                       if (PHP_VERSION == '5.0.0') return false;
+                       if (PHP_VERSION == '5.0.1') return false;
+                       if (PHP_VERSION == '5.0.2') return false;
+                       if (PHP_VERSION == '5.0.3') return false;
+                       if (PHP_VERSION == '4.3.10') return false; # see http://bugs.php.net/bug.php?id=31737
+                       
+                       @$c = new COM("WinMgmts:{impersonationLevel=impersonate}!Win32_PerfRawData_PerfOS_Processor.Name='_Total'");
+                       if (!$c) return false;
+                       
+                       $info[0] = $c->PercentProcessorTime;
+                       $info[1] = 0;
+                       $info[2] = 0;
+                       $info[3] = $c->TimeStamp_Sys100NS;
+                       //print_r($info);
+                       return $info;
+               }
+               
+               // Algorithm - Steve Blinch (BlitzAffe Online, http://www.blitzaffe.com)
+               $statfile = '/proc/stat';
+               if (!file_exists($statfile)) return false;
+               
+               $fd = fopen($statfile,"r");
+               if (!$fd) return false;
+               
+               $statinfo = explode("\n",fgets($fd, 1024));
+               fclose($fd);
+               foreach($statinfo as $line) {
+                       $info = explode(" ",$line);
+                       if($info[0]=="cpu") {
+                               array_shift($info);  // pop off "cpu"
+                               if(!$info[0]) array_shift($info); // pop off blank space (if any)
+                               return $info;
+                       }
+               }
+               
+               return false;
+               
+       }
+       
+       /* NOT IMPLEMENTED */
+       function MemInfo()
+       {
+               /*
+
+        total:    used:    free:  shared: buffers:  cached:
+Mem:  1055289344 917299200 137990144        0 165437440 599773184
+Swap: 2146775040 11055104 2135719936
+MemTotal:      1030556 kB
+MemFree:        134756 kB
+MemShared:           0 kB
+Buffers:        161560 kB
+Cached:         581384 kB
+SwapCached:       4332 kB
+Active:         494468 kB
+Inact_dirty:    322856 kB
+Inact_clean:     24256 kB
+Inact_target:   168316 kB
+HighTotal:      131064 kB
+HighFree:         1024 kB
+LowTotal:       899492 kB
+LowFree:        133732 kB
+SwapTotal:     2096460 kB
+SwapFree:      2085664 kB
+Committed_AS:   348732 kB
+               */
+       }
+       
+       
+       /*
+               Remember that this is client load, not db server load!
+       */
+       var $_lastLoad;
+       function CPULoad()
+       {
+               $info = $this->_CPULoad();
+               if (!$info) return false;
+                       
+               if (empty($this->_lastLoad)) {
+                       sleep(1);
+                       $this->_lastLoad = $info;
+                       $info = $this->_CPULoad();
+               }
+               
+               $last = $this->_lastLoad;
+               $this->_lastLoad = $info;
+               
+               $d_user = $info[0] - $last[0];
+               $d_nice = $info[1] - $last[1];
+               $d_system = $info[2] - $last[2];
+               $d_idle = $info[3] - $last[3];
+               
+               //printf("Delta - User: %f  Nice: %f  System: %f  Idle: %f<br>",$d_user,$d_nice,$d_system,$d_idle);
+
+               if (strncmp(PHP_OS,'WIN',3)==0) {
+                       if ($d_idle < 1) $d_idle = 1;
+                       return 100*(1-$d_user/$d_idle);
+               }else {
+                       $total=$d_user+$d_nice+$d_system+$d_idle;
+                       if ($total<1) $total=1;
+                       return 100*($d_user+$d_nice+$d_system)/$total; 
+               }
+       }
+       
+       function Tracer($sql)
+       {
+        $perf_table = adodb_perf::table();
+               $saveE = $this->conn->fnExecute;
+               $this->conn->fnExecute = false;
+               
+               global $ADODB_FETCH_MODE;
+               $save = $ADODB_FETCH_MODE;
+               $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+               if ($this->conn->fetchMode !== false) $savem = $this->conn->SetFetchMode(false);
+                               
+               $sqlq = $this->conn->qstr($sql);
+               $arr = $this->conn->GetArray(
+"select count(*),tracer 
+       from $perf_table where sql1=$sqlq 
+       group by tracer
+       order by 1 desc");
+               $s = '';
+               if ($arr) {
+                       $s .= '<h3>Scripts Affected</h3>';
+                       foreach($arr as $k) {
+                               $s .= sprintf("%4d",$k[0]).' &nbsp; '.strip_tags($k[1]).'<br>';
+                       }
+               }
+               
+               if (isset($savem)) $this->conn->SetFetchMode($savem);
+               $ADODB_CACHE_MODE = $save;
+               $this->conn->fnExecute = $saveE;
+               return $s;
+       }
+
+       /* 
+               Explain Plan for $sql.
+               If only a snippet of the $sql is passed in, then $partial will hold the crc32 of the 
+                       actual sql.
+       */
+       function Explain($sql,$partial=false)
+       {       
+               return false;
+       }
+       
+       function InvalidSQL($numsql = 10)
+       {
+       
+               if (isset($_GET['sql'])) return;
+               $s = '<h3>Invalid SQL</h3>';
+               $saveE = $this->conn->fnExecute;
+               $this->conn->fnExecute = false;
+        $perf_table = adodb_perf::table();
+               $rs =& $this->conn->SelectLimit("select distinct count(*),sql1,tracer as error_msg from $perf_table where tracer like 'ERROR:%' group by sql1,tracer order by 1 desc",$numsql);//,$numsql);
+               $this->conn->fnExecute = $saveE;
+               if ($rs) {
+                       $s .= rs2html($rs,false,false,false,false);
+               } else
+                       return "<p>$this->helpurl. ".$this->conn->ErrorMsg()."</p>";
+               
+               return $s;
+       }
+
+       
+       /*
+               This script identifies the longest running SQL
+       */      
+       function _SuspiciousSQL($numsql = 10)
+       {
+               global $ADODB_FETCH_MODE;
+               
+            $perf_table = adodb_perf::table();
+                       $saveE = $this->conn->fnExecute;
+                       $this->conn->fnExecute = false;
+                       
+                       if (isset($_GET['exps']) && isset($_GET['sql'])) {
+                               $partial = !empty($_GET['part']);
+                               echo "<a name=explain></a>".$this->Explain($_GET['sql'],$partial)."\n";
+                       }
+                       
+                       if (isset($_GET['sql'])) return;
+                       $sql1 = $this->sql1;
+                       
+                       $save = $ADODB_FETCH_MODE;
+                       $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+                       if ($this->conn->fetchMode !== false) $savem = $this->conn->SetFetchMode(false);
+                       //$this->conn->debug=1;
+                       $rs =& $this->conn->SelectLimit(
+                       "select avg(timer) as avg_timer,$sql1,count(*),max(timer) as max_timer,min(timer) as min_timer
+                               from $perf_table
+                               where {$this->conn->upperCase}({$this->conn->substr}(sql0,1,5)) not in ('DROP ','INSER','COMMI','CREAT')
+                               and (tracer is null or tracer not like 'ERROR:%')
+                               group by sql1
+                               order by 1 desc",$numsql);
+                       if (isset($savem)) $this->conn->SetFetchMode($savem);
+                       $ADODB_FETCH_MODE = $save;
+                       $this->conn->fnExecute = $saveE;
+                       
+                       if (!$rs) return "<p>$this->helpurl. ".$this->conn->ErrorMsg()."</p>";
+                       $s = "<h3>Suspicious SQL</h3>
+<font size=1>The following SQL have high average execution times</font><br>
+<table border=1 bgcolor=white><tr><td><b>Avg Time</b><td><b>Count</b><td><b>SQL</b><td><b>Max</b><td><b>Min</b></tr>\n";
+                       $max = $this->maxLength;
+                       while (!$rs->EOF) {
+                               $sql = $rs->fields[1];
+                               $raw = urlencode($sql);
+                               if (strlen($raw)>$max-100) {
+                                       $sql2 = substr($sql,0,$max-500);
+                                       $raw = urlencode($sql2).'&part='.crc32($sql);
+                               }
+                               $prefix = "<a target=sql".rand()." href=\"?hidem=1&exps=1&sql=".$raw."&x#explain\">";
+                               $suffix = "</a>";
+                               if ($this->explain == false || strlen($prefix)>$max) {
+                                       $suffix = ' ... <i>String too long for GET parameter: '.strlen($prefix).'</i>';
+                                       $prefix = '';
+                               }
+                               $s .= "<tr><td>".adodb_round($rs->fields[0],6)."<td align=right>".$rs->fields[2]."<td><font size=-1>".$prefix.htmlspecialchars($sql).$suffix."</font>".
+                                       "<td>".$rs->fields[3]."<td>".$rs->fields[4]."</tr>";
+                               $rs->MoveNext();
+                       }
+                       return $s."</table>";
+               
+       }
+       
+       function CheckMemory()
+       {
+               return '';
+       }
+       
+       
+       function SuspiciousSQL($numsql=10)
+       {
+               return adodb_perf::_SuspiciousSQL($numsql);
+       }
+
+       function ExpensiveSQL($numsql=10)
+       {
+               return adodb_perf::_ExpensiveSQL($numsql);
+       }
+
+       
+       /*
+               This reports the percentage of load on the instance due to the most 
+               expensive few SQL statements. Tuning these statements can often 
+               make huge improvements in overall system performance. 
+       */
+       function _ExpensiveSQL($numsql = 10)
+       {
+               global $ADODB_FETCH_MODE;
+               
+            $perf_table = adodb_perf::table();
+                       $saveE = $this->conn->fnExecute;
+                       $this->conn->fnExecute = false;
+                       
+                       if (isset($_GET['expe']) && isset($_GET['sql'])) {
+                               $partial = !empty($_GET['part']);
+                               echo "<a name=explain></a>".$this->Explain($_GET['sql'],$partial)."\n";
+                       }
+                       
+                       if (isset($_GET['sql'])) return;
+                       
+                       $sql1 = $this->sql1;
+                       $save = $ADODB_FETCH_MODE;
+                       $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+                       if ($this->conn->fetchMode !== false) $savem = $this->conn->SetFetchMode(false);
+                       
+                       $rs =& $this->conn->SelectLimit(
+                       "select sum(timer) as total,$sql1,count(*),max(timer) as max_timer,min(timer) as min_timer
+                               from $perf_table
+                               where {$this->conn->upperCase}({$this->conn->substr}(sql0,1,5))  not in ('DROP ','INSER','COMMI','CREAT')
+                               and (tracer is null or tracer not like 'ERROR:%')
+                               group by sql1
+                               having count(*)>1
+                               order by 1 desc",$numsql);
+                       if (isset($savem)) $this->conn->SetFetchMode($savem);
+                       $this->conn->fnExecute = $saveE;
+                       $ADODB_FETCH_MODE = $save;
+                       if (!$rs) return "<p>$this->helpurl. ".$this->conn->ErrorMsg()."</p>";
+                       $s = "<h3>Expensive SQL</h3>
+<font size=1>Tuning the following SQL could reduce the server load substantially</font><br>
+<table border=1 bgcolor=white><tr><td><b>Load</b><td><b>Count</b><td><b>SQL</b><td><b>Max</b><td><b>Min</b></tr>\n";
+                       $max = $this->maxLength;
+                       while (!$rs->EOF) {
+                               $sql = $rs->fields[1];
+                               $raw = urlencode($sql);
+                               if (strlen($raw)>$max-100) {
+                                       $sql2 = substr($sql,0,$max-500);
+                                       $raw = urlencode($sql2).'&part='.crc32($sql);
+                               }
+                               $prefix = "<a target=sqle".rand()." href=\"?hidem=1&expe=1&sql=".$raw."&x#explain\">";
+                               $suffix = "</a>";
+                               if($this->explain == false || strlen($prefix>$max)) {
+                                       $prefix = '';
+                                       $suffix = '';
+                               }
+                               $s .= "<tr><td>".adodb_round($rs->fields[0],6)."<td align=right>".$rs->fields[2]."<td><font size=-1>".$prefix.htmlspecialchars($sql).$suffix."</font>".
+                                       "<td>".$rs->fields[3]."<td>".$rs->fields[4]."</tr>";
+                               $rs->MoveNext();
+                       }
+                       return $s."</table>";
+       }
+       
+       /*
+               Raw function to return parameter value from $settings.
+       */
+       function DBParameter($param)
+       {
+               if (empty($this->settings[$param])) return false;
+               $sql = $this->settings[$param][1];
+               return $this->_DBParameter($sql);
+       }
+       
+       /*
+               Raw function returning array of poll paramters
+       */
+       function &PollParameters()
+       {
+               $arr[0] = (float)$this->DBParameter('data cache hit ratio');
+               $arr[1] = (float)$this->DBParameter('data reads');
+               $arr[2] = (float)$this->DBParameter('data writes');
+               $arr[3] = (integer) $this->DBParameter('current connections');
+               return $arr;
+       }
+       
+       /*
+               Low-level Get Database Parameter
+       */
+       function _DBParameter($sql)
+       {
+               $savelog = $this->conn->LogSQL(false);
+               if (is_array($sql)) {
+               global $ADODB_FETCH_MODE;
+               
+                       $sql1 = $sql[0];
+                       $key = $sql[1];
+                       if (sizeof($sql)>2) $pos = $sql[2];
+                       else $pos = 1;
+                       if (sizeof($sql)>3) $coef = $sql[3];
+                       else $coef = false;
+                       $ret = false;
+                       $save = $ADODB_FETCH_MODE;
+                       $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+                       if ($this->conn->fetchMode !== false) $savem = $this->conn->SetFetchMode(false);
+                       
+                       $rs = $this->conn->Execute($sql1);
+                       
+                       if (isset($savem)) $this->SetFetchMode($savem);
+                       $ADODB_FETCH_MODE = $save;
+                       if ($rs) {
+                               while (!$rs->EOF) {
+                                       $keyf = reset($rs->fields);
+                                       if (trim($keyf) == $key) {
+                                               $ret = $rs->fields[$pos];
+                                               if ($coef) $ret *= $coef;
+                                               break;
+                                       }
+                                       $rs->MoveNext();
+                               }
+                               $rs->Close();
+                       }
+                       $this->conn->LogSQL($savelog);
+                       return $ret;
+               } else {
+                       if (strncmp($sql,'=',1) == 0) {
+                               $fn = substr($sql,1);
+                               return $this->$fn();
+                       }
+                       $sql = str_replace('$DATABASE',$this->conn->database,$sql);
+                       $ret = $this->conn->GetOne($sql);
+                       $this->conn->LogSQL($savelog);
+                       
+                       return $ret;
+               }
+       }
+       
+       /*
+               Warn if cache ratio falls below threshold. Displayed in "Description" column.
+       */
+       function WarnCacheRatio($val)
+       {
+               if ($val < $this->warnRatio) 
+                        return '<font color=red><b>Cache ratio should be at least '.$this->warnRatio.'%</b></font>';
+               else return '';
+       }
+       
+       /***********************************************************************************************/
+       //                                    HIGH LEVEL UI FUNCTIONS
+       /***********************************************************************************************/
+
+       
+       function UI($pollsecs=5)
+       {
+       
+    $perf_table = adodb_perf::table();
+       $conn = $this->conn;
+       
+       $app = $conn->host;
+       if ($conn->host && $conn->database) $app .= ', db=';
+       $app .= $conn->database;
+       
+       if ($app) $app .= ', ';
+       $savelog = $this->conn->LogSQL(false);  
+       $info = $conn->ServerInfo();
+       if (isset($_GET['clearsql'])) {
+               $this->conn->Execute("delete from $perf_table");
+       }
+       $this->conn->LogSQL($savelog);
+       
+       // magic quotes
+       
+       if (isset($_GET['sql']) && get_magic_quotes_gpc()) {
+               $_GET['sql'] = $_GET['sql'] = str_replace(array("\\'",'\"'),array("'",'"'),$_GET['sql']);
+       }
+       
+       if (!isset($_SESSION['ADODB_PERF_SQL'])) $nsql = $_SESSION['ADODB_PERF_SQL'] = 10;
+       else  $nsql = $_SESSION['ADODB_PERF_SQL'];
+       
+       $app .= $info['description'];
+       
+       
+       if (isset($_GET['do'])) $do = $_GET['do'];
+       else if (isset($_POST['do'])) $do = $_POST['do'];
+        else if (isset($_GET['sql'])) $do = 'viewsql';
+        else $do = 'stats';
+        
+       if (isset($_GET['nsql'])) {
+               if ($_GET['nsql'] > 0) $nsql = $_SESSION['ADODB_PERF_SQL'] = (integer) $_GET['nsql'];
+       }
+       echo "<title>ADOdb Performance Monitor on $app</title><body bgcolor=white>";
+       if ($do == 'viewsql') $form = "<td><form># SQL:<input type=hidden value=viewsql name=do> <input type=text size=4 name=nsql value=$nsql><input type=submit value=Go></td></form>";
+       else $form = "<td>&nbsp;</td>";
+       
+       $allowsql = !defined('ADODB_PERF_NO_RUN_SQL');
+       
+       if  (empty($_GET['hidem']))
+       echo "<table border=1 width=100% bgcolor=lightyellow><tr><td colspan=2>
+       <b><a href=http://adodb.sourceforge.net/?perf=1>ADOdb</a> Performance Monitor</b> <font size=1>for $app</font></tr><tr><td>
+       <a href=?do=stats><b>Performance Stats</b></a> &nbsp; <a href=?do=viewsql><b>View SQL</b></a>
+        &nbsp; <a href=?do=tables><b>View Tables</b></a> &nbsp; <a href=?do=poll><b>Poll Stats</b></a>",
+        $allowsql ? ' &nbsp; <a href=?do=dosql><b>Run SQL</b></a>' : '',
+        "$form",
+        "</tr></table>";
+
+        
+               switch ($do) {
+               default:
+               case 'stats':
+                       echo $this->HealthCheck();
+                       //$this->conn->debug=1;
+                       echo $this->CheckMemory();
+                       break;
+               case 'poll':
+                       echo "<iframe width=720 height=80% 
+                               src=\"{$_SERVER['PHP_SELF']}?do=poll2&hidem=1\"></iframe>";
+                       break;
+               case 'poll2':
+                       echo "<pre>";
+                       $this->Poll($pollsecs);
+                       break;
+               
+               case 'dosql':
+                       if (!$allowsql) break;
+                       
+                       $this->DoSQLForm();
+                       break;
+               case 'viewsql':
+                       if (empty($_GET['hidem']))
+                               echo "&nbsp; <a href=\"?do=viewsql&clearsql=1\">Clear SQL Log</a><br>";
+                       echo($this->SuspiciousSQL($nsql));
+                       echo($this->ExpensiveSQL($nsql));
+                       echo($this->InvalidSQL($nsql));
+                       break;
+               case 'tables': 
+                       echo $this->Tables(); break;
+               }
+               global $ADODB_vers;
+               echo "<p><div align=center><font size=1>$ADODB_vers Sponsored by <a href=http://phplens.com/>phpLens</a></font></div>";
+       }
+       
+       /*
+               Runs in infinite loop, returning real-time statistics
+       */
+       function Poll($secs=5)
+       {
+               $this->conn->fnExecute = false;
+               //$this->conn->debug=1;
+               if ($secs <= 1) $secs = 1;
+               echo "Accumulating statistics, every $secs seconds...\n";flush();
+               $arro =& $this->PollParameters();
+               $cnt = 0;
+               set_time_limit(0);
+               sleep($secs);
+               while (1) {
+
+                       $arr =& $this->PollParameters();
+                       
+                       $hits   = sprintf('%2.2f',$arr[0]);
+                       $reads  = sprintf('%12.4f',($arr[1]-$arro[1])/$secs);
+                       $writes = sprintf('%12.4f',($arr[2]-$arro[2])/$secs);
+                       $sess = sprintf('%5d',$arr[3]);
+                       
+                       $load = $this->CPULoad();
+                       if ($load !== false) {
+                               $oslabel = 'WS-CPU%';
+                               $osval = sprintf(" %2.1f  ",(float) $load);
+                       }else {
+                               $oslabel = '';
+                               $osval = '';
+                       }
+                       if ($cnt % 10 == 0) echo " Time   ".$oslabel."   Hit%   Sess           Reads/s          Writes/s\n"; 
+                       $cnt += 1;
+                       echo date('H:i:s').'  '.$osval."$hits  $sess $reads $writes\n";
+                       flush();
+                       
+                       if (connection_aborted()) return;
+                       
+                       sleep($secs);
+                       $arro = $arr;
+               }
+       }
+       
+       /*
+               Returns basic health check in a command line interface
+       */
+       function HealthCheckCLI()
+       {
+               return $this->HealthCheck(true);
+       }
+       
+               
+       /*
+               Returns basic health check as HTML
+       */
+       function HealthCheck($cli=false)
+       {
+               $saveE = $this->conn->fnExecute;
+               $this->conn->fnExecute = false; 
+               if ($cli) $html = '';
+               else $html = $this->table.'<tr><td colspan=3><h3>'.$this->conn->databaseType.'</h3></td></tr>'.$this->titles;
+               
+               $oldc = false;
+               $bgc = '';
+               foreach($this->settings as $name => $arr) {
+                       if ($arr === false) break;
+                       
+                       if (!is_string($name)) {
+                               if ($cli) $html .= " -- $arr -- \n";
+                               else $html .= "<tr bgcolor=$this->color><td colspan=3><i>$arr</i> &nbsp;</td></tr>";
+                               continue;
+                       }
+                       
+                       if (!is_array($arr)) break;
+                       $category = $arr[0];
+                       $how = $arr[1];
+                       if (sizeof($arr)>2) $desc = $arr[2];
+                       else $desc = ' &nbsp; ';
+                       
+                       
+                       if ($category == 'HIDE') continue;
+                       
+                       $val = $this->_DBParameter($how);
+                       
+                       if ($desc && strncmp($desc,"=",1) === 0) {
+                               $fn = substr($desc,1);
+                               $desc = $this->$fn($val);
+                       }
+                       
+                       if ($val === false) {
+                               $m = $this->conn->ErrorMsg();
+                               $val = "Error: $m"; 
+                       } else {
+                               if (is_numeric($val) && $val >= 256*1024) {
+                                       if ($val % (1024*1024) == 0) {
+                                               $val /= (1024*1024);
+                                               $val .= 'M';
+                                       } else if ($val % 1024 == 0) {
+                                               $val /= 1024;
+                                               $val .= 'K';
+                                       }
+                                       //$val = htmlspecialchars($val);
+                               }
+                       }
+                       if ($category != $oldc) {
+                               $oldc = $category;
+                               //$bgc = ($bgc == ' bgcolor='.$this->color) ? ' bgcolor=white' : ' bgcolor='.$this->color;
+                       }
+                       if (strlen($desc)==0) $desc = '&nbsp;';
+                       if (strlen($val)==0) $val = '&nbsp;';
+                       if ($cli) {
+                               $html  .= str_replace('&nbsp;','',sprintf($this->cliFormat,strip_tags($name),strip_tags($val),strip_tags($desc)));
+                               
+                       }else {
+                               $html .= "<tr$bgc><td>".$name.'</td><td>'.$val.'</td><td>'.$desc."</td></tr>\n";
+                       }
+               }
+               
+               if (!$cli) $html .= "</table>\n";
+               $this->conn->fnExecute = $saveE;
+                       
+               return $html;   
+       }
+       
+       function Tables($orderby='1')
+       {
+               if (!$this->tablesSQL) return false;
+               
+               $savelog = $this->conn->LogSQL(false);
+               $rs = $this->conn->Execute($this->tablesSQL.' order by '.$orderby);
+               $this->conn->LogSQL($savelog);
+               $html = rs2html($rs,false,false,false,false);
+               return $html;
+       }
+       
+
+       function CreateLogTable()
+       {
+               if (!$this->createTableSQL) return false;
+               
+               $savelog = $this->conn->LogSQL(false);
+               $ok = $this->conn->Execute($this->createTableSQL);
+               $this->conn->LogSQL($savelog);
+               return ($ok) ? true : false;
+       }
+       
+       function DoSQLForm()
+       {
+       
+               
+               $PHP_SELF = $_SERVER['PHP_SELF'];
+               $sql = isset($_REQUEST['sql']) ? $_REQUEST['sql'] : '';
+
+               if (isset($_SESSION['phplens_sqlrows'])) $rows = $_SESSION['phplens_sqlrows'];
+               else $rows = 3;
+               
+               if (isset($_REQUEST['SMALLER'])) {
+                       $rows /= 2;
+                       if ($rows < 3) $rows = 3;
+                       $_SESSION['phplens_sqlrows'] = $rows;
+               }
+               if (isset($_REQUEST['BIGGER'])) {
+                       $rows *= 2;
+                       $_SESSION['phplens_sqlrows'] = $rows;
+               }
+               
+?>
+
+<form method="POST" action="<?php echo $PHP_SELF ?>">
+<table><tr>
+<td> Form size: <input type="submit" value=" &lt; " name="SMALLER"><input type="submit" value=" &gt; &gt; " name="BIGGER">
+</td>
+<td align=right>
+<input type="submit" value=" Run SQL Below " name="RUN"><input type=hidden name=do value=dosql>
+</td></tr>
+  <tr>
+  <td colspan=2><textarea rows=<?php print $rows; ?> name="sql" cols="80"><?php print htmlspecialchars($sql) ?></textarea>
+  </td>
+  </tr>
+ </table>
+</form>
+
+<?php
+               if (!isset($_REQUEST['sql'])) return;
+               
+               $sql = $this->undomq(trim($sql));
+               if (substr($sql,strlen($sql)-1) === ';') {
+                       $print = true;
+                       $sqla = $this->SplitSQL($sql);
+               } else  {
+                       $print = false;
+                       $sqla = array($sql);
+               }
+               foreach($sqla as $sqls) {
+
+                       if (!$sqls) continue;
+                       
+                       if ($print) {
+                               print "<p>".htmlspecialchars($sqls)."</p>";
+                               flush();
+                       }
+                       $savelog = $this->conn->LogSQL(false);
+                       $rs = $this->conn->Execute($sqls);
+                       $this->conn->LogSQL($savelog);
+                       if ($rs && is_object($rs) && !$rs->EOF) {
+                               rs2html($rs);
+                               while ($rs->NextRecordSet()) {
+                                       print "<table width=98% bgcolor=#C0C0FF><tr><td>&nbsp;</td></tr></table>";
+                                       rs2html($rs);
+                               }
+                       } else {
+                               $e1 = (integer) $this->conn->ErrorNo();
+                               $e2 = $this->conn->ErrorMsg();
+                               if (($e1) || ($e2)) {
+                                       if (empty($e1)) $e1 = '-1'; // postgresql fix
+                                       print ' &nbsp; '.$e1.': '.$e2;
+                               } else {
+                                       print "<p>No Recordset returned<br></p>";
+                               }
+                       }
+               } // foreach
+       }
+       
+       function SplitSQL($sql)
+       {
+               $arr = explode(';',$sql);
+               return $arr;
+       }
+       
+       function undomq(&$m) 
+       {
+       if (get_magic_quotes_gpc()) {
+               // undo the damage
+               $m = str_replace('\\\\','\\',$m);
+               $m = str_replace('\"','"',$m);
+               $m = str_replace('\\\'','\'',$m);
+       }
+       return $m;
+}
+
+    
+   /************************************************************************/
+   
+    /** 
+     * Reorganise multiple table-indices/statistics/..
+     * OptimizeMode could be given by last Parameter
+     * 
+     * @example
+     *      <pre>
+     *          optimizeTables( 'tableA');
+     *      </pre>
+     *      <pre>
+     *          optimizeTables( 'tableA', 'tableB', 'tableC');
+     *      </pre>
+     *      <pre>
+     *          optimizeTables( 'tableA', 'tableB', ADODB_OPT_LOW);
+     *      </pre>
+     * 
+     * @param string table name of the table to optimize
+     * @param int mode optimization-mode
+     *      <code>ADODB_OPT_HIGH</code> for full optimization 
+     *      <code>ADODB_OPT_LOW</code> for CPU-less optimization
+     *      Default is LOW <code>ADODB_OPT_LOW</code> 
+     * @author Markus Staab
+     * @return Returns <code>true</code> on success and <code>false</code> on error
+     */
+    function OptimizeTables()
+    {
+        $args = func_get_args();
+        $numArgs = func_num_args();
+        
+        if ( $numArgs == 0) return false;
+        
+        $mode = ADODB_OPT_LOW; 
+        $lastArg = $args[ $numArgs - 1];
+        if ( !is_string($lastArg)) {
+            $mode = $lastArg;
+            unset( $args[ $numArgs - 1]);
+        }
+        
+        foreach( $args as $table) {
+            $this->optimizeTable( $table, $mode);
+        }
+       }
+
+    /** 
+     * Reorganise the table-indices/statistics/.. depending on the given mode.
+     * Default Implementation throws an error.
+     * 
+     * @param string table name of the table to optimize
+     * @param int mode optimization-mode
+     *      <code>ADODB_OPT_HIGH</code> for full optimization 
+     *      <code>ADODB_OPT_LOW</code> for CPU-less optimization
+     *      Default is LOW <code>ADODB_OPT_LOW</code> 
+     * @author Markus Staab
+     * @return Returns <code>true</code> on success and <code>false</code> on error
+     */
+    function OptimizeTable( $table, $mode = ADODB_OPT_LOW) 
+    {
+        ADOConnection::outp( sprintf( "<p>%s: '%s' not implemented for driver '%s'</p>", __CLASS__, __FUNCTION__, $this->conn->databaseType));
+        return false;
+    }
+    
+    /** 
+     * Reorganise current database.
+     * Default implementation loops over all <code>MetaTables()</code> and 
+     * optimize each using <code>optmizeTable()</code>
+     * 
+     * @author Markus Staab
+     * @return Returns <code>true</code> on success and <code>false</code> on error
+     */
+    function optimizeDatabase() 
+    {
+        $conn = $this->conn;
+        if ( !$conn) return false;
+        
+        $tables = $conn->MetaTables( 'TABLES');
+        if ( !$tables ) return false;
+
+        foreach( $tables as $table) {
+            if ( !$this->optimizeTable( $table)) {
+                return false;
+            }
+        }
+      
+        return true;
+    }
+    // end hack 
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/adodb/adodb/adodb-php4.inc.php b/typo3/sysext/adodb/adodb/adodb-php4.inc.php
new file mode 100644 (file)
index 0000000..e449445
--- /dev/null
@@ -0,0 +1,16 @@
+<?php
+
+/*
+  V4.68 25 Nov 2005  (c) 2000-2005 John Lim (jlim@natsoft.com.my). All rights reserved.
+  Released under both BSD license and Lesser GPL library license. 
+  Whenever there is any discrepancy between the two licenses, 
+  the BSD license will take precedence.
+  
+  Set tabs to 4.
+*/
+
+
+class ADODB_BASE_RS {
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/adodb/adodb/adodb-time.inc.php b/typo3/sysext/adodb/adodb/adodb-time.inc.php
new file mode 100644 (file)
index 0000000..79e0dbc
--- /dev/null
@@ -0,0 +1,1312 @@
+<?php
+/**
+ADOdb Date Library, part of the ADOdb abstraction library
+Download: http://phplens.com/phpeverywhere/
+
+PHP native date functions use integer timestamps for computations.
+Because of this, dates are restricted to the years 1901-2038 on Unix 
+and 1970-2038 on Windows due to integer overflow for dates beyond 
+those years. This library overcomes these limitations by replacing the 
+native function's signed integers (normally 32-bits) with PHP floating 
+point numbers (normally 64-bits).
+
+Dates from 100 A.D. to 3000 A.D. and later
+have been tested. The minimum is 100 A.D. as <100 will invoke the
+2 => 4 digit year conversion. The maximum is billions of years in the 
+future, but this is a theoretical limit as the computation of that year 
+would take too long with the current implementation of adodb_mktime().
+
+This library replaces native functions as follows:
+
+<pre>  
+       getdate()  with  adodb_getdate()
+       date()     with  adodb_date() 
+       gmdate()   with  adodb_gmdate()
+       mktime()   with  adodb_mktime()
+       gmmktime() with  adodb_gmmktime()
+       strftime() with  adodb_strftime()
+       strftime() with  adodb_gmstrftime()
+</pre>
+       
+The parameters are identical, except that adodb_date() accepts a subset
+of date()'s field formats. Mktime() will convert from local time to GMT, 
+and date() will convert from GMT to local time, but daylight savings is 
+not handled currently.
+
+This library is independant of the rest of ADOdb, and can be used
+as standalone code.
+
+PERFORMANCE
+
+For high speed, this library uses the native date functions where
+possible, and only switches to PHP code when the dates fall outside 
+the 32-bit signed integer range.
+
+GREGORIAN CORRECTION
+
+Pope Gregory shortened October of A.D. 1582 by ten days. Thursday, 
+October 4, 1582 (Julian) was followed immediately by Friday, October 15, 
+1582 (Gregorian). 
+
+Since 0.06, we handle this correctly, so:
+
+adodb_mktime(0,0,0,10,15,1582) - adodb_mktime(0,0,0,10,4,1582) 
+       == 24 * 3600 (1 day)
+
+=============================================================================
+
+COPYRIGHT
+
+(c) 2003-2005 John Lim and released under BSD-style license except for code by 
+jackbbs, which includes adodb_mktime, adodb_get_gmt_diff, adodb_is_leap_year
+and originally found at http://www.php.net/manual/en/function.mktime.php
+
+=============================================================================
+
+BUG REPORTS
+
+These should be posted to the ADOdb forums at
+
+       http://phplens.com/lens/lensforum/topics.php?id=4
+
+=============================================================================
+
+FUNCTION DESCRIPTIONS
+
+
+** FUNCTION adodb_getdate($date=false)
+
+Returns an array containing date information, as getdate(), but supports
+dates greater than 1901 to 2038. The local date/time format is derived from a 
+heuristic the first time adodb_getdate is called. 
+        
+        
+** FUNCTION adodb_date($fmt, $timestamp = false)
+
+Convert a timestamp to a formatted local date. If $timestamp is not defined, the
+current timestamp is used. Unlike the function date(), it supports dates
+outside the 1901 to 2038 range.
+
+The format fields that adodb_date supports:
+
+<pre>
+       a - "am" or "pm" 
+       A - "AM" or "PM" 
+       d - day of the month, 2 digits with leading zeros; i.e. "01" to "31" 
+       D - day of the week, textual, 3 letters; e.g. "Fri" 
+       F - month, textual, long; e.g. "January" 
+       g - hour, 12-hour format without leading zeros; i.e. "1" to "12" 
+       G - hour, 24-hour format without leading zeros; i.e. "0" to "23" 
+       h - hour, 12-hour format; i.e. "01" to "12" 
+       H - hour, 24-hour format; i.e. "00" to "23" 
+       i - minutes; i.e. "00" to "59" 
+       j - day of the month without leading zeros; i.e. "1" to "31" 
+       l (lowercase 'L') - day of the week, textual, long; e.g. "Friday"  
+       L - boolean for whether it is a leap year; i.e. "0" or "1" 
+       m - month; i.e. "01" to "12" 
+       M - month, textual, 3 letters; e.g. "Jan" 
+       n - month without leading zeros; i.e. "1" to "12" 
+       O - Difference to Greenwich time in hours; e.g. "+0200" 
+       Q - Quarter, as in 1, 2, 3, 4 
+       r - RFC 822 formatted date; e.g. "Thu, 21 Dec 2000 16:01:07 +0200" 
+       s - seconds; i.e. "00" to "59" 
+       S - English ordinal suffix for the day of the month, 2 characters; 
+                               i.e. "st", "nd", "rd" or "th" 
+       t - number of days in the given month; i.e. "28" to "31"
+       T - Timezone setting of this machine; e.g. "EST" or "MDT" 
+       U - seconds since the Unix Epoch (January 1 1970 00:00:00 GMT)  
+       w - day of the week, numeric, i.e. "0" (Sunday) to "6" (Saturday) 
+       Y - year, 4 digits; e.g. "1999" 
+       y - year, 2 digits; e.g. "99" 
+       z - day of the year; i.e. "0" to "365" 
+       Z - timezone offset in seconds (i.e. "-43200" to "43200"). 
+                               The offset for timezones west of UTC is always negative, 
+                               and for those east of UTC is always positive. 
+</pre>
+
+Unsupported:
+<pre>
+       B - Swatch Internet time 
+       I (capital i) - "1" if Daylight Savings Time, "0" otherwise.
+       W - ISO-8601 week number of year, weeks starting on Monday 
+
+</pre>
+
+
+** FUNCTION adodb_date2($fmt, $isoDateString = false)
+Same as adodb_date, but 2nd parameter accepts iso date, eg.
+
+  adodb_date2('d-M-Y H:i','2003-12-25 13:01:34');
+
+  
+** FUNCTION adodb_gmdate($fmt, $timestamp = false)
+
+Convert a timestamp to a formatted GMT date. If $timestamp is not defined, the
+current timestamp is used. Unlike the function date(), it supports dates
+outside the 1901 to 2038 range.
+
+
+** FUNCTION adodb_mktime($hr, $min, $sec[, $month, $day, $year])
+
+Converts a local date to a unix timestamp.  Unlike the function mktime(), it supports
+dates outside the 1901 to 2038 range. All parameters are optional.
+
+
+** FUNCTION adodb_gmmktime($hr, $min, $sec [, $month, $day, $year])
+
+Converts a gmt date to a unix timestamp.  Unlike the function gmmktime(), it supports
+dates outside the 1901 to 2038 range. Differs from gmmktime() in that all parameters
+are currently compulsory.
+
+** FUNCTION adodb_gmstrftime($fmt, $timestamp = false)
+Convert a timestamp to a formatted GMT date.
+
+** FUNCTION adodb_strftime($fmt, $timestamp = false)
+
+Convert a timestamp to a formatted local date. Internally converts $fmt into 
+adodb_date format, then echo result.
+
+For best results, you can define the local date format yourself. Define a global
+variable $ADODB_DATE_LOCALE which is an array, 1st element is date format using
+adodb_date syntax, and 2nd element is the time format, also in adodb_date syntax.
+
+    eg. $ADODB_DATE_LOCALE = array('d/m/Y','H:i:s');
+       
+       Supported format codes:
+
+<pre>
+       %a - abbreviated weekday name according to the current locale 
+       %A - full weekday name according to the current locale 
+       %b - abbreviated month name according to the current locale 
+       %B - full month name according to the current locale 
+       %c - preferred date and time representation for the current locale 
+       %d - day of the month as a decimal number (range 01 to 31) 
+       %D - same as %m/%d/%y 
+       %e - day of the month as a decimal number, a single digit is preceded by a space (range ' 1' to '31') 
+       %h - same as %b
+       %H - hour as a decimal number using a 24-hour clock (range 00 to 23) 
+       %I - hour as a decimal number using a 12-hour clock (range 01 to 12) 
+       %m - month as a decimal number (range 01 to 12) 
+       %M - minute as a decimal number 
+       %n - newline character 
+       %p - either `am' or `pm' according to the given time value, or the corresponding strings for the current locale 
+       %r - time in a.m. and p.m. notation 
+       %R - time in 24 hour notation 
+       %S - second as a decimal number 
+       %t - tab character 
+       %T - current time, equal to %H:%M:%S 
+       %x - preferred date representation for the current locale without the time 
+       %X - preferred time representation for the current locale without the date 
+       %y - year as a decimal number without a century (range 00 to 99) 
+       %Y - year as a decimal number including the century 
+       %Z - time zone or name or abbreviation 
+       %% - a literal `%' character 
+</pre> 
+
+       Unsupported codes:
+<pre>
+       %C - century number (the year divided by 100 and truncated to an integer, range 00 to 99) 
+       %g - like %G, but without the century. 
+       %G - The 4-digit year corresponding to the ISO week number (see %V). 
+            This has the same format and value as %Y, except that if the ISO week number belongs 
+                to the previous or next year, that year is used instead. 
+       %j - day of the year as a decimal number (range 001 to 366) 
+       %u - weekday as a decimal number [1,7], with 1 representing Monday 
+       %U - week number of the current year as a decimal number, starting 
+           with the first Sunday as the first day of the first week 
+       %V - The ISO 8601:1988 week number of the current year as a decimal number, 
+            range 01 to 53, where week 1 is the first week that has at least 4 days in the 
+                current year, and with Monday as the first day of the week. (Use %G or %g for 
+                the year component that corresponds to the week number for the specified timestamp.) 
+       %w - day of the week as a decimal, Sunday being 0 
+       %W - week number of the current year as a decimal number, starting with the 
+            first Monday as the first day of the first week 
+</pre>
+
+=============================================================================
+
+NOTES
+
+Useful url for generating test timestamps:
+       http://www.4webhelp.net/us/timestamp.php
+
+Possible future optimizations include 
+
+a. Using an algorithm similar to Plauger's in "The Standard C Library" 
+(page 428, xttotm.c _Ttotm() function). Plauger's algorithm will not 
+work outside 32-bit signed range, so i decided not to implement it.
+
+b. Implement daylight savings, which looks awfully complicated, see
+       http://webexhibits.org/daylightsaving/
+
+
+CHANGELOG
+- 08 Sept 2005 0.22
+In adodb_date2(), $is_gmt not supported properly. Fixed.
+
+- 18 July  2005 0.21
+In PHP 4.3.11, the 'r' format has changed. Leading 0 in day is added. Changed for compat.
+Added support for negative months in adodb_mktime().
+
+- 24 Feb 2005 0.20
+Added limited strftime/gmstrftime support. x10 improvement in performance of adodb_date().
+
+- 21 Dec 2004 0.17
+In adodb_getdate(), the timestamp was accidentally converted to gmt when $is_gmt is false. 
+Also adodb_mktime(0,0,0) did not work properly. Both fixed thx Mauro.
+
+- 17 Nov 2004 0.16
+Removed intval typecast in adodb_mktime() for secs, allowing:
+        adodb_mktime(0,0,0 + 2236672153,1,1,1934);
+Suggested by Ryan.
+
+- 18 July 2004 0.15
+All params in adodb_mktime were formerly compulsory. Now only the hour, min, secs is compulsory. 
+This brings it more in line with mktime (still not identical).
+
+- 23 June 2004 0.14
+
+Allow you to define your own daylights savings function, adodb_daylight_sv.
+If the function is defined (somewhere in an include), then you can correct for daylights savings.
+
+In this example, we apply daylights savings in June or July, adding one hour. This is extremely
+unrealistic as it does not take into account time-zone, geographic location, current year.
+
+function adodb_daylight_sv(&$arr, $is_gmt)
+{
+       if ($is_gmt) return;
+       $m = $arr['mon'];
+       if ($m == 6 || $m == 7) $arr['hours'] += 1;
+}
+
+This is only called by adodb_date() and not by adodb_mktime(). 
+
+The format of $arr is
+Array ( 
+   [seconds] => 0 
+   [minutes] => 0 
+   [hours] => 0 
+   [mday] => 1      # day of month, eg 1st day of the month
+   [mon] => 2       # month (eg. Feb)
+   [year] => 2102 
+   [yday] => 31     # days in current year
+   [leap] =>        # true if leap year
+   [ndays] => 28    # no of days in current month
+   ) 
+   
+
+- 28 Apr 2004 0.13
+Fixed adodb_date to properly support $is_gmt. Thx to Dimitar Angelov.
+
+- 20 Mar 2004 0.12
+Fixed month calculation error in adodb_date. 2102-June-01 appeared as 2102-May-32.
+
+- 26 Oct 2003 0.11
+Because of daylight savings problems (some systems apply daylight savings to 
+January!!!), changed adodb_get_gmt_diff() to ignore daylight savings.
+
+- 9 Aug 2003 0.10
+Fixed bug with dates after 2038. 
+See http://phplens.com/lens/lensforum/msgs.php?id=6980
+
+- 1 July 2003 0.09
+Added support for Q (Quarter).
+Added adodb_date2(), which accepts ISO date in 2nd param
+
+- 3 March 2003 0.08
+Added support for 'S' adodb_date() format char. Added constant ADODB_ALLOW_NEGATIVE_TS
+if you want PHP to handle negative timestamps between 1901 to 1969.
+
+- 27 Feb 2003 0.07
+All negative numbers handled by adodb now because of RH 7.3+ problems.
+See http://bugs.php.net/bug.php?id=20048&edit=2
+
+- 4 Feb 2003 0.06
+Fixed a typo, 1852 changed to 1582! This means that pre-1852 dates
+are now correctly handled.
+
+- 29 Jan 2003 0.05
+
+Leap year checking differs under Julian calendar (pre 1582). Also
+leap year code optimized by checking for most common case first.
+
+We also handle month overflow correctly in mktime (eg month set to 13).
+
+Day overflow for less than one month's days is supported.
+
+- 28 Jan 2003 0.04
+
+Gregorian correction handled. In PHP5, we might throw an error if 
+mktime uses invalid dates around 5-14 Oct 1582. Released with ADOdb 3.10.
+Added limbo 5-14 Oct 1582 check, when we set to 15 Oct 1582.
+
+- 27 Jan 2003 0.03
+
+Fixed some more month problems due to gmt issues. Added constant ADODB_DATE_VERSION.
+Fixed calculation of days since start of year for <1970. 
+
+- 27 Jan 2003 0.02
+
+Changed _adodb_getdate() to inline leap year checking for better performance.
+Fixed problem with time-zones west of GMT +0000.
+
+- 24 Jan 2003 0.01
+
+First implementation.
+*/
+
+
+/* Initialization */
+
+/*
+       Version Number
+*/
+define('ADODB_DATE_VERSION',0.22);
+
+/*
+       This code was originally for windows. But apparently this problem happens 
+       also with Linux, RH 7.3 and later!
+       
+       glibc-2.2.5-34 and greater has been changed to return -1 for dates <
+       1970.  This used to work.  The problem exists with RedHat 7.3 and 8.0
+       echo (mktime(0, 0, 0, 1, 1, 1960));  // prints -1
+       
+       References:
+        http://bugs.php.net/bug.php?id=20048&edit=2
+        http://lists.debian.org/debian-glibc/2002/debian-glibc-200205/msg00010.html
+*/
+
+if (!defined('ADODB_ALLOW_NEGATIVE_TS')) define('ADODB_NO_NEGATIVE_TS',1);
+
+function adodb_date_test_date($y1,$m,$d=13)
+{
+       $t = adodb_mktime(0,0,0,$m,$d,$y1);
+       $rez = adodb_date('Y-n-j H:i:s',$t);
+       if ("$y1-$m-$d 00:00:00" != $rez) {
+               print "<b>$y1 error, expected=$y1-$m-$d 00:00:00, adodb=$rez</b><br>";
+               return false;
+       }
+       return true;
+}
+
+function adodb_date_test_strftime($fmt)
+{
+       $s1 = strftime($fmt);
+       $s2 = adodb_strftime($fmt);
+       
+       if ($s1 == $s2) return true;
+       
+       echo "error for $fmt,  strftime=$s1, $adodb=$s2<br>";
+       return false;
+}
+
+/**
+        Test Suite
+*/
+function adodb_date_test()
+{
+       
+       error_reporting(E_ALL);
+       print "<h4>Testing adodb_date and adodb_mktime. version=".ADODB_DATE_VERSION.' PHP='.PHP_VERSION."</h4>";
+       @set_time_limit(0);
+       $fail = false;
+       
+       // This flag disables calling of PHP native functions, so we can properly test the code
+       if (!defined('ADODB_TEST_DATES')) define('ADODB_TEST_DATES',1);
+       
+       adodb_date_test_strftime('%Y %m %x %X');
+       adodb_date_test_strftime("%A %d %B %Y");
+       adodb_date_test_strftime("%H %M S");
+       
+       $t = adodb_mktime(0,0,0);
+       if (!(adodb_date('Y-m-d') == date('Y-m-d'))) print 'Error in '.adodb_mktime(0,0,0).'<br>';
+       
+       $t = adodb_mktime(0,0,0,6,1,2102);
+       if (!(adodb_date('Y-m-d',$t) == '2102-06-01')) print 'Error in '.adodb_date('Y-m-d',$t).'<br>';
+       
+       $t = adodb_mktime(0,0,0,2,1,2102);
+       if (!(adodb_date('Y-m-d',$t) == '2102-02-01')) print 'Error in '.adodb_date('Y-m-d',$t).'<br>';
+       
+       
+       print "<p>Testing gregorian <=> julian conversion<p>";
+       $t = adodb_mktime(0,0,0,10,11,1492);
+       //http://www.holidayorigins.com/html/columbus_day.html - Friday check
+       if (!(adodb_date('D Y-m-d',$t) == 'Fri 1492-10-11')) print 'Error in Columbus landing<br>';
+       
+       $t = adodb_mktime(0,0,0,2,29,1500);
+       if (!(adodb_date('Y-m-d',$t) == '1500-02-29')) print 'Error in julian leap years<br>';
+       
+       $t = adodb_mktime(0,0,0,2,29,1700);
+       if (!(adodb_date('Y-m-d',$t) == '1700-03-01')) print 'Error in gregorian leap years<br>';
+       
+       print  adodb_mktime(0,0,0,10,4,1582).' ';
+       print adodb_mktime(0,0,0,10,15,1582);
+       $diff = (adodb_mktime(0,0,0,10,15,1582) - adodb_mktime(0,0,0,10,4,1582));
+       if ($diff != 3600*24) print " <b>Error in gregorian correction = ".($diff/3600/24)." days </b><br>";
+               
+       print " 15 Oct 1582, Fri=".(adodb_dow(1582,10,15) == 5 ? 'Fri' : '<b>Error</b>')."<br>";
+       print " 4 Oct 1582, Thu=".(adodb_dow(1582,10,4) == 4 ? 'Thu' : '<b>Error</b>')."<br>";
+       
+       print "<p>Testing overflow<p>";
+       
+       $t = adodb_mktime(0,0,0,3,33,1965);
+       if (!(adodb_date('Y-m-d',$t) == '1965-04-02')) print 'Error in day overflow 1 <br>';
+       $t = adodb_mktime(0,0,0,4,33,1971);
+       if (!(adodb_date('Y-m-d',$t) == '1971-05-03')) print 'Error in day overflow 2 <br>';
+       $t = adodb_mktime(0,0,0,1,60,1965);
+       if (!(adodb_date('Y-m-d',$t) == '1965-03-01')) print 'Error in day overflow 3 '.adodb_date('Y-m-d',$t).' <br>';
+       $t = adodb_mktime(0,0,0,12,32,1965);
+       if (!(adodb_date('Y-m-d',$t) == '1966-01-01')) print 'Error in day overflow 4 '.adodb_date('Y-m-d',$t).' <br>';
+       $t = adodb_mktime(0,0,0,12,63,1965);
+       if (!(adodb_date('Y-m-d',$t) == '1966-02-01')) print 'Error in day overflow 5 '.adodb_date('Y-m-d',$t).' <br>';
+       $t = adodb_mktime(0,0,0,13,3,1965);
+       if (!(adodb_date('Y-m-d',$t) == '1966-01-03')) print 'Error in mth overflow 1 <br>';
+       
+       print "Testing 2-digit => 4-digit year conversion<p>";
+       if (adodb_year_digit_check(00) != 2000) print "Err 2-digit 2000<br>";
+       if (adodb_year_digit_check(10) != 2010) print "Err 2-digit 2010<br>";
+       if (adodb_year_digit_check(20) != 2020) print "Err 2-digit 2020<br>";
+       if (adodb_year_digit_check(30) != 2030) print "Err 2-digit 2030<br>";
+       if (adodb_year_digit_check(40) != 1940) print "Err 2-digit 1940<br>";
+       if (adodb_year_digit_check(50) != 1950) print "Err 2-digit 1950<br>";
+       if (adodb_year_digit_check(90) != 1990) print "Err 2-digit 1990<br>";
+       
+       // Test string formating
+       print "<p>Testing date formating</p>";
+       $fmt = '\d\a\t\e T Y-m-d H:i:s a A d D F g G h H i j l L m M n O \R\F\C822 r s t U w y Y z Z 2003';
+       $s1 = date($fmt,0);
+       $s2 = adodb_date($fmt,0);
+       if ($s1 != $s2) {
+               print " date() 0 failed<br>$s1<br>$s2<br>";
+       }
+       flush();
+       for ($i=100; --$i > 0; ) {
+
+               $ts = 3600.0*((rand()%60000)+(rand()%60000))+(rand()%60000);
+               $s1 = date($fmt,$ts);
+               $s2 = adodb_date($fmt,$ts);
+               //print "$s1 <br>$s2 <p>";
+               $pos = strcmp($s1,$s2);
+
+               if (($s1) != ($s2)) {
+                       for ($j=0,$k=strlen($s1); $j < $k; $j++) {
+                               if ($s1[$j] != $s2[$j]) {
+                                       print substr($s1,$j).' ';
+                                       break;
+                               }
+                       }
+                       print "<b>Error date(): $ts<br><pre> 
+&nbsp; \"$s1\" (date len=".strlen($s1).")
+&nbsp; \"$s2\" (adodb_date len=".strlen($s2).")</b></pre><br>";
+                       $fail = true;
+               }
+               
+               $a1 = getdate($ts);
+               $a2 = adodb_getdate($ts);
+               $rez = array_diff($a1,$a2);
+               if (sizeof($rez)>0) {
+                       print "<b>Error getdate() $ts</b><br>";
+                               print_r($a1);
+                       print "<br>";
+                               print_r($a2);
+                       print "<p>";
+                       $fail = true;
+               }
+       }
+       
+       // Test generation of dates outside 1901-2038
+       print "<p>Testing random dates between 100 and 4000</p>";
+       adodb_date_test_date(100,1);
+       for ($i=100; --$i >= 0;) {
+               $y1 = 100+rand(0,1970-100);
+               $m = rand(1,12);
+               adodb_date_test_date($y1,$m);
+               
+               $y1 = 3000-rand(0,3000-1970);
+               adodb_date_test_date($y1,$m);
+       }
+       print '<p>';
+       $start = 1960+rand(0,10);
+       $yrs = 12;
+       $i = 365.25*86400*($start-1970);
+       $offset = 36000+rand(10000,60000);
+       $max = 365*$yrs*86400;
+       $lastyear = 0;
+       
+       // we generate a timestamp, convert it to a date, and convert it back to a timestamp
+       // and check if the roundtrip broke the original timestamp value.
+       print "Testing $start to ".($start+$yrs).", or $max seconds, offset=$offset: ";
+       $cnt = 0;
+       for ($max += $i; $i < $max; $i += $offset) {
+               $ret = adodb_date('m,d,Y,H,i,s',$i);
+               $arr = explode(',',$ret);
+               if ($lastyear != $arr[2]) {
+                       $lastyear = $arr[2];
+                       print " $lastyear ";
+                       flush();
+               }
+               $newi = adodb_mktime($arr[3],$arr[4],$arr[5],$arr[0],$arr[1],$arr[2]);
+               if ($i != $newi) {
+                       print "Error at $i, adodb_mktime returned $newi ($ret)";
+                       $fail = true;
+                       break;
+               }
+               $cnt += 1;
+       }
+       echo "Tested $cnt dates<br>";
+       if (!$fail) print "<p>Passed !</p>";
+       else print "<p><b>Failed</b> :-(</p>";
+}
+
+/**
+       Returns day of week, 0 = Sunday,... 6=Saturday. 
+       Algorithm from PEAR::Date_Calc
+*/
+function adodb_dow($year, $month, $day)
+{
+/*
+Pope Gregory removed 10 days - October 5 to October 14 - from the year 1582 and 
+proclaimed that from that time onwards 3 days would be dropped from the calendar 
+every 400 years.
+
+Thursday, October 4, 1582 (Julian) was followed immediately by Friday, October 15, 1582 (Gregorian). 
+*/
+       if ($year <= 1582) {
+               if ($year < 1582 || 
+                       ($year == 1582 && ($month < 10 || ($month == 10 && $day < 15)))) $greg_correction = 3;
+                else
+                       $greg_correction = 0;
+       } else
+               $greg_correction = 0;
+       
+       if($month > 2)
+           $month -= 2;
+       else {
+           $month += 10;
+           $year--;
+       }
+       
+       $day =  floor((13 * $month - 1) / 5) +
+               $day + ($year % 100) +
+               floor(($year % 100) / 4) +
+               floor(($year / 100) / 4) - 2 *
+               floor($year / 100) + 77 + $greg_correction;
+       
+       return $day - 7 * floor($day / 7);
+}
+
+
+/**
+ Checks for leap year, returns true if it is. No 2-digit year check. Also 
+ handles julian calendar correctly.
+*/
+function _adodb_is_leap_year($year) 
+{
+       if ($year % 4 != 0) return false;
+       
+       if ($year % 400 == 0) {
+               return true;
+       // if gregorian calendar (>1582), century not-divisible by 400 is not leap
+       } else if ($year > 1582 && $year % 100 == 0 ) {
+               return false;
+       } 
+       
+       return true;
+}
+
+
+/**
+ checks for leap year, returns true if it is. Has 2-digit year check
+*/
+function adodb_is_leap_year($year) 
+{
+       return  _adodb_is_leap_year(adodb_year_digit_check($year));
+}
+
+/**
+       Fix 2-digit years. Works for any century.
+       Assumes that if 2-digit is more than 30 years in future, then previous century.
+*/
+function adodb_year_digit_check($y) 
+{
+       if ($y < 100) {
+       
+               $yr = (integer) date("Y");
+               $century = (integer) ($yr /100);
+               
+               if ($yr%100 > 50) {
+                       $c1 = $century + 1;
+                       $c0 = $century;
+               } else {
+                       $c1 = $century;
+                       $c0 = $century - 1;
+               }
+               $c1 *= 100;
+               // if 2-digit year is less than 30 years in future, set it to this century
+               // otherwise if more than 30 years in future, then we set 2-digit year to the prev century.
+               if (($y + $c1) < $yr+30) $y = $y + $c1;
+               else $y = $y + $c0*100;
+       }
+       return $y;
+}
+
+/**
+ get local time zone offset from GMT
+*/
+function adodb_get_gmt_diff() 
+{
+static $TZ;
+       if (isset($TZ)) return $TZ;
+       
+       $TZ = mktime(0,0,0,1,2,1970,0) - gmmktime(0,0,0,1,2,1970,0);
+       return $TZ;
+}
+
+/**
+       Returns an array with date info.
+*/
+function adodb_getdate($d=false,$fast=false)
+{
+       if ($d === false) return getdate();
+       if (!defined('ADODB_TEST_DATES')) {
+               if ((abs($d) <= 0x7FFFFFFF)) { // check if number in 32-bit signed range
+                       if (!defined('ADODB_NO_NEGATIVE_TS') || $d >= 0) // if windows, must be +ve integer
+                               return @getdate($d);
+               }
+       }
+       return _adodb_getdate($d);
+}
+
+/*
+// generate $YRS table for _adodb_getdate()
+function adodb_date_gentable($out=true)
+{
+
+       for ($i=1970; $i >= 1600; $i-=10) {
+               $s = adodb_gmmktime(0,0,0,1,1,$i);
+               echo "$i => $s,<br>";   
+       }
+}
+adodb_date_gentable();
+
+for ($i=1970; $i > 1500; $i--) {
+
+echo "<hr />$i ";
+       adodb_date_test_date($i,1,1);
+}
+
+*/
+
+
+$_month_table_normal = array("",31,28,31,30,31,30,31,31,30,31,30,31);
+$_month_table_leaf = array("",31,29,31,30,31,30,31,31,30,31,30,31);
+       
+function adodb_validdate($y,$m,$d)
+{
+global $_month_table_normal,$_month_table_leaf;
+
+       if (_adodb_is_leap_year($y)) $marr =& $_month_table_leaf;
+       else $marr =& $_month_table_normal;
+       
+       if ($m > 12 || $m < 1) return false;
+       
+       if ($d > 31 || $d < 1) return false;
+       
+       if ($marr[$m] < $d) return false;
+       
+       if ($y < 1000 && $y > 3000) return false;
+       
+       return true;
+}
+
+/**
+       Low-level function that returns the getdate() array. We have a special
+       $fast flag, which if set to true, will return fewer array values,
+       and is much faster as it does not calculate dow, etc.
+*/
+function _adodb_getdate($origd=false,$fast=false,$is_gmt=false)
+{
+static $YRS;
+global $_month_table_normal,$_month_table_leaf;
+
+       $d =  $origd - ($is_gmt ? 0 : adodb_get_gmt_diff());
+       
+       $_day_power = 86400;
+       $_hour_power = 3600;
+       $_min_power = 60;
+       
+       if ($d < -12219321600) $d -= 86400*10; // if 15 Oct 1582 or earlier, gregorian correction 
+       
+       $_month_table_normal = array("",31,28,31,30,31,30,31,31,30,31,30,31);
+       $_month_table_leaf = array("",31,29,31,30,31,30,31,31,30,31,30,31);
+       
+       $d366 = $_day_power * 366;
+       $d365 = $_day_power * 365;
+       
+       if ($d < 0) {
+               
+               if (empty($YRS)) $YRS = array(
+                       1970 => 0,
+                       1960 => -315619200,
+                       1950 => -631152000,
+                       1940 => -946771200,
+                       1930 => -1262304000,
+                       1920 => -1577923200,
+                       1910 => -1893456000,
+                       1900 => -2208988800,
+                       1890 => -2524521600,
+                       1880 => -2840140800,
+                       1870 => -3155673600,
+                       1860 => -3471292800,
+                       1850 => -3786825600,
+                       1840 => -4102444800,
+                       1830 => -4417977600,
+                       1820 => -4733596800,
+                       1810 => -5049129600,
+                       1800 => -5364662400,
+                       1790 => -5680195200,
+                       1780 => -5995814400,
+                       1770 => -6311347200,
+                       1760 => -6626966400,
+                       1750 => -6942499200,
+                       1740 => -7258118400,
+                       1730 => -7573651200,
+                       1720 => -7889270400,
+                       1710 => -8204803200,
+                       1700 => -8520336000,
+                       1690 => -8835868800,
+                       1680 => -9151488000,
+                       1670 => -9467020800,
+                       1660 => -9782640000,
+                       1650 => -10098172800,
+                       1640 => -10413792000,
+                       1630 => -10729324800,
+                       1620 => -11044944000,
+                       1610 => -11360476800,
+                       1600 => -11676096000);
+
+               if ($is_gmt) $origd = $d;
+               // The valid range of a 32bit signed timestamp is typically from 
+               // Fri, 13 Dec 1901 20:45:54 GMT to Tue, 19 Jan 2038 03:14:07 GMT
+               //
+               
+               # old algorithm iterates through all years. new algorithm does it in
+               # 10 year blocks
+               
+               /*
+               # old algo
+               for ($a = 1970 ; --$a >= 0;) {
+                       $lastd = $d;
+                       
+                       if ($leaf = _adodb_is_leap_year($a)) $d += $d366;
+                       else $d += $d365;
+                       
+                       if ($d >= 0) {
+                               $year = $a;
+                               break;
+                       }
+               }
+               */
+               
+               $lastsecs = 0;
+               $lastyear = 1970;
+               foreach($YRS as $year => $secs) {
+                       if ($d >= $secs) {
+                               $a = $lastyear;
+                               break;
+                       }
+                       $lastsecs = $secs;
+                       $lastyear = $year;
+               }
+               
+               $d -= $lastsecs;
+               if (!isset($a)) $a = $lastyear;
+               
+               //echo ' yr=',$a,' ', $d,'.';
+               
+               for (; --$a >= 0;) {
+                       $lastd = $d;
+                       
+                       if ($leaf = _adodb_is_leap_year($a)) $d += $d366;
+                       else $d += $d365;
+                       
+                       if ($d >= 0) {
+                               $year = $a;
+                               break;
+                       }
+               }
+               /**/
+               
+               $secsInYear = 86400 * ($leaf ? 366 : 365) + $lastd;
+               
+               $d = $lastd;
+               $mtab = ($leaf) ? $_month_table_leaf : $_month_table_normal;
+               for ($a = 13 ; --$a > 0;) {
+                       $lastd = $d;
+                       $d += $mtab[$a] * $_day_power;
+                       if ($d >= 0) {
+                               $month = $a;
+                               $ndays = $mtab[$a];
+                               break;
+                       }
+               }
+               
+               $d = $lastd;
+               $day = $ndays + ceil(($d+1) / ($_day_power));
+
+               $d += ($ndays - $day+1)* $_day_power;
+               $hour = floor($d/$_hour_power);
+       
+       } else {
+               for ($a = 1970 ;; $a++) {
+                       $lastd = $d;
+                       
+                       if ($leaf = _adodb_is_leap_year($a)) $d -= $d366;
+                       else $d -= $d365;
+                       if ($d < 0) {
+                               $year = $a;
+                               break;
+                       }
+               }
+               $secsInYear = $lastd;
+               $d = $lastd;
+               $mtab = ($leaf) ? $_month_table_leaf : $_month_table_normal;
+               for ($a = 1 ; $a <= 12; $a++) {
+                       $lastd = $d;
+                       $d -= $mtab[$a] * $_day_power;
+                       if ($d < 0) {
+                               $month = $a;
+                               $ndays = $mtab[$a];
+                               break;
+                       }
+               }
+               $d = $lastd;
+               $day = ceil(($d+1) / $_day_power);
+               $d = $d - ($day-1) * $_day_power;
+               $hour = floor($d /$_hour_power);
+       }
+       
+       $d -= $hour * $_hour_power;
+       $min = floor($d/$_min_power);
+       $secs = $d - $min * $_min_power;
+       if ($fast) {
+               return array(
+               'seconds' => $secs,
+               'minutes' => $min,
+               'hours' => $hour,
+               'mday' => $day,
+               'mon' => $month,
+               'year' => $year,
+               'yday' => floor($secsInYear/$_day_power),
+               'leap' => $leaf,
+               'ndays' => $ndays
+               );
+       }
+       
+       
+       $dow = adodb_dow($year,$month,$day);
+
+       return array(
+               'seconds' => $secs,
+               'minutes' => $min,
+               'hours' => $hour,
+               'mday' => $day,
+               'wday' => $dow,
+               'mon' => $month,
+               'year' => $year,
+               'yday' => floor($secsInYear/$_day_power),
+               'weekday' => gmdate('l',$_day_power*(3+$dow)),
+               'month' => gmdate('F',mktime(0,0,0,$month,2,1971)),
+               0 => $origd
+       );
+}
+
+function adodb_gmdate($fmt,$d=false)
+{
+       return adodb_date($fmt,$d,true);
+}
+
+// accepts unix timestamp and iso date format in $d
+function adodb_date2($fmt, $d=false, $is_gmt=false)
+{
+       if ($d !== false) {
+               if (!preg_match( 
+                       "|^([0-9]{4})[-/\.]?([0-9]{1,2})[-/\.]?([0-9]{1,2})[ -]?(([0-9]{1,2}):?([0-9]{1,2}):?([0-9\.]{1,4}))?|", 
+                       ($d), $rr)) return adodb_date($fmt,false,$is_gmt);
+
+               if ($rr[1] <= 100 && $rr[2]<= 1) return adodb_date($fmt,false,$is_gmt);
+       
+               // h-m-s-MM-DD-YY
+               if (!isset($rr[5])) $d = adodb_mktime(0,0,0,$rr[2],$rr[3],$rr[1],false,$is_gmt);
+               else $d = @adodb_mktime($rr[5],$rr[6],$rr[7],$rr[2],$rr[3],$rr[1],false,$is_gmt);
+       }
+       
+       return adodb_date($fmt,$d,$is_gmt);
+}
+
+
+/**
+       Return formatted date based on timestamp $d
+*/
+function adodb_date($fmt,$d=false,$is_gmt=false)
+{
+static $daylight;
+
+       if ($d === false) return ($is_gmt)? @gmdate($fmt): @date($fmt);
+       if (!defined('ADODB_TEST_DATES')) {
+               if ((abs($d) <= 0x7FFFFFFF)) { // check if number in 32-bit signed range
+                       if (!defined('ADODB_NO_NEGATIVE_TS') || $d >= 0) // if windows, must be +ve integer
+                               return ($is_gmt)? @gmdate($fmt,$d): @date($fmt,$d);
+
+               }
+       }
+       $_day_power = 86400;
+       
+       $arr = _adodb_getdate($d,true,$is_gmt);
+       
+       if (!isset($daylight)) $daylight = function_exists('adodb_daylight_sv');
+       if ($daylight) adodb_daylight_sv($arr, $is_gmt);
+       
+       $year = $arr['year'];
+       $month = $arr['mon'];
+       $day = $arr['mday'];
+       $hour = $arr['hours'];
+       $min = $arr['minutes'];
+       $secs = $arr['seconds'];
+       
+       $max = strlen($fmt);
+       $dates = '';
+       
+       /*
+               at this point, we have the following integer vars to manipulate:
+               $year, $month, $day, $hour, $min, $secs
+       */
+       for ($i=0; $i < $max; $i++) {
+               switch($fmt[$i]) {
+               case 'T': $dates .= date('T');break;
+               // YEAR
+               case 'L': $dates .= $arr['leap'] ? '1' : '0'; break;
+               case 'r': // Thu, 21 Dec 2000 16:01:07 +0200
+               
+                       // 4.3.11 uses '04 Jun 2004'
+                       // 4.3.8 uses  ' 4 Jun 2004'
+                       $dates .= gmdate('D',$_day_power*(3+adodb_dow($year,$month,$day))).', '         
+                               . ($day<10?'0'.$day:$day) . ' '.date('M',mktime(0,0,0,$month,2,1971)).' '.$year.' ';
+                       
+                       if ($hour < 10) $dates .= '0'.$hour; else $dates .= $hour; 
+                       
+                       if ($min < 10) $dates .= ':0'.$min; else $dates .= ':'.$min;
+                       
+                       if ($secs < 10) $dates .= ':0'.$secs; else $dates .= ':'.$secs;
+                       
+                       $gmt = adodb_get_gmt_diff();
+                       $dates .= sprintf(' %s%04d',($gmt<0)?'+':'-',abs($gmt)/36); break;
+                               
+               case 'Y': $dates .= $year; break;
+               case 'y': $dates .= substr($year,strlen($year)-2,2); break;
+               // MONTH
+               case 'm': if ($month<10) $dates .= '0'.$month; else $dates .= $month; break;
+               case 'Q': $dates .= ($month+3)>>2; break;
+               case 'n': $dates .= $month; break;
+               case 'M': $dates .= date('M',mktime(0,0,0,$month,2,1971)); break;
+               case 'F': $dates .= date('F',mktime(0,0,0,$month,2,1971)); break;
+               // DAY
+               case 't': $dates .= $arr['ndays']; break;
+               case 'z': $dates .= $arr['yday']; break;
+               case 'w': $dates .= adodb_dow($year,$month,$day); break;
+               case 'l': $dates .= gmdate('l',$_day_power*(3+adodb_dow($year,$month,$day))); break;
+               case 'D': $dates .= gmdate('D',$_day_power*(3+adodb_dow($year,$month,$day))); break;
+               case 'j': $dates .= $day; break;
+               case 'd': if ($day<10) $dates .= '0'.$day; else $dates .= $day; break;
+               case 'S': 
+                       $d10 = $day % 10;
+                       if ($d10 == 1) $dates .= 'st';
+                       else if ($d10 == 2 && $day != 12) $dates .= 'nd';
+                       else if ($d10 == 3) $dates .= 'rd';
+                       else $dates .= 'th';
+                       break;
+                       
+               // HOUR
+               case 'Z':
+                       $dates .= ($is_gmt) ? 0 : -adodb_get_gmt_diff(); break;
+               case 'O': 
+                       $gmt = ($is_gmt) ? 0 : adodb_get_gmt_diff();
+                       $dates .= sprintf('%s%04d',($gmt<0)?'+':'-',abs($gmt)/36); break;
+                       
+               case 'H': 
+                       if ($hour < 10) $dates .= '0'.$hour; 
+                       else $dates .= $hour; 
+                       break;
+               case 'h': 
+                       if ($hour > 12) $hh = $hour - 12; 
+                       else {
+                               if ($hour == 0) $hh = '12'; 
+                               else $hh = $hour;
+                       }
+                       
+                       if ($hh < 10) $dates .= '0'.$hh;
+                       else $dates .= $hh;
+                       break;
+                       
+               case 'G': 
+                       $dates .= $hour;
+                       break;
+                       
+               case 'g':
+                       if ($hour > 12) $hh = $hour - 12; 
+                       else {
+                               if ($hour == 0) $hh = '12'; 
+                               else $hh = $hour; 
+                       }
+                       $dates .= $hh;
+                       break;
+               // MINUTES
+               case 'i': if ($min < 10) $dates .= '0'.$min; else $dates .= $min; break;
+               // SECONDS
+               case 'U': $dates .= $d; break;
+               case 's': if ($secs < 10) $dates .= '0'.$secs; else $dates .= $secs; break;
+               // AM/PM
+               // Note 00:00 to 11:59 is AM, while 12:00 to 23:59 is PM
+               case 'a':
+                       if ($hour>=12) $dates .= 'pm';
+                       else $dates .= 'am';
+                       break;
+               case 'A':
+                       if ($hour>=12) $dates .= 'PM';
+                       else $dates .= 'AM';
+                       break;
+               default:
+                       $dates .= $fmt[$i]; break;
+               // ESCAPE
+               case "\\": 
+                       $i++;
+                       if ($i < $max) $dates .= $fmt[$i];
+                       break;
+               }
+       }
+       return $dates;
+}
+
+/**
+       Returns a timestamp given a GMT/UTC time. 
+       Note that $is_dst is not implemented and is ignored.
+*/
+function adodb_gmmktime($hr,$min,$sec,$mon=false,$day=false,$year=false,$is_dst=false)
+{
+       return adodb_mktime($hr,$min,$sec,$mon,$day,$year,$is_dst,true);
+}
+
+/**
+       Return a timestamp given a local time. Originally by jackbbs.
+       Note that $is_dst is not implemented and is ignored.
+       
+       Not a very fast algorithm - O(n) operation. Could be optimized to O(1).
+*/
+function adodb_mktime($hr,$min,$sec,$mon=false,$day=false,$year=false,$is_dst=false,$is_gmt=false) 
+{
+       if (!defined('ADODB_TEST_DATES')) {
+
+               if ($mon === false) {
+                       return $is_gmt? @gmmktime($hr,$min,$sec): @mktime($hr,$min,$sec);
+               }
+               
+               // for windows, we don't check 1970 because with timezone differences, 
+               // 1 Jan 1970 could generate negative timestamp, which is illegal
+               if (1971 < $year && $year < 2038
+                       || !defined('ADODB_NO_NEGATIVE_TS') && (1901 < $year && $year < 2038)
+                       ) {
+                               return $is_gmt ?
+                                       @gmmktime($hr,$min,$sec,$mon,$day,$year):
+                                       @mktime($hr,$min,$sec,$mon,$day,$year);
+                       }
+       }
+       
+       $gmt_different = ($is_gmt) ? 0 : adodb_get_gmt_diff();
+
+       /*
+       # disabled because some people place large values in $sec.
+       # however we need it for $mon because we use an array...
+       $hr = intval($hr);
+       $min = intval($min);
+       $sec = intval($sec);
+       */
+       $mon = intval($mon);
+       $day = intval($day);
+       $year = intval($year);
+       
+       
+       $year = adodb_year_digit_check($year);
+
+       if ($mon > 12) {
+               $y = floor($mon / 12);
+               $year += $y;
+               $mon -= $y*12;
+       } else if ($mon < 1) {
+               $y = ceil((1-$mon) / 12);
+               $year -= $y;
+               $mon += $y*12;
+       }
+       
+       $_day_power = 86400;
+       $_hour_power = 3600;
+       $_min_power = 60;
+       
+       $_month_table_normal = array("",31,28,31,30,31,30,31,31,30,31,30,31);
+       $_month_table_leaf = array("",31,29,31,30,31,30,31,31,30,31,30,31);
+       
+       $_total_date = 0;
+       if ($year >= 1970) {
+               for ($a = 1970 ; $a <= $year; $a++) {
+                       $leaf = _adodb_is_leap_year($a);
+                       if ($leaf == true) {
+                               $loop_table = $_month_table_leaf;
+                               $_add_date = 366;
+                       } else {
+                               $loop_table = $_month_table_normal;
+                               $_add_date = 365;
+                       }
+                       if ($a < $year) { 
+                               $_total_date += $_add_date;
+                       } else {
+                               for($b=1;$b<$mon;$b++) {
+                                       $_total_date += $loop_table[$b];
+                               }
+                       }
+               }
+               $_total_date +=$day-1;
+               $ret = $_total_date * $_day_power + $hr * $_hour_power + $min * $_min_power + $sec + $gmt_different;
+       
+       } else {
+               for ($a = 1969 ; $a >= $year; $a--) {
+                       $leaf = _adodb_is_leap_year($a);
+                       if ($leaf == true) {
+                               $loop_table = $_month_table_leaf;
+                               $_add_date = 366;
+                       } else {
+                               $loop_table = $_month_table_normal;
+                               $_add_date = 365;
+                       }
+                       if ($a > $year) { $_total_date += $_add_date;
+                       } else {
+                               for($b=12;$b>$mon;$b--) {
+                                       $_total_date += $loop_table[$b];
+                               }
+                       }
+               }
+               $_total_date += $loop_table[$mon] - $day;
+               
+               $_day_time = $hr * $_hour_power + $min * $_min_power + $sec;
+               $_day_time = $_day_power - $_day_time;
+               $ret = -( $_total_date * $_day_power + $_day_time - $gmt_different);
+               if ($ret < -12220185600) $ret += 10*86400; // if earlier than 5 Oct 1582 - gregorian correction
+               else if ($ret < -12219321600) $ret = -12219321600; // if in limbo, reset to 15 Oct 1582.
+       } 
+       //print " dmy=$day/$mon/$year $hr:$min:$sec => " .$ret;
+       return $ret;
+}
+
+function adodb_gmstrftime($fmt, $ts=false)
+{
+       return adodb_strftime($fmt,$ts,true);
+}
+
+// hack - convert to adodb_date
+function adodb_strftime($fmt, $ts=false,$is_gmt=false)
+{
+global $ADODB_DATE_LOCALE;
+
+       if (!defined('ADODB_TEST_DATES')) {
+               if ((abs($ts) <= 0x7FFFFFFF)) { // check if number in 32-bit signed range
+                       if (!defined('ADODB_NO_NEGATIVE_TS') || $ts >= 0) // if windows, must be +ve integer
+                               return ($is_gmt)? @gmstrftime($fmt,$ts): @strftime($fmt,$ts);
+
+               }
+       }
+       
+       if (empty($ADODB_DATE_LOCALE)) {
+               $tstr = strtoupper(gmstrftime('%c',31366800)); // 30 Dec 1970, 1 am
+               $sep = substr($tstr,2,1);
+               $hasAM = strrpos($tstr,'M') !== false;
+               
+               $ADODB_DATE_LOCALE = array();
+               $ADODB_DATE_LOCALE[] =  strncmp($tstr,'30',2) == 0 ? 'd'.$sep.'m'.$sep.'y' : 'm'.$sep.'d'.$sep.'y';     
+               $ADODB_DATE_LOCALE[]  = ($hasAM) ? 'h:i:s a' : 'H:i:s';
+                       
+       }
+       $inpct = false;
+       $fmtdate = '';
+       for ($i=0,$max = strlen($fmt); $i < $max; $i++) {
+               $ch = $fmt[$i];
+               if ($ch == '%') {
+                       if ($inpct) {
+                               $fmtdate .= '%';
+                               $inpct = false;
+                       } else
+                               $inpct = true;
+               } else if ($inpct) {
+               
+                       $inpct = false;
+                       switch($ch) {
+                       case '0':
+                       case '1':
+                       case '2':
+                       case '3':
+                       case '4':
+                       case '5':
+                       case '6':
+                       case '7':
+                       case '8':
+                       case '9':
+                       case 'E':
+                       case 'O':
+                               /* ignore format modifiers */
+                               $inpct = true; 
+                               break;
+                               
+                       case 'a': $fmtdate .= 'D'; break;
+                       case 'A': $fmtdate .= 'l'; break;
+                       case 'h':
+                       case 'b': $fmtdate .= 'M'; break;
+                       case 'B': $fmtdate .= 'F'; break;
+                       case 'c': $fmtdate .= $ADODB_DATE_LOCALE[0].$ADODB_DATE_LOCALE[1]; break;
+                       case 'C': $fmtdate .= '\C?'; break; // century
+                       case 'd': $fmtdate .= 'd'; break;
+                       case 'D': $fmtdate .= 'm/d/y'; break;
+                       case 'e': $fmtdate .= 'j'; break;
+                       case 'g': $fmtdate .= '\g?'; break; //?
+                       case 'G': $fmtdate .= '\G?'; break; //?
+                       case 'H': $fmtdate .= 'H'; break;
+                       case 'I': $fmtdate .= 'h'; break;
+                       case 'j': $fmtdate .= '?z'; $parsej = true; break; // wrong as j=1-based, z=0-basd
+                       case 'm': $fmtdate .= 'm'; break;
+                       case 'M': $fmtdate .= 'i'; break;
+                       case 'n': $fmtdate .= "\n"; break;
+                       case 'p': $fmtdate .= 'a'; break;
+                       case 'r': $fmtdate .= 'h:i:s a'; break;
+                       case 'R': $fmtdate .= 'H:i:s'; break;
+                       case 'S': $fmtdate .= 's'; break;
+                       case 't': $fmtdate .= "\t"; break;
+                       case 'T': $fmtdate .= 'H:i:s'; break;
+                       case 'u': $fmtdate .= '?u'; $parseu = true; break; // wrong strftime=1-based, date=0-based
+                       case 'U': $fmtdate .= '?U'; $parseU = true; break;// wrong strftime=1-based, date=0-based
+                       case 'x': $fmtdate .= $ADODB_DATE_LOCALE[0]; break;
+                       case 'X': $fmtdate .= $ADODB_DATE_LOCALE[1]; break;
+                       case 'w': $fmtdate .= '?w'; $parseu = true; break; // wrong strftime=1-based, date=0-based
+                       case 'W': $fmtdate .= '?W'; $parseU = true; break;// wrong strftime=1-based, date=0-based
+                       case 'y': $fmtdate .= 'y'; break;
+                       case 'Y': $fmtdate .= 'Y'; break;
+                       case 'Z': $fmtdate .= 'T'; break;
+                       }
+               } else if (('A' <= ($ch) && ($ch) <= 'Z' ) || ('a' <= ($ch) && ($ch) <= 'z' ))
+                       $fmtdate .= "\\".$ch;
+               else
+                       $fmtdate .= $ch;
+       }
+       //echo "fmt=",$fmtdate,"<br>";
+       if ($ts === false) $ts = time();
+       $ret = adodb_date($fmtdate, $ts, $is_gmt);
+       return $ret;
+}
+
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/adodb/adodb/adodb-xmlschema.inc.php b/typo3/sysext/adodb/adodb/adodb-xmlschema.inc.php
new file mode 100644 (file)
index 0000000..bd1b04a
--- /dev/null
@@ -0,0 +1,2216 @@
+<?php
+// Copyright (c) 2004 ars Cognita Inc., all rights reserved
+/* ******************************************************************************
+    Released under both BSD license and Lesser GPL library license. 
+       Whenever there is any discrepancy between the two licenses, 
+       the BSD license will take precedence. 
+*******************************************************************************/
+/**
+ * xmlschema is a class that allows the user to quickly and easily
+ * build a database on any ADOdb-supported platform using a simple
+ * XML schema.
+ *
+ * Last Editor: $Author$
+ * @author Richard Tango-Lowy & Dan Cech
+ * @version $Revision$
+ *
+ * @package axmls
+ * @tutorial getting_started.pkg
+ */
+function _file_get_contents($file) 
+{
+       if (function_exists('file_get_contents')) return file_get_contents($file);
+       
+       $f = fopen($file,'r');
+       if (!$f) return '';
+       $t = '';
+       
+       while ($s = fread($f,100000)) $t .= $s;
+       fclose($f);
+       return $t;
+}
+
+
+/**
+* Debug on or off
+*/
+if( !defined( 'XMLS_DEBUG' ) ) {
+       define( 'XMLS_DEBUG', FALSE );
+}
+
+/**
+* Default prefix key
+*/
+if( !defined( 'XMLS_PREFIX' ) ) {
+       define( 'XMLS_PREFIX', '%%P' );
+}
+
+/**
+* Maximum length allowed for object prefix
+*/
+if( !defined( 'XMLS_PREFIX_MAXLEN' ) ) {
+       define( 'XMLS_PREFIX_MAXLEN', 10 );
+}
+
+/**
+* Execute SQL inline as it is generated
+*/
+if( !defined( 'XMLS_EXECUTE_INLINE' ) ) {
+       define( 'XMLS_EXECUTE_INLINE', FALSE );
+}
+
+/**
+* Continue SQL Execution if an error occurs?
+*/
+if( !defined( 'XMLS_CONTINUE_ON_ERROR' ) ) {
+       define( 'XMLS_CONTINUE_ON_ERROR', FALSE );
+}
+
+/**
+* Current Schema Version
+*/
+if( !defined( 'XMLS_SCHEMA_VERSION' ) ) {
+       define( 'XMLS_SCHEMA_VERSION', '0.2' );
+}
+
+/**
+* Default Schema Version.  Used for Schemas without an explicit version set.
+*/
+if( !defined( 'XMLS_DEFAULT_SCHEMA_VERSION' ) ) {
+       define( 'XMLS_DEFAULT_SCHEMA_VERSION', '0.1' );
+}
+
+/**
+* Default Schema Version.  Used for Schemas without an explicit version set.
+*/
+if( !defined( 'XMLS_DEFAULT_UPGRADE_METHOD' ) ) {
+       define( 'XMLS_DEFAULT_UPGRADE_METHOD', 'ALTER' );
+}
+
+/**
+* Include the main ADODB library
+*/
+if( !defined( '_ADODB_LAYER' ) ) {
+       require( 'adodb.inc.php' );
+       require( 'adodb-datadict.inc.php' );
+}
+
+/**
+* Abstract DB Object. This class provides basic methods for database objects, such
+* as tables and indexes.
+*
+* @package axmls
+* @access private
+*/
+class dbObject {
+       
+       /**
+       * var object Parent
+       */
+       var $parent;
+       
+       /**
+       * var string current element
+       */
+       var $currentElement;
+       
+       /**
+       * NOP
+       */
+       function dbObject( &$parent, $attributes = NULL ) {
+               $this->parent =& $parent;
+       }
+       
+       /**
+       * XML Callback to process start elements
+       *
+       * @access private
+       */
+       function _tag_open( &$parser, $tag, $attributes ) {
+               
+       }
+       
+       /**
+       * XML Callback to process CDATA elements
+       *
+       * @access private
+       */
+       function _tag_cdata( &$parser, $cdata ) {
+               
+       }
+       
+       /**
+       * XML Callback to process end elements
+       *
+       * @access private
+       */
+       function _tag_close( &$parser, $tag ) {
+               
+       }
+       
+       function create() {
+               return array();
+       }
+       
+       /**
+       * Destroys the object
+       */
+       function destroy() {
+               unset( $this );
+       }
+       
+       /**
+       * Checks whether the specified RDBMS is supported by the current
+       * database object or its ranking ancestor.
+       *
+       * @param string $platform RDBMS platform name (from ADODB platform list).
+       * @return boolean TRUE if RDBMS is supported; otherwise returns FALSE.
+       */
+       function supportedPlatform( $platform = NULL ) {
+               return is_object( $this->parent ) ? $this->parent->supportedPlatform( $platform ) : TRUE;
+       }
+       
+       /**
+       * Returns the prefix set by the ranking ancestor of the database object.
+       *
+       * @param string $name Prefix string.
+       * @return string Prefix.
+       */
+       function prefix( $name = '' ) {
+               return is_object( $this->parent ) ? $this->parent->prefix( $name ) : $name;
+       }
+       
+       /**
+       * Extracts a field ID from the specified field.
+       *
+       * @param string $field Field.
+       * @return string Field ID.
+       */
+       function FieldID( $field ) {
+               return strtoupper( preg_replace( '/^`(.+)`$/', '$1', $field ) );
+       }
+}
+
+/**
+* Creates a table object in ADOdb's datadict format
+*
+* This class stores information about a database table. As charactaristics
+* of the table are loaded from the external source, methods and properties
+* of this class are used to build up the table description in ADOdb's
+* datadict format.
+*
+* @package axmls
+* @access private
+*/
+class dbTable extends dbObject {
+       
+       /**
+       * @var string Table name
+       */
+       var $name;
+       
+       /**
+       * @var array Field specifier: Meta-information about each field
+       */
+       var $fields = array();
+       
+       /**
+       * @var array List of table indexes.
+       */
+       var $indexes = array();
+       
+       /**
+       * @var array Table options: Table-level options
+       */
+       var $opts = array();
+       
+       /**
+       * @var string Field index: Keeps track of which field is currently being processed
+       */
+       var $current_field;
+       
+       /**
+       * @var boolean Mark table for destruction
+       * @access private
+       */
+       var $drop_table;
+       
+       /**
+       * @var boolean Mark field for destruction (not yet implemented)
+       * @access private
+       */
+       var $drop_field = array();
+       
+       /**
+       * Iniitializes a new table object.
+       *
+       * @param string $prefix DB Object prefix
+       * @param array $attributes Array of table attributes.
+       */
+       function dbTable( &$parent, $attributes = NULL ) {
+               $this->parent =& $parent;
+               $this->name = $this->prefix($attributes['NAME']);
+       }
+       
+       /**
+       * XML Callback to process start elements. Elements currently 
+       * processed are: INDEX, DROP, FIELD, KEY, NOTNULL, AUTOINCREMENT & DEFAULT. 
+       *
+       * @access private
+       */
+       function _tag_open( &$parser, $tag, $attributes ) {
+               $this->currentElement = strtoupper( $tag );
+               
+               switch( $this->currentElement ) {
+                       case 'INDEX':
+                               if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
+                                       xml_set_object( $parser, $this->addIndex( $attributes ) );
+                               }
+                               break;
+                       case 'DATA':
+                               if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
+                                       xml_set_object( $parser, $this->addData( $attributes ) );
+                               }
+                               break;
+                       case 'DROP':
+                               $this->drop();
+                               break;
+                       case 'FIELD':
+                               // Add a field
+                               $fieldName = $attributes['NAME'];
+                               $fieldType = $attributes['TYPE'];
+                               $fieldSize = isset( $attributes['SIZE'] ) ? $attributes['SIZE'] : NULL;
+                               $fieldOpts = isset( $attributes['OPTS'] ) ? $attributes['OPTS'] : NULL;
+                               
+                               $this->addField( $fieldName, $fieldType, $fieldSize, $fieldOpts );
+                               break;
+                       case 'KEY':
+                       case 'NOTNULL':
+                       case 'AUTOINCREMENT':
+                               // Add a field option
+                               $this->addFieldOpt( $this->current_field, $this->currentElement );
+                               break;
+                       case 'DEFAULT':
+                               // Add a field option to the table object
+                               
+                               // Work around ADOdb datadict issue that misinterprets empty strings.
+                               if( $attributes['VALUE'] == '' ) {
+                                       $attributes['VALUE'] = " '' ";
+                               }
+                               
+                               $this->addFieldOpt( $this->current_field, $this->currentElement, $attributes['VALUE'] );
+                               break;
+                       case 'DEFDATE':
+                       case 'DEFTIMESTAMP':
+                               // Add a field option to the table object
+                               $this->addFieldOpt( $this->current_field, $this->currentElement );
+                               break;
+                       default:
+                               // print_r( array( $tag, $attributes ) );
+               }
+       }
+       
+       /**
+       * XML Callback to process CDATA elements
+       *
+       * @access private
+       */
+       function _tag_cdata( &$parser, $cdata ) {
+               switch( $this->currentElement ) {
+                       // Table constraint
+                       case 'CONSTRAINT':
+                               if( isset( $this->current_field ) ) {
+                                       $this->addFieldOpt( $this->current_field, $this->currentElement, $cdata );
+                               } else {
+                                       $this->addTableOpt( $cdata );
+                               }
+                               break;
+                       // Table option
+                       case 'OPT':
+                               $this->addTableOpt( $cdata );
+                               break;
+                       default:
+                               
+               }
+       }
+       
+       /**
+       * XML Callback to process end elements
+       *
+       * @access private
+       */
+       function _tag_close( &$parser, $tag ) {
+               $this->currentElement = '';
+               
+               switch( strtoupper( $tag ) ) {
+                       case 'TABLE':
+                               $this->parent->addSQL( $this->create( $this->parent ) );
+                               xml_set_object( $parser, $this->parent );
+                               $this->destroy();
+                               break;
+                       case 'FIELD':
+                               unset($this->current_field);
+                               break;
+
+               }
+       }
+       
+       /**
+       * Adds an index to a table object
+       *
+       * @param array $attributes Index attributes
+       * @return object dbIndex object
+       */
+       function &addIndex( $attributes ) {
+               $name = strtoupper( $attributes['NAME'] );
+               $this->indexes[$name] =& new dbIndex( $this, $attributes );
+               return $this->indexes[$name];
+       }
+       
+       /**
+       * Adds data to a table object
+       *
+       * @param array $attributes Data attributes
+       * @return object dbData object
+       */
+       function &addData( $attributes ) {
+               if( !isset( $this->data ) ) {
+                       $this->data =& new dbData( $this, $attributes );
+               }
+               return $this->data;
+       }
+       
+       /**
+       * Adds a field to a table object
+       *
+       * $name is the name of the table to which the field should be added. 
+       * $type is an ADODB datadict field type. The following field types
+       * are supported as of ADODB 3.40:
+       *       - C:  varchar
+       *       - X:  CLOB (character large object) or largest varchar size
+       *          if CLOB is not supported
+       *       - C2: Multibyte varchar
+       *       - X2: Multibyte CLOB
+       *       - B:  BLOB (binary large object)
+       *       - D:  Date (some databases do not support this, and we return a datetime type)
+       *       - T:  Datetime or Timestamp
+       *       - L:  Integer field suitable for storing booleans (0 or 1)
+       *       - I:  Integer (mapped to I4)
+       *       - I1: 1-byte integer
+       *       - I2: 2-byte integer
+       *       - I4: 4-byte integer
+       *       - I8: 8-byte integer
+       *       - F:  Floating point number
+       *       - N:  Numeric or decimal number
+       *
+       * @param string $name Name of the table to which the field will be added.
+       * @param string $type   ADODB datadict field type.
+       * @param string $size   Field size
+       * @param array $opts    Field options array
+       * @return array Field specifier array
+       */
+       function addField( $name, $type, $size = NULL, $opts = NULL ) {
+               $field_id = $this->FieldID( $name );
+               
+               // Set the field index so we know where we are
+               $this->current_field = $field_id;
+               
+               // Set the field name (required)
+               $this->fields[$field_id]['NAME'] = $name;
+               
+               // Set the field type (required)
+               $this->fields[$field_id]['TYPE'] = $type;
+               
+               // Set the