summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE/bug_report.md32
-rw-r--r--SECURITY.md2
-rw-r--r--adodb-lib.inc.php254
-rw-r--r--adodb-time.inc.php1482
-rw-r--r--adodb.inc.php136
-rw-r--r--composer.json4
-rw-r--r--docs/changelog.md46
-rw-r--r--drivers/adodb-ado.inc.php10
-rw-r--r--drivers/adodb-ado5.inc.php10
-rw-r--r--drivers/adodb-ads.inc.php23
-rw-r--r--drivers/adodb-db2.inc.php11
-rw-r--r--drivers/adodb-fbsql.inc.php24
-rw-r--r--drivers/adodb-firebird.inc.php18
-rw-r--r--drivers/adodb-ibase.inc.php7
-rw-r--r--drivers/adodb-informix72.inc.php11
-rw-r--r--drivers/adodb-ldap.inc.php35
-rw-r--r--drivers/adodb-mssql.inc.php12
-rw-r--r--drivers/adodb-mssqlnative.inc.php49
-rw-r--r--drivers/adodb-mysqli.inc.php166
-rw-r--r--drivers/adodb-oci8.inc.php123
-rw-r--r--drivers/adodb-odbc.inc.php11
-rw-r--r--drivers/adodb-odbtp.inc.php9
-rw-r--r--drivers/adodb-oracle.inc.php15
-rw-r--r--drivers/adodb-pdo.inc.php99
-rw-r--r--drivers/adodb-postgres64.inc.php335
-rw-r--r--drivers/adodb-sqlite.inc.php13
-rw-r--r--drivers/adodb-sqlite3.inc.php11
-rw-r--r--drivers/adodb-sybase.inc.php14
-rw-r--r--replicate/adodb-replicate.inc.php1179
-rw-r--r--replicate/replicate-steps.php156
-rw-r--r--replicate/test-tnb.php440
-rw-r--r--scripts/adodbutil.py182
-rwxr-xr-xscripts/announce.py253
-rw-r--r--scripts/env.yml.sample27
-rw-r--r--scripts/fix-static-docs.php251
-rwxr-xr-xscripts/uploadrelease.py44
-rw-r--r--session/adodb-session2.php87
-rw-r--r--session/old/adodb-cryptsession.php331
-rw-r--r--session/old/adodb-session-clob.php457
-rw-r--r--session/old/adodb-session.php449
-rw-r--r--session/old/crypt.inc.php83
-rw-r--r--tests/PdoDriverTest.php160
-rw-r--r--tests/test.php3
-rw-r--r--tests/time.php35
44 files changed, 1540 insertions, 5559 deletions
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 00000000..8b7038aa
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,32 @@
+---
+name: Bug report
+about: Submit a new bug report to help us improve ADOdb
+title: ''
+labels: 'triage'
+assignees: ''
+
+---
+
+### Description
+A clear and concise description of what the problem is, including relevant error messages and stack trace.
+
+### Environment
+- ADOdb version: _Version number (or Git Commit/Ref)_
+- Driver or Module:
+- Database type and version:
+- PHP version:
+- Platform:
+
+* [ ] I have tested that the problem is reproducible in the [latest release](https://github.com/ADOdb/ADOdb/releases/latest) / **master** branch / **hotfix** branch
+ ⚠️ Keep only the applicable option(s), i.e. where you actually tested and remove the others)
+
+### Steps to reproduce
+Detailed, step-by-step instructions to reproduce the behavior, including:
+- code snippet
+- SQL to create and populate database objects used by the code snippet
+
+### Expected behavior
+A clear and concise description of what you expected to happen.
+
+### Additional context
+Add any other information relevant to the problem here.
diff --git a/SECURITY.md b/SECURITY.md
index 00670f24..a52a6c2c 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -19,7 +19,7 @@ If you discover a vulnerability in ADOdb, please contact
the [project's maintainer](https://github.com/dregad)
- by e-mail (look for it in the Git history)
-- via private chat on [Gitter](https://gitter.im/dregad)
+- via private chat on [Matrix](https://matrix.to/#/@dregad:matrix.org)
Kindly provide the following information in your report:
diff --git a/adodb-lib.inc.php b/adodb-lib.inc.php
index 90b8b9d6..72514f40 100644
--- a/adodb-lib.inc.php
+++ b/adodb-lib.inc.php
@@ -1175,104 +1175,108 @@ function _adodb_column_sql(&$zthis, $action, $type, $fname, $fnameq, $arrFields,
* @param string|string[] $sql A string or array of SQL statements
* @param string[]|null $inputarr An optional array of bind parameters
*
-* @return handle|void A handle to the executed query
+* @return mixed A handle to the executed query (actual type is driver-dependent)
*/
function _adodb_debug_execute($zthis, $sql, $inputarr)
{
+ // Execute the query, capturing any output
+ ob_start();
+ $queryId = $zthis->_query($sql, $inputarr);
+ $queryOutput = ob_get_clean();
+
+ // Get last error number and message if query execution failed
+ if (!$queryId) {
+ if ($zthis->databaseType == 'mssql') {
+ // Alexios Fakios notes that ErrorMsg() must be called before ErrorNo() for mssql
+ // because ErrorNo() calls Execute('SELECT @ERROR'), causing recursion
+ // ErrorNo is a slow function call in mssql
+ $errMsg = $zthis->ErrorMsg();
+ if ($errMsg && ($errNo = $zthis->ErrorNo())) {
+ $queryOutput .= $errNo . ': ' . $errMsg . "\n";
+ }
+ } else {
+ $errNo = $zthis->ErrorNo();
+ if ($errNo) {
+ $queryOutput .= $errNo . ': ' . $zthis->ErrorMsg() . "\n";
+ }
+ }
+ }
+
+ // Driver name
+ $driverName = $zthis->databaseType;
+ if (!isset($zthis->dsnType)) {
+ // Append the PDO driver name
+ $driverName .= '-' . $zthis->dsnType;
+ }
+
+ // Prepare SQL statement for display (remove newlines and tabs, compress repeating spaces)
+ $sqlText = preg_replace('/\s+/', ' ', is_array($sql) ? $sql[0] : $sql);
+
// Unpack the bind parameters
- $ss = '';
+ $bindParams = '';
if ($inputarr) {
+ $MAXSTRLEN = 64;
foreach ($inputarr as $kk => $vv) {
- if (is_string($vv) && strlen($vv) > 64) {
- $vv = substr($vv, 0, 64) . '...';
+ if (is_string($vv) && strlen($vv) > $MAXSTRLEN) {
+ $vv = substr($vv, 0, $MAXSTRLEN) . '...';
}
if (is_null($vv)) {
- $ss .= "($kk=>null) ";
+ $bindParams .= "$kk=>null\n";
} else {
if (is_array($vv)) {
$vv = sprintf("Array Of Values: [%s]", implode(',', $vv));
}
- $ss .= "($kk=>'$vv') ";
+ $bindParams .= "$kk=>'$vv'\n";
}
}
- $ss = "[ $ss ]";
}
- $sqlTxt = is_array($sql) ? $sql[0] : $sql;
-
- // Remove newlines and tabs, compress repeating spaces
- $sqlTxt = preg_replace('/\s+/', ' ', $sqlTxt);
-
// check if running from browser or command-line
- $inBrowser = isset($_SERVER['HTTP_USER_AGENT']);
-
- $myDatabaseType = $zthis->databaseType;
- if (!isset($zthis->dsnType)) {
- // Append the PDO driver name
- $myDatabaseType .= '-' . $zthis->dsnType;
- }
+ $isHtml = isset($_SERVER['HTTP_USER_AGENT']);
- if ($inBrowser) {
- if ($ss) {
- // Default formatting for passed parameter
- $ss = sprintf('<code class="adodb-debug">%s</code>', htmlspecialchars($ss));
+ // Output format - sprintf parameters:
+ // %1 = horizontal line, %2 = DB driver, %3 = SQL statement, %4 = Query params
+ if ($isHtml) {
+ $fmtSql = '<div class="adodb-debug">' . PHP_EOL
+ . '<div class="adodb-debug-sql">' . PHP_EOL
+ . '%1$s<table>' . PHP_EOL
+ . '<tr><th>%2$s</th><td><code>%3$s</code></td></tr>' . PHP_EOL
+ . '%4$s</table>%1$s' . PHP_EOL
+ . '</div>' . PHP_EOL;
+ $hr = $zthis->debug === -1 ? '' : '<hr>';
+ $sqlText = htmlspecialchars($sqlText);
+ if ($bindParams) {
+ $bindParams = '<tr><th>Parameters</th><td><code>'
+ . nl2br(htmlspecialchars($bindParams))
+ . '</code></td></tr>' . PHP_EOL;
}
- if ($zthis->debug === -1) {
- $outString = "<br class='adodb-debug'>(%s): %s &nbsp; %s<br class='adodb-debug'>";
- ADOConnection::outp(sprintf($outString, $myDatabaseType, htmlspecialchars($sqlTxt), $ss), false);
- } elseif ($zthis->debug !== -99) {
- $outString = "<hr class='adodb-debug'>(%s): %s &nbsp; %s<hr class='adodb-debug'>";
- ADOConnection::outp(sprintf($outString, $myDatabaseType, htmlspecialchars($sqlTxt), $ss), false);
+ if ($queryOutput) {
+ $queryOutput = '<div class="adodb-debug-errmsg">' . $queryOutput . '</div>' . PHP_EOL;
}
} else {
// CLI output
- if ($zthis->debug !== -99) {
- $outString = sprintf("%s\n%s\n %s %s \n%s\n", str_repeat('-', 78), $myDatabaseType, $sqlTxt, $ss, str_repeat('-', 78));
- ADOConnection::outp($outString, false);
- }
+ $fmtSql = '%1$s%2$s: %3$s%4$s%1$s';
+ $hr = $zthis->debug === -1 ? '' : str_repeat('-', 78) . "\n";
+ $sqlText .= "\n";
}
- // Now execute the query
- $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
- if ($emsg = $zthis->ErrorMsg()) {
- if ($err = $zthis->ErrorNo()) {
- if ($zthis->debug === -99) {
- ADOConnection::outp("<hr>\n($myDatabaseType): " . htmlspecialchars($sqlTxt) . " &nbsp; $ss\n<hr>\n", false);
- }
-
- ADOConnection::outp($err . ': ' . $emsg);
- }
- }
- } else {
- if (!$qID) {
- // Statement execution has failed
- if ($zthis->debug === -99) {
- if ($inBrowser) {
- $outString = "<hr class='adodb-debug'>(%s): %s &nbsp; %s<hr class='adodb-debug'>";
- ADOConnection::outp(sprintf($outString, $myDatabaseType, htmlspecialchars($sqlTxt), $ss), false);
- } else {
- $outString = sprintf("%s\n%s\n %s %s \n%s\n",str_repeat('-',78),$myDatabaseType,$sqlTxt,$ss,str_repeat('-',78));
- ADOConnection::outp($outString, false);
- }
- }
-
- // Send last error to output
- $errno = $zthis->ErrorNo();
- if ($errno) {
- ADOConnection::outp($errno . ': ' . $zthis->ErrorMsg());
- }
+ // Always output debug info if statement execution failed
+ if (!$queryId || $zthis->debug !== -99) {
+ printf($fmtSql, $hr, $driverName, $sqlText, $bindParams);
+ if ($queryOutput) {
+ echo $queryOutput . ($isHtml ? '' : "\n");
}
}
- if ($qID === false || $zthis->debug === 99) {
- _adodb_backtrace();
+ // Print backtrace if query failed or forced
+ if ($queryId === false || $zthis->debug === 99) {
+ _adodb_backtrace(true, 0, 0, $isHtml);
+ }
+ if ($isHtml && $zthis->debug !== -99) {
+ echo '</div>' . PHP_EOL;
}
- return $qID;
+
+ return $queryId;
}
/**
@@ -1281,73 +1285,60 @@ function _adodb_debug_execute($zthis, $sql, $inputarr)
* @param string[]|bool $printOrArr Whether to print the result directly or return the result
* @param int $maximumDepth The maximum depth of the array to traverse
* @param int $elementsToIgnore The backtrace array indexes to ignore
- * @param null|bool $ishtml True if we are in a CGI environment, false for CLI,
+ * @param null|bool $isHtml True if we are in a CGI environment, false for CLI,
* null to auto detect
*
* @return string Formatted backtrace
*/
-function _adodb_backtrace($printOrArr=true, $maximumDepth=9999, $elementsToIgnore=0, $ishtml=null)
+function _adodb_backtrace($printOrArr=true, $maximumDepth=0, $elementsToIgnore=0, $isHtml=null)
{
- if (!function_exists('debug_backtrace')) {
- return '';
+ if ($isHtml === null) {
+ // Auto determine if we in a CGI environment
+ $isHtml = isset($_SERVER['HTTP_USER_AGENT']);
}
- if ($ishtml === null) {
- // Auto determine if we in a CGI enviroment
- $html = (isset($_SERVER['HTTP_USER_AGENT']));
+ $s = "Call stack (most recent call first):\n";
+ if ($isHtml) {
+ $s = '<div class="adodb-debug-trace">' . PHP_EOL
+ . "<h4>$s</h4>\n"
+ . '<table>' . PHP_EOL
+ . '<thead><tr><th>#</th><th>Function</th><th>Location</th></tr></thead>' . PHP_EOL;
+ $fmt = '<tr><td>%1$d</td><td>%2$s</td><td>%3$s line %4$d</td></tr>' . PHP_EOL;
} else {
- $html = $ishtml;
+ $fmt = '%1$2d. %2$s in %3$s line %4$d' . PHP_EOL;
}
- $cgiString = "</font><font color=#808080 size=-1> %% line %4d, file: <a href=\"file:/%s\">%s</a></font>";
- $cliString = "%% line %4d, file: %s";
- $fmt = ($html) ? $cgiString : $cliString;
-
+ // Maximum length for string arguments display
$MAXSTRLEN = 128;
- $s = ($html) ? '<pre align=left>' : '';
-
+ // Get 2 extra elements if max depth is specified
+ if ($maximumDepth) {
+ $maximumDepth += 2;
+ }
if (is_array($printOrArr)) {
- $traceArr = $printOrArr;
+ $traceArr = array_slice($printOrArr, 0, $maximumDepth);
} else {
- $traceArr = debug_backtrace();
+ $traceArr = debug_backtrace(0, $maximumDepth);
}
- // Remove first 2 elements that just show calls to adodb_backtrace
- array_shift($traceArr);
- array_shift($traceArr);
-
- // We want last element to have no indent
- $tabs = sizeof($traceArr) - 1;
+ // Remove elements to ignore, plus the first 2 elements that just show
+ // calls to adodb_backtrace
+ for ($elementsToIgnore += 2; $elementsToIgnore > 0; $elementsToIgnore--) {
+ array_shift($traceArr);
+ }
+ $elements = sizeof($traceArr);
- foreach ($traceArr as $arr) {
- if ($elementsToIgnore) {
- // Ignore array element at start of array
- $elementsToIgnore--;
- $tabs--;
- continue;
- }
- $maximumDepth--;
- if ($maximumDepth < 0) {
- break;
+ foreach ($traceArr as $element) {
+ // Function name with class prefix
+ $functionName = $element['function'];
+ if (isset($element['class'])) {
+ $functionName = $element['class'] . '::' . $functionName;
}
+ // Function arguments
$args = array();
-
- if ($tabs) {
- $s .= str_repeat($html ? ' &nbsp; ' : "\t", $tabs);
- $tabs--;
- }
- 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 (isset($element['args'])) {
+ foreach ($element['args'] as $v) {
if (is_null($v)) {
$args[] = 'null';
} elseif (is_array($v)) {
@@ -1357,29 +1348,34 @@ function _adodb_backtrace($printOrArr=true, $maximumDepth=9999, $elementsToIgnor
} elseif (is_bool($v)) {
$args[] = $v ? 'true' : 'false';
} else {
- $v = (string)@$v;
- // Truncate
- $v = substr($v, 0, $MAXSTRLEN);
// Remove newlines and tabs, compress repeating spaces
$v = preg_replace('/\s+/', ' ', $v);
- // Convert htmlchars (not sure why we do this in CLI)
- $str = htmlspecialchars($v);
+ // Truncate if needed
if (strlen($v) > $MAXSTRLEN) {
- $str .= '...';
+ $v = substr($v, 0, $MAXSTRLEN) . '...';
}
- $args[] = $str;
+ $args[] = $isHtml ? htmlspecialchars($v) : $v;
}
}
}
- $s .= $arr['function'] . '(' . implode(', ', $args) . ')';
- $s .= @sprintf($fmt, $arr['line'], $arr['file'], basename($arr['file']));
- $s .= "\n";
+
+ // Shorten ADOdb paths ('/path/to/adodb/XXX' printed as '.../XXX')
+ $file = str_replace(__DIR__, '...', $element['file']);
+
+ $s .= sprintf($fmt,
+ $elements--,
+ $functionName . '(' . implode(', ', $args) . ')',
+ $file,
+ $element['line']
+ );
}
- if ($html) {
- $s .= '</pre>';
+
+ if ($isHtml) {
+ $s .= '</table>' . PHP_EOL . '</div>' . PHP_EOL;
}
+
if ($printOrArr) {
print $s;
}
diff --git a/adodb-time.inc.php b/adodb-time.inc.php
deleted file mode 100644
index 0c3dd11d..00000000
--- a/adodb-time.inc.php
+++ /dev/null
@@ -1,1482 +0,0 @@
-<?php
-/**
- * ADOdb Date Library.
- *
- * @deprecated 5.22.6 Use 64-bit PHP native functions instead.
- *
- * 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().
- *
- * Replaces native functions as follows:
- * - 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()
- *
- * 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.
- *
- * To improve performance, the native date functions are used whenever
- * possible, the library only switches to PHP code when the dates fall outside
- * of the 32-bit signed integer range.
- *
- * This library is independent of the rest of ADOdb, and can be used
- * as standalone code.
- *
- * 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). 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)
- *
- * This file is part of ADOdb, a Database Abstraction Layer library for PHP.
- *
- * @package ADOdb
- * @link https://adodb.org Project's web site and documentation
- * @link https://github.com/ADOdb/ADOdb Source code and issue tracker
- *
- * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause
- * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option,
- * any later version. This means you can use it in proprietary products.
- * See the LICENSE.md file distributed with this source code for details.
- * @license BSD-3-Clause
- * @license LGPL-2.1-or-later
- *
- * @copyright 2003-2013 John Lim
- * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community
- */
-
-/*
-=============================================================================
-
-FUNCTION DESCRIPTIONS
-
-** FUNCTION adodb_time()
-
-Returns the current time measured in the number of seconds since the Unix Epoch (January 1 1970 00:00:00 GMT) as an unsigned integer.
-
-** 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 2822 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
-- 16 Jan 2011 0.36
-Added adodb_time() which returns current time. If > 2038, will return as float
-
-- 7 Feb 2011 0.35
-Changed adodb_date to be symmetric with adodb_mktime. See $jan1_71. fix for bc.
-
-- 13 July 2010 0.34
-Changed adodb_get_gm_diff to use DateTimeZone().
-
-- 11 Feb 2008 0.33
-* Bug in 0.32 fix for hour handling. Fixed.
-
-- 1 Feb 2008 0.32
-* Now adodb_mktime(0,0,0,12+$m,20,2040) works properly.
-
-- 10 Jan 2008 0.31
-* Now adodb_mktime(0,0,0,24,1,2037) works correctly.
-
-- 15 July 2007 0.30
-Added PHP 5.2.0 compatibility fixes.
- * gmtime behaviour for 1970 has changed. We use the actual date if it is between 1970 to 2038 to get the
- * timezone, otherwise we use the current year as the baseline to retrieve the timezone.
- * Also the timezone's in php 5.2.* support historical data better, eg. if timezone today was +8, but
- in 1970 it was +7:30, then php 5.2 return +7:30, while this library will use +8.
- *
-
-- 19 March 2006 0.24
-Changed strftime() locale detection, because some locales prepend the day of week to the date when %c is used.
-
-- 10 Feb 2006 0.23
-PHP5 compat: when we detect PHP5, the RFC2822 format for gmt 0000hrs is changed from -0000 to +0000.
- In PHP4, we will still use -0000 for 100% compat with PHP4.
-
-- 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 PHPLens Issue No: 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.35);
-
-/*
- 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);
-
-if (!DEFINED('ADODB_FUTURE_DATE_CUTOFF_YEARS'))
- DEFINE('ADODB_FUTURE_DATE_CUTOFF_YEARS',200);
-
-function adodb_date_test_date($y1,$m,$d=13)
-{
- $h = round(rand()% 24);
- $t = adodb_mktime($h,0,0,$m,$d,$y1);
- $rez = adodb_date('Y-n-j H:i:s',$t);
- if ($h == 0) $h = '00';
- else if ($h < 10) $h = '0'.$h;
- if ("$y1-$m-$d $h:00:00" != $rez) {
- print "<b>$y1 error, expected=$y1-$m-$d $h: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()
-{
-
- for ($m=-24; $m<=24; $m++)
- echo "$m :",adodb_date('d-m-Y',adodb_mktime(0,0,0,1+$m,20,2040)),"<br>";
-
- 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);
-
- $t = time();
-
-
- $fmt = 'Y-m-d H:i:s';
- echo '<pre>';
- echo 'adodb: ',adodb_date($fmt,$t),'<br>';
- echo 'php : ',date($fmt,$t),'<br>';
- echo '</pre>';
-
- 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 formatting
- print "<p>Testing date formatting</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\C2822 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>";
-}
-
-function adodb_time()
-{
- $d = new DateTime();
- return $d->format('U');
-}
-
-/**
- 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;
-}
-
-function adodb_get_gmt_diff_ts($ts)
-{
- if (0 <= $ts && $ts <= 0x7FFFFFFF) { // check if number in 32-bit signed range) {
- $arr = getdate($ts);
- $y = $arr['year'];
- $m = $arr['mon'];
- $d = $arr['mday'];
- return adodb_get_gmt_diff($y,$m,$d);
- } else {
- return adodb_get_gmt_diff(false,false,false);
- }
-
-}
-
-/**
- get local time zone offset from GMT. Does not handle historical timezones before 1970.
-*/
-function adodb_get_gmt_diff($y,$m,$d)
-{
- static $TZ,$tzo;
-
- if (!defined('ADODB_TEST_DATES')) $y = false;
- else if ($y < 1970 || $y >= 2038) $y = false;
-
- if ($y !== false) {
- $dt = new DateTime();
- $dt->setISODate($y,$m,$d);
- if (empty($tzo)) {
- $tzo = new DateTimeZone(date_default_timezone_get());
- # $tzt = timezone_transitions_get( $tzo );
- }
- return -$tzo->getOffset($dt);
- } else {
- if (isset($TZ)) return $TZ;
- $y = date('Y');
- /*
- if (function_exists('date_default_timezone_get') && function_exists('timezone_offset_get')) {
- $tzonename = date_default_timezone_get();
- if ($tzonename) {
- $tobj = new DateTimeZone($tzonename);
- $TZ = -timezone_offset_get($tobj,new DateTime("now",$tzo));
- }
- }
- */
- if (empty($TZ)) $TZ = mktime(0,0,0,12,2,$y) - gmmktime(0,0,0,12,2,$y);
- }
- 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, $_adodb_last_date_call_failed;
-
- $_adodb_last_date_call_failed = false;
-
- $d = $origd - ($is_gmt ? 0 : adodb_get_gmt_diff_ts($origd));
- $_day_power = 86400;
- $_hour_power = 3600;
- $_min_power = 60;
-
- $cutoffDate = time() + (60 * 60 * 24 * 365 * ADODB_FUTURE_DATE_CUTOFF_YEARS);
-
- if ($d > $cutoffDate)
- {
- $d = $cutoffDate;
- $_adodb_last_date_call_failed = true;
- }
-
- 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
- );
-}
-
-/**
- * Compute timezone offset.
- *
- * @param int $gmt Time offset from GMT, in seconds
- * @param bool $ignored Param leftover from removed PHP4-compatibility code
- * kept to avoid altering function signature.
- * @return string
- */
-function adodb_tz_offset($gmt, $ignored=true)
-{
- $zhrs = abs($gmt) / 3600;
- $hrs = floor($zhrs);
- return sprintf('%s%02d%02d', ($gmt <= 0) ? '+' : '-', $hrs, ($zhrs - $hrs) * 60);
-}
-
-
-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;
- static $jan1_1971;
-
- if (!isset($daylight)) {
- $daylight = function_exists('adodb_daylight_sv');
- if (empty($jan1_1971)) $jan1_1971 = mktime(0,0,0,1,1,1971); // we only use date() when > 1970 as adodb_mktime() only uses mktime() when > 1970
- }
-
- if ($d === false) return ($is_gmt)? @gmdate($fmt): @date($fmt);
- if (!defined('ADODB_TEST_DATES')) {
-
- /*
- * Format 'Q' is an ADOdb custom format, not supported in PHP
- * so if there is a 'Q' in the format, we force it to use our
- * function. There is a trivial overhead in this
- */
-
- if ((abs($d) <= 0x7FFFFFFF) && strpos($fmt,'Q') === false)
- { // check if number in 32-bit signed range
-
- if (!defined('ADODB_NO_NEGATIVE_TS') || $d >= $jan1_1971) // 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 ($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 'e':
- $dates .= date('e');
- break;
- case 'T':
- $dt = new DateTime();
- $dt->SetDate($year,$month,$day);
- $dates .= $dt->Format('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($year,$month,$day);
-
- $dates .= ' '.adodb_tz_offset($gmt);
- 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 .= ceil($month / 3);
- 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 'W':
- $dates .= sprintf('%02d',ceil( $arr['yday'] / 7) - 1);
- 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($year,$month,$day); break;
- case 'O':
- $gmt = ($is_gmt) ? 0 : adodb_get_gmt_diff($year,$month,$day);
-
- $dates .= adodb_tz_offset($gmt);
- 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
- $usephpfns = (1970 < $year && $year < 2038
- || !defined('ADODB_NO_NEGATIVE_TS') && (1901 < $year && $year < 2038)
- );
-
-
- if ($usephpfns && ($year + $mon/12+$day/365.25+$hr/(24*365.25) >= 2038)) $usephpfns = false;
-
- if ($usephpfns) {
- 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($year,$mon,$day);
-
- /*
- # 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-1)/ 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;
- */
- # see PHPLens Issue No: 14865 for reasoning, and changelog for version 0.24
- $dstr = gmstrftime('%x',31366800); // 30 Dec 1970, 1 am
- $sep = substr($dstr,2,1);
- $tstr = strtoupper(gmstrftime('%X',31366800)); // 30 Dec 1970, 1 am
- $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;
-}
-
-/**
-* Returns the status of the last date calculation and whether it exceeds
-* the limit of ADODB_FUTURE_DATE_CUTOFF_YEARS
-*
-* @return boolean
-*/
-function adodb_last_date_status()
-{
- global $_adodb_last_date_call_failed;
-
- return $_adodb_last_date_call_failed;
-}
diff --git a/adodb.inc.php b/adodb.inc.php
index 73bef1ef..e521d5db 100644
--- a/adodb.inc.php
+++ b/adodb.inc.php
@@ -198,7 +198,7 @@ if (!defined('_ADODB_LAYER')) {
/**
* ADODB version as a string.
*/
- $ADODB_vers = 'v5.22.6-dev Unreleased';
+ $ADODB_vers = 'v5.23.0-dev Unreleased';
/**
* Determines whether recordset->RecordCount() is used.
@@ -228,19 +228,55 @@ if (!defined('_ADODB_LAYER')) {
*/
#[\AllowDynamicProperties]
class ADOFieldObject {
- var $name = '';
- var $max_length=0;
- var $type="";
-/*
- // additional fields by dannym... (danny_milo@yahoo.com)
- var $not_null = false;
- // actually, this has already been built-in in the postgres, fbsql AND mysql module? ^-^
- // so we can as well make not_null standard (leaving it at "false" does not harm anyways)
+ /**
+ * @var string Field name
+ */
+ public $name = '';
- var $has_default = false; // this one I have done only in mysql and postgres for now ...
- // others to come (dannym)
- var $default_value; // default, if any, and supported. Check has_default first.
-*/
+ /**
+ * @var int Field size
+ */
+ public $max_length = 0;
+
+ /**
+ * @var string Field type.
+ */
+ public $type = '';
+
+ /**
+ * @var int|null Numeric field scale.
+ */
+ public $scale;
+
+ /**
+ * @var bool True if field can be NULL
+ */
+ public $not_null = false;
+
+ /**
+ * @var bool True if field is a primary key
+ */
+ public $primary_key = false;
+
+ /**
+ * @var bool True if field is unique key
+ */
+ public $unique = false;
+
+ /**
+ * @var bool True if field is automatically incremented
+ */
+ public $auto_increment = false;
+
+ /**
+ * @var bool True if field has a default value
+ */
+ public $has_default = false;
+
+ /**
+ * @var mixed Default value, if any and supported; check {@see $has_default} first.
+ */
+ public $default_value;
}
@@ -477,7 +513,29 @@ if (!defined('_ADODB_LAYER')) {
var $port = ''; /// The port of the database server
var $user = ''; /// The username which is used to connect to the database server.
var $password = ''; /// Password for the username. For security, we no longer store it.
- var $debug = false; /// if set to true will output sql statements
+
+ /**
+ * Debug Mode.
+ *
+ * Enables printing of SQL queries execution and additional debugging
+ * information. Can be enabled/disabled at any time after the database
+ * Connection has been initialized {@see ADONewConnection()}.
+ *
+ * Possible values are:
+ * - False: Disabled
+ * - True: Standard mode, prints executed SQL statements and error
+ * information including a Backtrace if the query failed.
+ * - -1: Same as standard mode, but without line separators.
+ * - 99: Prints a Backtrace after every query execution, even if
+ * it was successful.
+ * - -99: Debug information is only printed if query execution failed.
+ *
+ * @see https://adodb.org/dokuwiki/doku.php?id=v5:userguide:debug
+ *
+ * @var bool|int
+ */
+ public $debug = false;
+
var $maxblobsize = 262144; /// maximum size of blobs or large text fields (262144 = 256K)-- some db's die otherwise like foxpro
var $concat_operator = '+'; /// default concat operator -- change to || for Oracle/Interbase
var $substr = 'substr'; /// substring operator
@@ -854,21 +912,15 @@ if (!defined('_ADODB_LAYER')) {
return;
}
- if ($newline) {
- $msg .= "<br>\n";
- }
-
- if (isset($_SERVER['HTTP_USER_AGENT']) || !$newline) {
- echo $msg;
+ if (isset($_SERVER['HTTP_USER_AGENT'])) {
+ echo $msg . ($newline ? '<br>' :'');
} else {
- echo strip_tags($msg);
+ echo strip_tags($msg) . ($newline ? PHP_EOL : '');
}
-
if (!empty($ADODB_FLUSH) && ob_get_length() !== false) {
flush(); // do not flush if output buffering enabled - useless - thx to Jesse Mullan
}
-
}
/**
@@ -3884,13 +3936,6 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
}
}
- //==============================================================================================
- // DATE AND TIME FUNCTIONS
- //==============================================================================================
- if (!defined('ADODB_DATE_VERSION')) {
- include_once(ADODB_DIR.'/adodb-time.inc.php');
- }
-
/**
* Class ADODB_Iterator
*/
@@ -3975,7 +4020,7 @@ class ADORecordSet implements IteratorAggregate {
var $timeCreated=0; /// datetime in Unix format rs created -- for cached recordsets
var $bind = false; /// used by Fields() to hold array - should be private?
- var $fetchMode; /// default fetch mode
+
/** @var ADOConnection The parent connection */
var $connection = false;
/**
@@ -4024,6 +4069,21 @@ class ADORecordSet implements IteratorAggregate {
protected $fieldObjectsCache;
/**
+ * @var bool True if we have retrieved the fields metadata
+ */
+ protected $fieldObjectsRetrieved = false;
+
+ /**
+ * @var array Cross-reference the objects by name for easy access
+ */
+ protected $fieldObjectsIndex = array();
+
+ /**
+ * @var bool|int Driver-specific fetch mode
+ */
+ var $fetchMode;
+
+ /**
* @var int Defines the Fetch Mode for a recordset
* See the ADODB_FETCH_* constants
*/
@@ -4035,7 +4095,13 @@ class ADORecordSet implements IteratorAggregate {
* @param resource|int $queryID Query ID returned by ADOConnection->_query()
* @param int|bool $mode The ADODB_FETCH_MODE value
*/
- function __construct($queryID,$mode=false) {
+ function __construct($queryID, $mode=false) {
+ if ($mode === false) {
+ global $ADODB_FETCH_MODE;
+ $mode = $ADODB_FETCH_MODE;
+ }
+ $this->adodbFetchMode = $this->fetchMode = $mode;
+
$this->_queryID = $queryID;
}
@@ -5255,15 +5321,13 @@ class ADORecordSet implements IteratorAggregate {
* @param int|bool $mode The ADODB_FETCH_MODE value
*/
function __construct($queryID, $mode=false) {
- global $ADODB_FETCH_MODE,$ADODB_COMPAT_FETCH;
+ parent::__construct(self::DUMMY_QUERY_ID);
// fetch() on EOF does not delete $this->fields
+ global $ADODB_COMPAT_FETCH;
$this->compat = !empty($ADODB_COMPAT_FETCH);
- parent::__construct($queryID); // fake queryID
- $this->fetchMode = $ADODB_FETCH_MODE;
}
-
/**
* Setup the array.
*
diff --git a/composer.json b/composer.json
index cd97e9d7..eea5e002 100644
--- a/composer.json
+++ b/composer.json
@@ -27,11 +27,11 @@
},
"require" : {
- "php" : "^7.0 || ^8.0"
+ "php" : "^7.4 || ^8.0"
},
"require-dev" : {
- "phpunit/phpunit": "^8.5"
+ "phpunit/phpunit": "^9.5"
},
"autoload" : {
diff --git a/docs/changelog.md b/docs/changelog.md
index b41f81c2..69b1e804 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -14,6 +14,50 @@ Older changelogs:
--------------------------------------------------------------------------------
+## [5.23.0] - Unreleased
+
+### Added
+
+- oci8: support session_mode parameter
+ [#801](https://github.com/ADOdb/ADOdb/issues/801)
+- oci8: support setting the client identifier
+ [#805](https://github.com/ADOdb/ADOdb/issues/805)
+- pdo: bind support both '?'-style and named parameters
+ [#880](https://github.com/ADOdb/ADOdb/issues/880)
+
+### Changed
+
+- Refactor debug functions
+ [#863](https://github.com/ADOdb/ADOdb/issues/863)
+- mssql: Simplify serverInfo()
+ [#830](https://github.com/ADOdb/ADOdb/pull/830#issuecomment-1119655907)
+- Code cleanup: PHPDoc, code style, whitespace, etc.
+
+### Removed
+
+- Compatibility with PHP < 7.4
+ [#868](https://github.com/ADOdb/ADOdb/issues/868)
+- Database Replication add-on
+ [#780](https://github.com/ADOdb/ADOdb/issues/780)
+- Date/Time Library
+ [#970](https://github.com/ADOdb/ADOdb/issues/970)
+- mysqli: legacy non-functional $optionFlags property
+ [#814](https://github.com/ADOdb/ADOdb/issues/814)
+- mysqli: remove obsolete, dead code
+ [#877](https://github.com/ADOdb/ADOdb/issues/877)
+- pgsql: Remove legacy workarounds for old PostgreSQL versions
+ [#950](https://github.com/ADOdb/ADOdb/issues/950)
+- session: remove legacy PHP 4 scripts
+ [#962](https://github.com/ADOdb/ADOdb/issues/962)
+
+### Fixed
+
+- oci8: silence deprecation warnings on PHP 8
+ [#883](https://github.com/ADOdb/ADOdb/issues/883)
+- pgsql: affected_rows() always returns false on PHP 8.1
+ [#833](https://github.com/ADOdb/ADOdb/issues/833)
+
+
## [5.22.6] - Unreleased
### Deprecated
@@ -1409,6 +1453,8 @@ Released together with [v4.95](changelog_v4.x.md#495---17-may-2007)
- Adodb5 version,more error checking code now will use exceptions if available.
+[5.23.0]: https://github.com/adodb/adodb/compare/v5.22.5...master
+
[5.22.6]: https://github.com/adodb/adodb/compare/v5.22.5...hotfix/5.22
[5.22.5]: https://github.com/adodb/adodb/compare/v5.22.4...v5.22.5
[5.22.4]: https://github.com/adodb/adodb/compare/v5.22.3...v5.22.4
diff --git a/drivers/adodb-ado.inc.php b/drivers/adodb-ado.inc.php
index df95c690..30edf28b 100644
--- a/drivers/adodb-ado.inc.php
+++ b/drivers/adodb-ado.inc.php
@@ -345,16 +345,6 @@ class ADORecordSet_ado extends ADORecordSet {
var $canSeek = true;
var $hideErrors = true;
- function __construct($id,$mode=false)
- {
- if ($mode === false) {
- global $ADODB_FETCH_MODE;
- $mode = $ADODB_FETCH_MODE;
- }
- $this->fetchMode = $mode;
- parent::__construct($id);
- }
-
// returns the field object
function FetchField($fieldOffset = -1) {
diff --git a/drivers/adodb-ado5.inc.php b/drivers/adodb-ado5.inc.php
index 04b45abf..53bdc6a1 100644
--- a/drivers/adodb-ado5.inc.php
+++ b/drivers/adodb-ado5.inc.php
@@ -382,16 +382,6 @@ class ADORecordSet_ado extends ADORecordSet {
var $canSeek = true;
var $hideErrors = true;
- function __construct($id,$mode=false)
- {
- if ($mode === false) {
- global $ADODB_FETCH_MODE;
- $mode = $ADODB_FETCH_MODE;
- }
- $this->fetchMode = $mode;
- parent::__construct($id);
- }
-
// returns the field object
function FetchField($fieldOffset = -1) {
diff --git a/drivers/adodb-ads.inc.php b/drivers/adodb-ads.inc.php
index 16eec976..e6cd4f3b 100644
--- a/drivers/adodb-ads.inc.php
+++ b/drivers/adodb-ads.inc.php
@@ -287,7 +287,7 @@ class ADODB_ads extends ADOConnection
// Returns tables,Views or both on successful execution. Returns
// tables by default on successful execution.
- function &MetaTables($ttype = false, $showSchema = false, $mask = false)
+ function MetaTables($ttype = false, $showSchema = false, $mask = false)
{
$recordSet1 = $this->Execute("select * from system.tables");
if (!$recordSet1) {
@@ -325,7 +325,7 @@ class ADODB_ads extends ADOConnection
}
- function &MetaPrimaryKeys($table, $owner = false)
+ function MetaPrimaryKeys($table, $owner = false)
{
$recordSet = $this->Execute("select table_primary_key from system.tables where name='$table'");
if (!$recordSet) {
@@ -533,7 +533,7 @@ class ADODB_ads extends ADOConnection
}
// Returns an array of columns names for a given table
- function &MetaColumnNames($table, $numIndexes = false, $useattnum = false)
+ function MetaColumnNames($table, $numIndexes = false, $useattnum = false)
{
$recordSet = $this->Execute("select name from system.columns where parent='$table'");
if (!$recordSet) {
@@ -684,20 +684,13 @@ class ADORecordSet_ads extends ADORecordSet
var $dataProvider = "ads";
var $useFetchArray;
- function __construct($id, $mode = false)
+ function __construct($queryID, $mode = false)
{
- if ($mode === false) {
- global $ADODB_FETCH_MODE;
- $mode = $ADODB_FETCH_MODE;
- }
- $this->fetchMode = $mode;
-
- $this->_queryID = $id;
+ parent::__construct($queryID, $mode);
// the following is required for mysql odbc driver in 4.3.1 -- why?
$this->EOF = false;
$this->_currentRow = -1;
- //parent::__construct($id);
}
@@ -760,7 +753,7 @@ class ADORecordSet_ads extends ADORecordSet
function &GetArrayLimit($nrows, $offset = -1)
{
if ($offset <= 0) {
- $rs =& $this->GetArray($nrows);
+ $rs = $this->GetArray($nrows);
return $rs;
}
$savem = $this->fetchMode;
@@ -769,7 +762,7 @@ class ADORecordSet_ads extends ADORecordSet
$this->fetchMode = $savem;
if ($this->fetchMode & ADODB_FETCH_ASSOC) {
- $this->fields =& $this->GetRowAssoc();
+ $this->fields = $this->GetRowAssoc();
}
$results = array();
@@ -802,7 +795,7 @@ class ADORecordSet_ads extends ADORecordSet
$rez = @ads_fetch_into($this->_queryID, $this->fields);
if ($rez) {
if ($this->fetchMode & ADODB_FETCH_ASSOC) {
- $this->fields =& $this->GetRowAssoc();
+ $this->fields = $this->GetRowAssoc();
}
return true;
}
diff --git a/drivers/adodb-db2.inc.php b/drivers/adodb-db2.inc.php
index e214d2d7..9a3a90c5 100644
--- a/drivers/adodb-db2.inc.php
+++ b/drivers/adodb-db2.inc.php
@@ -1832,17 +1832,6 @@ class ADORecordSet_db2 extends ADORecordSet {
var $dataProvider = "db2";
var $useFetchArray;
- function __construct($id,$mode=false)
- {
- if ($mode === false) {
- global $ADODB_FETCH_MODE;
- $mode = $ADODB_FETCH_MODE;
- }
- $this->fetchMode = $mode;
-
- $this->_queryID = $id;
- }
-
// returns the field object
function fetchField($offset = 0)
diff --git a/drivers/adodb-fbsql.inc.php b/drivers/adodb-fbsql.inc.php
index 64913bc2..ca2df2da 100644
--- a/drivers/adodb-fbsql.inc.php
+++ b/drivers/adodb-fbsql.inc.php
@@ -169,20 +169,22 @@ class ADORecordSet_fbsql extends ADORecordSet{
var $databaseType = "fbsql";
var $canSeek = true;
- function __construct($queryID,$mode=false)
+ function __construct($queryID, $mode=false)
{
- if (!$mode) {
- global $ADODB_FETCH_MODE;
- $mode = $ADODB_FETCH_MODE;
- }
+ parent::__construct($queryID, $mode);
+
switch ($mode) {
- case ADODB_FETCH_NUM: $this->fetchMode = FBSQL_NUM; break;
- case ADODB_FETCH_ASSOC: $this->fetchMode = FBSQL_ASSOC; break;
- case ADODB_FETCH_BOTH:
- default:
- $this->fetchMode = FBSQL_BOTH; break;
+ case ADODB_FETCH_NUM:
+ $this->fetchMode = FBSQL_NUM;
+ break;
+ case ADODB_FETCH_ASSOC:
+ $this->fetchMode = FBSQL_ASSOC;
+ break;
+ case ADODB_FETCH_BOTH:
+ default:
+ $this->fetchMode = FBSQL_BOTH;
+ break;
}
- parent::__construct($queryID);
}
function _initrs()
diff --git a/drivers/adodb-firebird.inc.php b/drivers/adodb-firebird.inc.php
index db3cca5d..848b3c4e 100644
--- a/drivers/adodb-firebird.inc.php
+++ b/drivers/adodb-firebird.inc.php
@@ -1020,28 +1020,10 @@ class ADORecordset_firebird extends ADORecordSet
private $fieldObjects = false;
/**
- * @var bool Flags if we have retrieved the metadata
- */
- private $fieldObjectsRetrieved = false;
-
- /**
- * @var array Cross-reference the objects by name for easy access
- */
- private $fieldObjectsIndex = array();
-
- /**
* @var bool Flag to indicate if the result has a blob
*/
private $fieldObjectsHaveBlob = false;
- function __construct($id, $mode = false)
- {
- global $ADODB_FETCH_MODE;
-
- $this->fetchMode = ($mode === false) ? $ADODB_FETCH_MODE : $mode;
- parent::__construct($id);
- }
-
/**
* Returns: an object containing field information.
diff --git a/drivers/adodb-ibase.inc.php b/drivers/adodb-ibase.inc.php
index 8159c512..8d48f17d 100644
--- a/drivers/adodb-ibase.inc.php
+++ b/drivers/adodb-ibase.inc.php
@@ -741,13 +741,6 @@ class ADORecordSet_ibase extends ADORecordSet
var $bind=false;
var $_cacheType;
- function __construct($id,$mode=false)
- {
- global $ADODB_FETCH_MODE;
-
- $this->fetchMode = ($mode === false) ? $ADODB_FETCH_MODE : $mode;
- parent::__construct($id);
- }
/* Returns: an object containing field information.
Get column information in the Recordset object. fetchField() can be used in order to obtain information about
diff --git a/drivers/adodb-informix72.inc.php b/drivers/adodb-informix72.inc.php
index 6fddde3d..d4083d5e 100644
--- a/drivers/adodb-informix72.inc.php
+++ b/drivers/adodb-informix72.inc.php
@@ -399,17 +399,6 @@ class ADORecordset_informix72 extends ADORecordSet {
var $canSeek = true;
var $_fieldprops = false;
- function __construct($id,$mode=false)
- {
- if ($mode === false) {
- global $ADODB_FETCH_MODE;
- $mode = $ADODB_FETCH_MODE;
- }
- $this->fetchMode = $mode;
- parent::__construct($id);
- }
-
-
/* Returns: an object containing field information.
Get column information in the Recordset object. fetchField() can be used in order to obtain information about
diff --git a/drivers/adodb-ldap.inc.php b/drivers/adodb-ldap.inc.php
index 305f6a7f..e81cb818 100644
--- a/drivers/adodb-ldap.inc.php
+++ b/drivers/adodb-ldap.inc.php
@@ -295,28 +295,23 @@ class ADORecordSet_ldap extends ADORecordSet{
var $canSeek = false;
var $_entryID; /* keeps track of the entry resource identifier */
- function __construct($queryID,$mode=false)
+ function __construct($queryID, $mode=false)
{
- if ($mode === false) {
- global $ADODB_FETCH_MODE;
- $mode = $ADODB_FETCH_MODE;
- }
- switch ($mode)
- {
- case ADODB_FETCH_NUM:
- $this->fetchMode = LDAP_NUM;
- break;
- case ADODB_FETCH_ASSOC:
- $this->fetchMode = LDAP_ASSOC;
- break;
- case ADODB_FETCH_DEFAULT:
- case ADODB_FETCH_BOTH:
- default:
- $this->fetchMode = LDAP_BOTH;
- break;
- }
+ parent::__construct($queryID, $mode);
- parent::__construct($queryID);
+ switch ($mode) {
+ case ADODB_FETCH_NUM:
+ $this->fetchMode = LDAP_NUM;
+ break;
+ case ADODB_FETCH_ASSOC:
+ $this->fetchMode = LDAP_ASSOC;
+ break;
+ case ADODB_FETCH_DEFAULT:
+ case ADODB_FETCH_BOTH:
+ default:
+ $this->fetchMode = LDAP_BOTH;
+ break;
+ }
}
function _initrs()
diff --git a/drivers/adodb-mssql.inc.php b/drivers/adodb-mssql.inc.php
index c0b714ed..c0a2eabd 100644
--- a/drivers/adodb-mssql.inc.php
+++ b/drivers/adodb-mssql.inc.php
@@ -857,18 +857,12 @@ class ADORecordset_mssql extends ADORecordSet {
var $hasFetchAssoc; // see PHPLens Issue No: 6083
// _mths works only in non-localised system
- function __construct($id,$mode=false)
+ function __construct($queryID, $mode=false)
{
+ parent::__construct($queryID, $mode);
+
// freedts check...
$this->hasFetchAssoc = function_exists('mssql_fetch_assoc');
-
- if ($mode === false) {
- global $ADODB_FETCH_MODE;
- $mode = $ADODB_FETCH_MODE;
-
- }
- $this->fetchMode = $mode;
- return parent::__construct($id);
}
diff --git a/drivers/adodb-mssqlnative.inc.php b/drivers/adodb-mssqlnative.inc.php
index f7e1bcc1..a7640625 100644
--- a/drivers/adodb-mssqlnative.inc.php
+++ b/drivers/adodb-mssqlnative.inc.php
@@ -136,26 +136,12 @@ class ADODB_mssqlnative extends ADOConnection {
$this->mssql_version = $version;
}
- function ServerInfo() {
- global $ADODB_FETCH_MODE;
- static $arr = false;
- if (is_array($arr))
- return $arr;
- if ($this->fetchMode === false) {
- $savem = $ADODB_FETCH_MODE;
- $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
- } elseif ($this->fetchMode >=0 && $this->fetchMode <=2) {
- $savem = $this->fetchMode;
- } else
- $savem = $this->SetFetchMode(ADODB_FETCH_NUM);
-
- $arrServerInfo = sqlsrv_server_info($this->_connectionID);
- $ADODB_FETCH_MODE = $savem;
-
- $arr = array();
- $arr['description'] = $arrServerInfo['SQLServerName'].' connected to '.$arrServerInfo['CurrentDatabase'];
- $arr['version'] = $arrServerInfo['SQLServerVersion'];//ADOConnection::_findvers($arr['description']);
- return $arr;
+ function serverInfo() {
+ $info = sqlsrv_server_info($this->_connectionID);
+ return array(
+ 'description' => $info['SQLServerName'] . ' connected to ' . $info['CurrentDatabase'],
+ 'version' => $info['SQLServerVersion'],
+ );
}
function IfNull( $field, $ifNull )
@@ -1053,15 +1039,6 @@ class ADORecordset_mssqlnative extends ADORecordSet {
var $fieldOffset = 0;
// _mths works only in non-localised system
- /**
- * @var bool True if we have retrieved the fields metadata
- */
- private $fieldObjectsRetrieved = false;
-
- /*
- * Cross-reference the objects by name for easy access
- */
- private $fieldObjectsIndex = array();
/*
* Cross references the dateTime objects for faster decoding
@@ -1107,20 +1084,6 @@ class ADORecordset_mssqlnative extends ADORecordSet {
);
-
-
- function __construct($id,$mode=false)
- {
- if ($mode === false) {
- global $ADODB_FETCH_MODE;
- $mode = $ADODB_FETCH_MODE;
-
- }
- $this->fetchMode = $mode;
- parent::__construct($id);
- }
-
-
function _initrs()
{
$this->_numOfRows = -1;//not supported
diff --git a/drivers/adodb-mysqli.inc.php b/drivers/adodb-mysqli.inc.php
index 07b294ca..62c28949 100644
--- a/drivers/adodb-mysqli.inc.php
+++ b/drivers/adodb-mysqli.inc.php
@@ -66,7 +66,6 @@ class ADODB_mysqli extends ADOConnection {
var $socket = ''; //Default to empty string to fix HHVM bug
var $_bindInputArray = false;
var $nameQuote = '`'; /// string to use to quote identifiers and names
- var $optionFlags = array(array(MYSQLI_READ_DEFAULT_GROUP,0));
var $arrayClass = 'ADORecordSet_array_mysqli';
var $multiQuery = false;
var $ssl_key = null;
@@ -176,15 +175,6 @@ class ADODB_mysqli extends ADOConnection {
}
return false;
}
- /*
- I suggest a simple fix which would enable adodb and mysqli driver to
- read connection options from the standard mysql configuration file
- /etc/my.cnf - "Bastien Duclaux" <bduclaux#yahoo.com>
- */
- $this->optionFlags = array();
- foreach($this->optionFlags as $arr) {
- mysqli_options($this->_connectionID,$arr[0],$arr[1]);
- }
// Now merge in the standard connection parameters setting
foreach ($this->connectionParameters as $options) {
@@ -211,7 +201,6 @@ class ADODB_mysqli extends ADOConnection {
$this->clientFlags = MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT;
}
- #if (!empty($this->port)) $argHostname .= ":".$this->port;
/** @noinspection PhpCastIsUnnecessaryInspection */
$ok = @mysqli_real_connect($this->_connectionID,
$argHostname,
@@ -747,8 +736,6 @@ class ADODB_mysqli extends ADOConnection {
$fraction = $dayFraction * 24 * 3600;
return $date . ' + INTERVAL ' . $fraction.' SECOND';
-
-// return "from_unixtime(unix_timestamp($date)+$fraction)";
}
/**
@@ -1015,7 +1002,6 @@ class ADODB_mysqli extends ADOConnection {
*/
function SelectDB($dbName)
{
-// $this->_connectionID = $this->mysqli_resolve_link($this->_connectionID);
$this->database = $dbName;
if ($this->_connectionID) {
@@ -1074,21 +1060,11 @@ class ADODB_mysqli extends ADOConnection {
*/
function Prepare($sql)
{
- /*
- * Flag the insert_id method to use the correct retrieval method
- */
+ // Flag the insert_id method to use the correct retrieval method
$this->usePreparedStatement = true;
- /*
- * Prepared statements are not yet handled correctly
- */
+ // Prepared statements are not yet handled correctly
return $sql;
- $stmt = $this->_connectionID->prepare($sql);
- if (!$stmt) {
- echo $this->errorMsg();
- return $sql;
- }
- return array($sql,$stmt);
}
public function execute($sql, $inputarr = false)
@@ -1189,12 +1165,6 @@ class ADODB_mysqli extends ADOConnection {
function _query($sql, $inputarr = false)
{
global $ADODB_COUNTRECS;
- // Move to the next recordset, or return false if there is none. In a stored proc
- // call, mysqli_next_result returns true for the last "recordset", but mysqli_store_result
- // returns false. I think this is because the last "recordset" is actually just the
- // return value of the stored proc (ie the number of rows affected).
- // Commented out for reasons of performance. You should retrieve every recordset yourself.
- // if (!mysqli_next_result($this->connection->_connectionID)) return false;
// When SQL is empty, mysqli_query() throws exception on PHP 8 (#945)
if (!$sql) {
@@ -1204,80 +1174,39 @@ class ADODB_mysqli extends ADOConnection {
return false;
}
- if (is_array($sql)) {
-
- // Prepare() not supported because mysqli_stmt_execute does not return a recordset, but
- // returns as bound variables.
-
- $stmt = $sql[1];
- $a = '';
- foreach($inputarr as $v) {
- if (is_string($v)) $a .= 's';
- else if (is_integer($v)) $a .= 'i';
- else $a .= 'd';
- }
-
- /*
- * set prepared statement flags
- */
- if ($this->usePreparedStatement)
- $this->useLastInsertStatement = true;
-
- $fnarr = array_merge( array($stmt,$a) , $inputarr);
- call_user_func_array('mysqli_stmt_bind_param',$fnarr);
- return mysqli_stmt_execute($stmt);
- }
- else if (is_string($sql) && is_array($inputarr))
- {
-
- /*
- * This is support for true prepared queries
- * with bound parameters
- *
- * set prepared statement flags
- */
+ if (is_string($sql) && is_array($inputarr)) {
+ // This is support for true prepared queries with bound parameters
+ // set prepared statement flags
$this->usePreparedStatement = true;
$this->usingBoundVariables = true;
$bulkBindArray = array();
- if (is_array($inputarr[0]))
- {
+ if (is_array($inputarr[0])) {
$bulkBindArray = $inputarr;
$inputArrayCount = count($inputarr[0]) - 1;
- }
- else
- {
+ } else {
$bulkBindArray[] = $inputarr;
$inputArrayCount = count($inputarr) - 1;
}
-
- /*
- * Prepare the statement with the placeholders,
- * prepare will fail if the statement is invalid
- * so we trap and error if necessary. Note that we
- * are calling MySQL prepare here, not ADOdb
- */
+ // Prepare the statement with the placeholders
+ // prepare will fail if the statement is invalid, so we trap and error if necessary.
+ // Note that we are calling MySQL prepare here, not ADOdb
$stmt = $this->_connectionID->prepare($sql);
- if ($stmt === false)
- {
+ if ($stmt === false) {
$this->outp_throw(
"SQL Statement failed on preparation: " . htmlspecialchars($sql) . "'",
'Execute'
);
return false;
}
- /*
- * Make sure the number of parameters provided in the input
- * array matches what the query expects. We must discount
- * the first parameter which contains the data types in
- * our inbound parameters
- */
- $nparams = $stmt->param_count;
- if ($nparams != $inputArrayCount)
- {
+ // Make sure the number of parameters provided in the input array
+ // matches what the query expects. We must discount the first
+ // parameter which contains the data types in our inbound parameters
+ $nparams = $stmt->param_count;
+ if ($nparams != $inputArrayCount) {
$this->outp_throw(
"Input array has " . $inputArrayCount .
" params, does not match query: '" . htmlspecialchars($sql) . "'",
@@ -1286,37 +1215,28 @@ class ADODB_mysqli extends ADOConnection {
return false;
}
- foreach ($bulkBindArray as $inputarr)
- {
- /*
- * Must pass references into call_user_func_array
- */
+ foreach ($bulkBindArray as $inputarr) {
+ // Must pass references into call_user_func_array
$paramsByReference = array();
- foreach($inputarr as $key => $value) {
+ foreach ($inputarr as $key => $value) {
/** @noinspection PhpArrayAccessCanBeReplacedWithForeachValueInspection */
$paramsByReference[$key] = &$inputarr[$key];
}
- /*
- * Bind the params
- */
+ // Bind the params
call_user_func_array(array($stmt, 'bind_param'), $paramsByReference);
- /*
- * Execute
- */
-
+ // Execute
$ret = mysqli_stmt_execute($stmt);
// Store error code and message
$this->_errorCode = $stmt->errno;
$this->_errorMsg = $stmt->error;
- /*
- * Did we throw an error?
- */
- if ($ret == false)
+ // Did we throw an error?
+ if (!$ret) {
return false;
+ }
}
// Tells affected_rows to be compliant
@@ -1328,14 +1248,9 @@ class ADODB_mysqli extends ADOConnection {
// Turn the statement into a result set and return it
return $stmt->get_result();
- }
- else
- {
- /*
- * reset prepared statement flags, in case we set them
- * previously and didn't use them
- */
- $this->usePreparedStatement = false;
+ } else {
+ // Reset prepared statement flags, in case we set them previously and didn't use them
+ $this->usePreparedStatement = false;
$this->useLastInsertStatement = false;
// Reset error code and message
@@ -1343,19 +1258,12 @@ class ADODB_mysqli extends ADOConnection {
$this->_errorMsg = '';
}
- /*
- if (!$mysql_res = mysqli_query($this->_connectionID, $sql, ($ADODB_COUNTRECS) ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT)) {
- if ($this->debug) ADOConnection::outp("Query: " . $sql . " failed. " . $this->errorMsg());
- return false;
- }
-
- return $mysql_res;
- */
-
if ($this->multiQuery) {
- $rs = mysqli_multi_query($this->_connectionID, $sql.';');
+ $rs = mysqli_multi_query($this->_connectionID, $sql . ';');
if ($rs) {
- $rs = ($ADODB_COUNTRECS) ? @mysqli_store_result( $this->_connectionID ) : @mysqli_use_result( $this->_connectionID );
+ $rs = ($ADODB_COUNTRECS)
+ ? @mysqli_store_result($this->_connectionID)
+ : @mysqli_use_result($this->_connectionID);
return $rs ?: true; // mysqli_more_results( $this->_connectionID )
}
} else {
@@ -1366,11 +1274,10 @@ class ADODB_mysqli extends ADOConnection {
}
}
- if($this->debug)
+ if ($this->debug) {
ADOConnection::outp("Query: " . $sql . " failed. " . $this->errorMsg());
-
+ }
return false;
-
}
/**
@@ -1492,10 +1399,7 @@ class ADORecordSet_mysqli extends ADORecordSet{
function __construct($queryID, $mode = false)
{
- if ($mode === false) {
- global $ADODB_FETCH_MODE;
- $mode = $ADODB_FETCH_MODE;
- }
+ parent::__construct($queryID, $mode);
switch ($mode) {
case ADODB_FETCH_NUM:
@@ -1510,8 +1414,6 @@ class ADORecordSet_mysqli extends ADORecordSet{
$this->fetchMode = MYSQLI_BOTH;
break;
}
- $this->adodbFetchMode = $mode;
- parent::__construct($queryID);
}
function _initrs()
diff --git a/drivers/adodb-oci8.inc.php b/drivers/adodb-oci8.inc.php
index f361d683..2c2c891a 100644
--- a/drivers/adodb-oci8.inc.php
+++ b/drivers/adodb-oci8.inc.php
@@ -105,8 +105,6 @@ END;
var $datetime = false; // MetaType('DATE') returns 'D' (datetime==false) or 'T' (datetime == true)
var $_refLOBs = array();
- // var $ansiOuter = true; // if oracle9
-
/*
* Legacy compatibility for sequence names for emulated auto-increments
*/
@@ -193,21 +191,33 @@ END;
}
/**
+ * Connect to database.
+ *
* Multiple modes of connection are supported:
*
- * a. Local Database
- * $conn->Connect(false,'scott','tiger');
+ * 1. Local Database
+ * $conn->connect(false, 'scott', 'tiger');
*
- * b. From tnsnames.ora
- * $conn->Connect($tnsname,'scott','tiger');
- * $conn->Connect(false,'scott','tiger',$tnsname);
+ * 2. From tnsnames.ora
+ * $conn->connect($tnsname, 'scott', 'tiger');
+ * OR
+ * $conn->connect(false, 'scott', 'tiger', $tnsname);
*
- * c. Server + service name
- * $conn->Connect($serveraddress,'scott,'tiger',$service_name);
+ * 3. Server + service name
+ * $conn->connect($serveraddress, 'scott, 'tiger', $service_name);
*
- * d. Server + SID
+ * 4. Server + SID
* $conn->connectSID = true;
* $conn->Connect($serveraddress,'scott,'tiger',$SID);
+ * OR
+ * $conn->Connect($serveraddress,'scott,'tiger',"SID=$SID");
+ *
+ * By default, the Session Mode will be set to OCI_DEFAULT, but it is
+ * possible to use one of other modes referenced in the
+ * {@link https://www.php.net/manual/en/function.oci-connect oci8_connect()}
+ * function's documentation, like this:
+ * $conn->setConnectionParameter('session_mode', OCI_SYSDBA);
+ * $conn->connect(...);
*
* @param string|false $argHostname DB server hostname or TNS name
* @param string $argUsername
@@ -245,45 +255,60 @@ END;
$argDatabasename = substr($argDatabasename,4);
$this->connectSID = true;
}
-
- if ($this->connectSID) {
- $argDatabasename="(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=".$argHostname
- .")(PORT=$argHostport))(CONNECT_DATA=(SID=$argDatabasename)))";
- } else
- $argDatabasename="(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=".$argHostname
- .")(PORT=$argHostport))(CONNECT_DATA=(SERVICE_NAME=$argDatabasename)))";
+ $sidOrService = $this->connectSID ? 'SID' : 'SERVICE_NAME';
+ $argDatabasename = "(DESCRIPTION="
+ . "(ADDRESS=(PROTOCOL=TCP)(HOST=$argHostname)(PORT=$argHostport))"
+ . "(CONNECT_DATA=($sidOrService=$argDatabasename)))";
}
}
- //if ($argHostname) print "<p>Connect: 1st argument should be left blank for $this->databaseType</p>";
- if ($mode==1) {
- $this->_connectionID = ($this->charSet)
- ? oci_pconnect($argUsername,$argPassword, $argDatabasename,$this->charSet)
- : oci_pconnect($argUsername,$argPassword, $argDatabasename);
- if ($this->_connectionID && $this->autoRollback) {
- oci_rollback($this->_connectionID);
+ // Determine the connect function to use based on connection mode
+ switch ($mode) {
+ case 1: $ociConnectFunction = 'oci_pconnect'; break;
+ case 2: $ociConnectFunction = 'oci_new_connect'; break;
+ default: $ociConnectFunction = 'oci_connect';
+ }
+
+ // Process the connection parameters
+ $sessionMode = OCI_DEFAULT;
+ $clientIdentifier = '';
+ foreach ($this->connectionParameters as $options) {
+ foreach($options as $parameter => $value) {
+ switch ($parameter) {
+ case 'session_mode':
+ $sessionMode = $value;
+ break;
+ case 'client_identifier':
+ $clientIdentifier = $value;
+ break;
+ }
}
- } else if ($mode==2) {
- $this->_connectionID = ($this->charSet)
- ? oci_new_connect($argUsername,$argPassword, $argDatabasename,$this->charSet)
- : oci_new_connect($argUsername,$argPassword, $argDatabasename);
- } else {
- $this->_connectionID = ($this->charSet)
- ? oci_connect($argUsername,$argPassword, $argDatabasename,$this->charSet)
- : oci_connect($argUsername,$argPassword, $argDatabasename);
}
+
+ $this->_connectionID = $ociConnectFunction(
+ $argUsername,
+ $argPassword,
+ $argDatabasename,
+ $this->charSet ?: '',
+ $sessionMode
+ );
if (!$this->_connectionID) {
return false;
}
+ // Set client identifier, but see documentation for limitations
+ if ($clientIdentifier) {
+ oci_set_client_identifier($this->_connectionID, $clientIdentifier);
+ }
+
+ if ($mode == 1 && $this->autoRollback ) {
+ oci_rollback($this->_connectionID);
+ }
+
if ($this->_initdate) {
$this->Execute("ALTER SESSION SET NLS_DATE_FORMAT='".$this->NLS_DATE_FORMAT."'");
}
- // looks like:
- // Oracle8i Enterprise Edition Release 8.1.7.0.0 - Production With the Partitioning option JServer Release 8.1.7.0.0 - Production
- // $vers = oci_server_version($this->_connectionID);
- // if (strpos($vers,'8i') !== false) $this->ansiOuter = true;
return true;
}
@@ -547,7 +572,7 @@ END;
$ok = true;
}
- return $ok ? true : false;
+ return (bool)$ok;
}
function CommitTrans($ok=true)
@@ -1252,9 +1277,9 @@ END;
* $db->Parameter($stmt,$group,'group');
* $db->Execute($stmt);
*
- * @param $stmt Statement returned by {@see Prepare()} or {@see PrepareSP()}.
- * @param $var PHP variable to bind to
- * @param $name Name of stored procedure variable name to bind to.
+ * @param array $stmt Statement returned by {@see Prepare()} or {@see PrepareSP()}.
+ * @param mixed $var PHP variable to bind to
+ * @param string $name Name of stored procedure variable name to bind to.
* @param bool $isOutput Indicates direction of parameter 0/false=IN 1=OUT 2= IN/OUT. This is ignored in oci8.
* @param int $maxLen Holds an maximum length of the variable.
* @param mixed $type The data type of $var. Legal values depend on driver.
@@ -1398,15 +1423,13 @@ END;
$ok = oci_execute($cursor);
return $cursor;
}
- return $stmt;
} else {
if (is_resource($stmt)) {
oci_free_statement($stmt);
return true;
}
- return $stmt;
}
- break;
+ return $stmt;
default :
return true;
@@ -1571,8 +1594,6 @@ SELECT /*+ RULE */ distinct b.column_name
* It remains for backwards compatibility.
*
* @return string Quoted string to be sent back to database
- *
- * @noinspection PhpUnusedParameterInspection
*/
function qStr($s, $magic_quotes=false)
{
@@ -1600,12 +1621,10 @@ class ADORecordset_oci8 extends ADORecordSet {
/** @var resource Cursor reference */
var $_refcursor;
- function __construct($queryID,$mode=false)
+ function __construct($queryID, $mode=false)
{
- if ($mode === false) {
- global $ADODB_FETCH_MODE;
- $mode = $ADODB_FETCH_MODE;
- }
+ parent::__construct($queryID, $mode);
+
switch ($mode) {
case ADODB_FETCH_ASSOC:
$this->fetchMode = OCI_ASSOC;
@@ -1620,8 +1639,6 @@ class ADORecordset_oci8 extends ADORecordSet {
break;
}
$this->fetchMode += OCI_RETURN_NULLS + OCI_RETURN_LOBS;
- $this->adodbFetchMode = $mode;
- $this->_queryID = $queryID;
}
/**
@@ -1821,7 +1838,7 @@ class ADORecordset_oci8 extends ADORecordSet {
* @param mixed $t
* @param int $len [optional] Length of blobsize
* @param bool $fieldobj [optional][discarded]
- * @return str The metatype of the field
+ * @return string The metatype of the field
*/
function MetaType($t, $len=-1, $fieldobj=false)
{
diff --git a/drivers/adodb-odbc.inc.php b/drivers/adodb-odbc.inc.php
index 56db8b0e..59909646 100644
--- a/drivers/adodb-odbc.inc.php
+++ b/drivers/adodb-odbc.inc.php
@@ -613,20 +613,13 @@ class ADORecordSet_odbc extends ADORecordSet {
var $dataProvider = "odbc";
var $useFetchArray;
- function __construct($id,$mode=false)
+ function __construct($queryID, $mode=false)
{
- if ($mode === false) {
- global $ADODB_FETCH_MODE;
- $mode = $ADODB_FETCH_MODE;
- }
- $this->fetchMode = $mode;
-
- $this->_queryID = $id;
+ parent::__construct($queryID, $mode);
// the following is required for mysql odbc driver in 4.3.1 -- why?
$this->EOF = false;
$this->_currentRow = -1;
- //parent::__construct($id);
}
diff --git a/drivers/adodb-odbtp.inc.php b/drivers/adodb-odbtp.inc.php
index e3f81481..b4e12601 100644
--- a/drivers/adodb-odbtp.inc.php
+++ b/drivers/adodb-odbtp.inc.php
@@ -684,15 +684,6 @@ class ADORecordSet_odbtp extends ADORecordSet {
var $databaseType = 'odbtp';
var $canSeek = true;
- function __construct($queryID,$mode=false)
- {
- if ($mode === false) {
- global $ADODB_FETCH_MODE;
- $mode = $ADODB_FETCH_MODE;
- }
- $this->fetchMode = $mode;
- parent::__construct($queryID);
- }
function _initrs()
{
diff --git a/drivers/adodb-oracle.inc.php b/drivers/adodb-oracle.inc.php
index dc0462fe..5cd4bedf 100644
--- a/drivers/adodb-oracle.inc.php
+++ b/drivers/adodb-oracle.inc.php
@@ -223,16 +223,9 @@ class ADORecordset_oracle extends ADORecordSet {
var $databaseType = "oracle";
var $bind = false;
- function __construct($queryID,$mode=false)
+ function __construct($queryID, $mode=false)
{
-
- if ($mode === false) {
- global $ADODB_FETCH_MODE;
- $mode = $ADODB_FETCH_MODE;
- }
- $this->fetchMode = $mode;
-
- $this->_queryID = $queryID;
+ parent::__construct($queryID, $mode);
$this->_inited = true;
$this->fields = array();
@@ -249,9 +242,7 @@ class ADORecordset_oracle extends ADORecordSet {
return $this->_queryID;
}
-
-
- /* Returns: an object containing field information.
+ /* Returns: an object containing field information.
Get column information in the Recordset object. fetchField() can be used in order to obtain information about
fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by
fetchField() is retrieved. */
diff --git a/drivers/adodb-pdo.inc.php b/drivers/adodb-pdo.inc.php
index d3ce12d0..bdc466dd 100644
--- a/drivers/adodb-pdo.inc.php
+++ b/drivers/adodb-pdo.inc.php
@@ -66,6 +66,10 @@ function adodb_pdo_type($t)
class ADODB_pdo extends ADOConnection {
+ const BIND_USE_QUESTION_MARKS = 0;
+ const BIND_USE_NAMED_PARAMETERS = 1;
+ const BIND_USE_BOTH = 2;
+
var $databaseType = "pdo";
var $dataProvider = "pdo";
var $fmtDate = "'Y-m-d'";
@@ -100,6 +104,15 @@ class ADODB_pdo extends ADOConnection {
*/
public $pdoParameters = array();
+ /*
+ * Set which style is used to bind parameters
+ *
+ * BIND_USE_QUESTION_MARKS = Use only question marks
+ * BIND_USE_NAMED_PARAMETERS = Use only named parameters
+ * BIND_USE_BOTH = Use both question marks and named parameters (Default)
+ */
+ public $bindParameterStyle = self::BIND_USE_BOTH;
+
function _UpdatePDO()
{
$d = $this->_driver;
@@ -592,11 +605,7 @@ class ADODB_pdo extends ADOConnection {
$this->_driver->debug = $this->debug;
}
if ($inputarr) {
-
- /*
- * inputarr must be numeric
- */
- $inputarr = array_values($inputarr);
+ $inputarr = $this->conformToBindParameterStyle($stmt->queryString, $inputarr);
$ok = $stmt->execute($inputarr);
}
else {
@@ -666,6 +675,58 @@ class ADODB_pdo extends ADOConnection {
return "'" . str_replace("'", $this->replaceQuote, $s) . "'";
}
+ /**
+ * Make bind parameters conform to settings.
+ *
+ * @param string $sql
+ * @param array $inputarr
+ * @return array
+ */
+ private function conformToBindParameterStyle($sql, $inputarr)
+ {
+ switch ($this->bindParameterStyle)
+ {
+ case self::BIND_USE_QUESTION_MARKS:
+ default:
+ $inputarr = array_values($inputarr);
+ break;
+
+ case self::BIND_USE_NAMED_PARAMETERS:
+ break;
+
+ case self::BIND_USE_BOTH:
+ // inputarr must be numeric if SQL contains a question mark
+ if ($this->containsQuestionMarkPlaceholder($sql)) {
+ $inputarr = array_values($inputarr);
+
+ if ($this->debug) {
+ ADOconnection::outp('improve the performance of this query by setting the bindParameterStyle to BIND_USE_QUESTION_MARKS');
+ }
+ }
+ break;
+ }
+
+ return $inputarr;
+ }
+
+ /**
+ * Checks for the inclusion of a question mark placeholder.
+ *
+ * @param string $sql SQL string
+ * @return boolean Returns true if a question mark placeholder is included
+ */
+ private function containsQuestionMarkPlaceholder($sql)
+ {
+ $pattern = '/(.\?(:?.|$))/';
+ if (preg_match_all($pattern, $sql, $matches, PREG_SET_ORDER)) {
+ foreach ($matches as $match) {
+ if ($match[1] !== '`?`' && strpos($match[1], '??') === false) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
}
/**
@@ -792,27 +853,25 @@ class ADORecordSet_pdo extends ADORecordSet {
/** @var PDOStatement */
var $_queryID;
- function __construct($id,$mode=false)
+ function __construct($queryID, $mode=false)
{
- if ($mode === false) {
- global $ADODB_FETCH_MODE;
- $mode = $ADODB_FETCH_MODE;
- }
- $this->adodbFetchMode = $mode;
- switch($mode) {
- case ADODB_FETCH_NUM: $mode = PDO::FETCH_NUM; break;
- case ADODB_FETCH_ASSOC: $mode = PDO::FETCH_ASSOC; break;
+ parent::__construct($queryID, $mode);
- case ADODB_FETCH_BOTH:
- default: $mode = PDO::FETCH_BOTH; break;
+ switch($mode) {
+ case ADODB_FETCH_NUM:
+ $mode = PDO::FETCH_NUM;
+ break;
+ case ADODB_FETCH_ASSOC:
+ $mode = PDO::FETCH_ASSOC;
+ break;
+ case ADODB_FETCH_BOTH:
+ default:
+ $mode = PDO::FETCH_BOTH;
+ break;
}
$this->fetchMode = $mode;
-
- $this->_queryID = $id;
- parent::__construct($id);
}
-
function Init()
{
if ($this->_inited) {
diff --git a/drivers/adodb-postgres64.inc.php b/drivers/adodb-postgres64.inc.php
index 9bf9e713..9f02c5cd 100644
--- a/drivers/adodb-postgres64.inc.php
+++ b/drivers/adodb-postgres64.inc.php
@@ -26,6 +26,10 @@ class ADODB_postgres64 extends ADOConnection{
var $databaseType = 'postgres64';
var $dataProvider = 'postgres';
var $hasInsertID = true;
+ /** @var PgSql\Connection|resource|false Identifier for the native database connection */
+ var $_connectionID = false;
+ /** @var PgSql\Connection|resource|false */
+ var $_queryID;
/** @var PgSql\Connection|resource|false */
var $_resultid = false;
var $concat_operator='||';
@@ -85,7 +89,7 @@ class ADODB_postgres64 extends ADOConnection{
var $_pnum = 0;
var $version;
- var $_nestedSQL = false;
+ var $_nestedSQL = true;
// The last (fmtTimeStamp is not entirely correct:
// PostgreSQL also has support for time zones,
@@ -117,9 +121,7 @@ class ADODB_postgres64 extends ADOConnection{
// If PHP has been compiled with PostgreSQL 7.3 or lower, then
// server version is not set so we use pg_parameter_status()
// which includes logic to obtain values server_version
- 'version' => isset($version['server'])
- ? $version['server']
- : pg_parameter_status($this->_connectionID, 'server_version'),
+ 'version' => $version['server'] ?? pg_parameter_status($this->_connectionID, 'server_version'),
'client' => $version['client'],
'description' => null,
);
@@ -136,7 +138,15 @@ class ADODB_postgres64 extends ADOConnection{
return " coalesce($field, $ifNull) ";
}
- // get the last id - never tested
+ /**
+ * Get the last id - never tested.
+ *
+ * @param string $tablename
+ * @param string $fieldname
+ * @return false|mixed
+ *
+ * @noinspection PhpUnused
+ */
function pg_insert_id($tablename,$fieldname)
{
$result=pg_query($this->_connectionID, 'SELECT last_value FROM '. $tablename .'_'. $fieldname .'_seq');
@@ -158,7 +168,9 @@ class ADODB_postgres64 extends ADOConnection{
*/
protected function _insertID($table = '', $column = '')
{
- if ($this->_resultid === false) return false;
+ if ($this->_resultid === false) {
+ return false;
+ }
$oid = pg_last_oid($this->_resultid);
// to really return the id, we need the table and column-name, else we can only return the oid != id
return empty($table) || empty($column) ? $oid : $this->GetOne("SELECT $column FROM $table WHERE oid=".(int)$oid);
@@ -166,7 +178,9 @@ class ADODB_postgres64 extends ADOConnection{
function _affectedrows()
{
- if ($this->_resultid === false) return false;
+ if ($this->_resultid === false) {
+ return false;
+ }
return pg_affected_rows($this->_resultid);
}
@@ -181,13 +195,14 @@ class ADODB_postgres64 extends ADOConnection{
return pg_query($this->_connectionID, 'begin '.$this->_transmode);
}
- function RowLock($tables,$where,$col='1 as adodbignore')
+ function RowLock($table, $where, $col='1 as adodbignore')
{
- if (!$this->transCnt) $this->BeginTrans();
- return $this->GetOne("select $col from $tables where $where for update");
+ if (!$this->transCnt) {
+ $this->BeginTrans();
+ }
+ return $this->GetOne("select $col from $table where $where for update");
}
- // returns true/false.
function CommitTrans($ok=true)
{
if ($this->transOff) return true;
@@ -197,7 +212,6 @@ class ADODB_postgres64 extends ADOConnection{
return pg_query($this->_connectionID, 'commit');
}
- // returns true/false
function RollbackTrans()
{
if ($this->transOff) return true;
@@ -264,8 +278,6 @@ class ADODB_postgres64 extends ADOConnection{
}
}
-
- // Format date column in sql string given an input format that understands Y M D
function SQLDate($fmt, $col=false)
{
if (!$col) $col = $this->sysTimeStamp;
@@ -345,15 +357,24 @@ class ADODB_postgres64 extends ADOConnection{
- /*
- * Load a Large Object from a file
- * - the procedure stores the object id in the table and imports the object using
- * postgres proprietary blob handling routines
- *
- * contributed by Mattia Rossi mattia@technologist.com
- * modified for safe mode by juraj chlebec
- */
- function UpdateBlobFile($table,$column,$path,$where,$blobtype='BLOB')
+ /**
+ * Update a BLOB from a file.
+ *
+ * The procedure stores the object id in the table and imports the object using
+ * postgres proprietary blob handling routines.
+ *
+ * Usage example:
+ * $conn->updateBlobFile('table', 'blob_col', '/path/to/file', 'id=1');
+ *
+ * @param string $table
+ * @param string $column
+ * @param string $path Filename containing blob data
+ * @param mixed $where {@see updateBlob()}
+ * @param string $blobtype supports 'BLOB' and 'CLOB'
+ *
+ * @return bool success
+ */
+ function updateBlobFile($table,$column,$path,$where,$blobtype='BLOB')
{
pg_query($this->_connectionID, 'begin');
@@ -369,24 +390,25 @@ class ADODB_postgres64 extends ADOConnection{
// $oid = pg_lo_import ($path);
pg_query($this->_connectionID, 'commit');
$rs = ADOConnection::UpdateBlob($table,$column,$oid,$where,$blobtype);
- $rez = !empty($rs);
- return $rez;
+ return !empty($rs);
}
- /*
- * Deletes/Unlinks a Blob from the database, otherwise it
- * will be left behind
- *
- * Returns TRUE on success or FALSE on failure.
- *
- * contributed by Todd Rogers todd#windfox.net
- */
- function BlobDelete( $blob )
+ /**
+ * Deletes/Unlinks a Blob from the database, otherwise it will be left behind.
+ *
+ * contributed by Todd Rogers todd#windfox.net
+ *
+ * @param mixed $blob
+ * @return bool True on success, false on failure.
+ *
+ * @noinspection PhpUnused
+ */
+ function BlobDelete($blob)
{
pg_query($this->_connectionID, 'begin');
$result = @pg_lo_unlink($this->_connectionID, $blob);
pg_query($this->_connectionID, 'commit');
- return( $result );
+ return $result;
}
/*
@@ -398,19 +420,21 @@ class ADODB_postgres64 extends ADOConnection{
return is_numeric($oid);
}
- /*
- * If an OID is detected, then we use pg_lo_* to open the oid file and read the
- * real blob from the db using the oid supplied as a parameter. If you are storing
- * blobs using bytea, we autodetect and process it so this function is not needed.
- *
- * contributed by Mattia Rossi mattia@technologist.com
- *
- * see http://www.postgresql.org/idocs/index.php?largeobjects.html
- *
- * Since adodb 4.54, this returns the blob, instead of sending it to stdout. Also
- * added maxsize parameter, which defaults to $db->maxblobsize if not defined.
- */
- function BlobDecode($blob,$maxsize=false,$hastrans=true)
+ /**
+ * If an OID is detected, then we use pg_lo_* to open the oid file and read the
+ * real blob from the db using the oid supplied as a parameter. If you are storing
+ * blobs using bytea, we autodetect and process it so this function is not needed.
+ *
+ * Contributed by Mattia Rossi mattia@technologist.com
+ *
+ * @link https://www.postgresql.org/docs/current/largeobjects.html
+ *
+ * @param mixed $blob
+ * @param int|false $maxsize Defaults to $db->maxblobsize if false
+ * @param bool $hastrans
+ * @return string|false The blob
+ */
+ function BlobDecode($blob, $maxsize=false, $hastrans=true)
{
if (!$this->GuessOID($blob)) return $blob;
@@ -430,7 +454,7 @@ class ADODB_postgres64 extends ADOConnection{
/**
* Encode binary value prior to DB storage.
*
- * See https://www.postgresql.org/docs/current/static/datatype-binary.html
+ * @link https://www.postgresql.org/docs/current/static/datatype-binary.html
*
* NOTE: SQL string literals (input strings) must be preceded with two
* backslashes due to the fact that they must pass through two parsers in
@@ -491,7 +515,6 @@ class ADODB_postgres64 extends ADOConnection{
global $ADODB_FETCH_MODE;
$schema = false;
- $false = false;
$this->_findschema($table,$schema);
if ($normalize) $table = strtolower($table);
@@ -505,7 +528,7 @@ class ADODB_postgres64 extends ADOConnection{
$ADODB_FETCH_MODE = $save;
if ($rs === false) {
- return $false;
+ return false;
}
if (!empty($this->metaKeySQL)) {
// If we want the primary keys, we have to issue a separate query
@@ -523,6 +546,8 @@ class ADODB_postgres64 extends ADOConnection{
$rskey->Close();
unset($rskey);
+ } else {
+ $keys = [];
}
$rsdefa = array();
@@ -575,28 +600,29 @@ class ADODB_postgres64 extends ADOConnection{
//Freek
$fld->not_null = $rs->fields[4] == 't';
-
// Freek
if (is_array($keys)) {
foreach($keys as $key) {
- if ($fld->name == $key['column_name'] AND $key['primary_key'] == 't')
+ if ($fld->name == $key['column_name'] && $key['primary_key'] == 't') {
$fld->primary_key = true;
- if ($fld->name == $key['column_name'] AND $key['unique_key'] == 't')
+ }
+ if ($fld->name == $key['column_name'] && $key['unique_key'] == 't') {
$fld->unique = true; // What name is more compatible?
+ }
}
}
- if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) $retarr[] = $fld;
- else $retarr[($normalize) ? strtoupper($fld->name) : $fld->name] = $fld;
+ if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) {
+ $retarr[] = $fld;
+ }
+ else {
+ $retarr[($normalize) ? strtoupper($fld->name) : $fld->name] = $fld;
+ }
$rs->MoveNext();
}
$rs->Close();
- if (empty($retarr))
- return $false;
- else
- return $retarr;
-
+ return $retarr ?: false;
}
function param($name, $type='C')
@@ -640,7 +666,7 @@ class ADODB_postgres64 extends ADOConnection{
WHERE (c2.relname=\'%s\' or c2.relname=lower(\'%s\'))';
}
- if ($primary == FALSE) {
+ if (!$primary) {
$sql .= ' AND i.indisprimary=false;';
}
@@ -657,8 +683,7 @@ class ADODB_postgres64 extends ADOConnection{
$ADODB_FETCH_MODE = $save;
if (!is_object($rs)) {
- $false = false;
- return $false;
+ return false;
}
// Get column names indexed by attnum so we can lookup the index key
@@ -749,22 +774,6 @@ class ADODB_postgres64 extends ADOConnection{
if ($this->_connectionID === false) return false;
$this->Execute("set datestyle='ISO'");
- $info = $this->ServerInfo(false);
-
- if (version_compare($info['version'], '7.1', '>=')) {
- $this->_nestedSQL = true;
- }
-
- # PostgreSQL 9.0 changed the default output for bytea from 'escape' to 'hex'
- # PHP does not handle 'hex' properly ('x74657374' is returned as 't657374')
- # https://bugs.php.net/bug.php?id=59831 states this is in fact not a bug,
- # so we manually set bytea_output
- if (version_compare($info['version'], '9.0', '>=')
- && version_compare($info['client'], '9.2', '<')
- ) {
- $this->Execute('set bytea_output=escape');
- }
-
return true;
}
@@ -911,17 +920,17 @@ class ADODB_postgres64 extends ADOConnection{
}
- /*
- * Maximum size of C field
- */
+ /**
+ * @return int Maximum size of C field
+ */
function CharMax()
{
return 1000000000; // should be 1 Gb?
}
- /*
- * Maximum size of X field
- */
+ /**
+ * @return int Maximum size of X field
+ */
function TextMax()
{
return 1000000000; // should be 1 Gb?
@@ -941,23 +950,21 @@ class ADORecordSet_postgres64 extends ADORecordSet{
function __construct($queryID, $mode=false)
{
- if ($mode === false) {
- global $ADODB_FETCH_MODE;
- $mode = $ADODB_FETCH_MODE;
- }
- switch ($mode)
- {
- case ADODB_FETCH_NUM: $this->fetchMode = PGSQL_NUM; break;
- case ADODB_FETCH_ASSOC:$this->fetchMode = PGSQL_ASSOC; break;
+ parent::__construct($queryID, $mode);
- case ADODB_FETCH_DEFAULT:
- case ADODB_FETCH_BOTH:
- default: $this->fetchMode = PGSQL_BOTH; break;
+ switch ($mode) {
+ case ADODB_FETCH_NUM:
+ $this->fetchMode = PGSQL_NUM;
+ break;
+ case ADODB_FETCH_ASSOC:
+ $this->fetchMode = PGSQL_ASSOC;
+ break;
+ case ADODB_FETCH_DEFAULT:
+ case ADODB_FETCH_BOTH:
+ default:
+ $this->fetchMode = PGSQL_BOTH;
+ break;
}
- $this->adodbFetchMode = $mode;
-
- // Parent's constructor
- parent::__construct($queryID);
}
function GetRowAssoc($upper = ADODB_ASSOC_CASE)
@@ -965,8 +972,7 @@ class ADORecordSet_postgres64 extends ADORecordSet{
if ($this->fetchMode == PGSQL_ASSOC && $upper == ADODB_ASSOC_CASE_LOWER) {
return $this->fields;
}
- $row = ADORecordSet::GetRowAssoc($upper);
- return $row;
+ return ADORecordSet::GetRowAssoc($upper);
}
function _initRS()
@@ -978,7 +984,6 @@ class ADORecordSet_postgres64 extends ADORecordSet{
// cache types for blob decode check
// apparently pg_field_type actually performs an sql query on the database to get the type.
- if (empty($this->connection->noBlobs))
for ($i=0, $max = $this->_numOfFields; $i < $max; $i++) {
if (pg_field_type($qid,$i) == 'bytea') {
$this->_blobArr[$i] = pg_field_name($qid,$i);
@@ -1045,7 +1050,7 @@ class ADORecordSet_postgres64 extends ADORecordSet{
}
}
if ($this->fetchMode == PGSQL_ASSOC || $this->fetchMode == PGSQL_BOTH) {
- foreach($this->_blobArr as $k => $v) {
+ foreach($this->_blobArr as $v) {
$this->fields[$v] = ADORecordSet_postgres64::_decode($this->fields[$v]);
}
}
@@ -1086,7 +1091,7 @@ class ADORecordSet_postgres64 extends ADORecordSet{
return pg_free_result($this->_queryID);
}
- function MetaType($t,$len=-1,$fieldobj=false)
+ function MetaType($t,$len=-1, $fieldObj=false)
{
if (is_object($t)) {
$fieldobj = $t;
@@ -1096,71 +1101,81 @@ class ADORecordSet_postgres64 extends ADORecordSet{
$t = strtoupper($t);
- if (array_key_exists($t,$this->connection->customActualTypes))
- return $this->connection->customActualTypes[$t];
+ if (array_key_exists($t, $this->connection->customActualTypes)) {
+ return $this->connection->customActualTypes[$t];
+ }
switch ($t) {
- case 'MONEY': // stupid, postgres expects money to be a string
- case 'INTERVAL':
- case 'CHAR':
- case 'CHARACTER':
- case 'VARCHAR':
- case 'NAME':
- case 'BPCHAR':
- case '_VARCHAR':
- case 'CIDR':
- case 'INET':
- case 'MACADDR':
- case 'UUID':
- if ($len <= $this->blobSize) return 'C';
-
- case 'TEXT':
- return 'X';
+ case 'MONEY': // stupid, postgres expects money to be a string
+ case 'INTERVAL':
+ case 'CHAR':
+ case 'CHARACTER':
+ case 'VARCHAR':
+ case 'NAME':
+ case 'BPCHAR':
+ case '_VARCHAR':
+ case 'CIDR':
+ case 'INET':
+ case 'MACADDR':
+ /** @noinspection PhpMissingBreakStatementInspection */
+ case 'UUID':
+ if ($len <= $this->blobSize) {
+ return 'C';
+ }
+ // Fall-through
- case 'IMAGE': // user defined type
- case 'BLOB': // user defined type
- case 'BIT': // This is a bit string, not a single bit, so don't return 'L'
- case 'VARBIT':
- case 'BYTEA':
- return 'B';
+ case 'TEXT':
+ return 'X';
- case 'BOOL':
- case 'BOOLEAN':
- return 'L';
+ case 'IMAGE': // user defined type
+ case 'BLOB': // user defined type
+ case 'BIT': // This is a bit string, not a single bit, so don't return 'L'
+ case 'VARBIT':
+ case 'BYTEA':
+ return 'B';
- case 'DATE':
- return 'D';
+ case 'BOOL':
+ case 'BOOLEAN':
+ return 'L';
+ case 'DATE':
+ return 'D';
- case 'TIMESTAMP WITHOUT TIME ZONE':
- case 'TIME':
- case 'DATETIME':
- case 'TIMESTAMP':
- case 'TIMESTAMPTZ':
- return 'T';
+ case 'TIMESTAMP WITHOUT TIME ZONE':
+ case 'TIME':
+ case 'DATETIME':
+ case 'TIMESTAMP':
+ case 'TIMESTAMPTZ':
+ return 'T';
- case 'SMALLINT':
- case 'BIGINT':
- case 'INTEGER':
- case 'INT8':
- case 'INT4':
- case 'INT2':
- if (isset($fieldobj) &&
- empty($fieldobj->primary_key) && (!$this->connection->uniqueIisR || empty($fieldobj->unique))) return 'I';
+ case 'SMALLINT':
+ case 'BIGINT':
+ case 'INTEGER':
+ case 'INT8':
+ case 'INT4':
+ /** @noinspection PhpMissingBreakStatementInspection */
+ case 'INT2':
+ if (isset($fieldobj)
+ && empty($fieldobj->primary_key)
+ && (!$this->connection->uniqueIisR || empty($fieldobj->unique))
+ ) {
+ return 'I';
+ }
+ // Fall-through
- case 'OID':
- case 'SERIAL':
- return 'R';
+ case 'OID':
+ case 'SERIAL':
+ return 'R';
- case 'NUMERIC':
- case 'DECIMAL':
- case 'FLOAT4':
- case 'FLOAT8':
- return 'N';
+ case 'NUMERIC':
+ case 'DECIMAL':
+ case 'FLOAT4':
+ case 'FLOAT8':
+ return 'N';
- default:
- return ADODB_DEFAULT_METATYPE;
- }
+ default:
+ return ADODB_DEFAULT_METATYPE;
+ }
}
}
diff --git a/drivers/adodb-sqlite.inc.php b/drivers/adodb-sqlite.inc.php
index d41829c0..d4cf19be 100644
--- a/drivers/adodb-sqlite.inc.php
+++ b/drivers/adodb-sqlite.inc.php
@@ -425,14 +425,11 @@ class ADORecordset_sqlite extends ADORecordSet {
var $databaseType = "sqlite";
var $bind = false;
- function __construct($queryID,$mode=false)
+ function __construct($queryID, $mode=false)
{
+ parent::__construct($queryID, $mode);
- if ($mode === false) {
- global $ADODB_FETCH_MODE;
- $mode = $ADODB_FETCH_MODE;
- }
- switch($mode) {
+ switch ($mode) {
case ADODB_FETCH_NUM:
$this->fetchMode = SQLITE_NUM;
break;
@@ -443,9 +440,6 @@ class ADORecordset_sqlite extends ADORecordSet {
$this->fetchMode = SQLITE_BOTH;
break;
}
- $this->adodbFetchMode = $mode;
-
- $this->_queryID = $queryID;
$this->_inited = true;
$this->fields = array();
@@ -462,7 +456,6 @@ class ADORecordset_sqlite extends ADORecordSet {
return $this->_queryID;
}
-
function FetchField($fieldOffset = -1)
{
$fld = new ADOFieldObject;
diff --git a/drivers/adodb-sqlite3.inc.php b/drivers/adodb-sqlite3.inc.php
index 7623a3c8..822a649d 100644
--- a/drivers/adodb-sqlite3.inc.php
+++ b/drivers/adodb-sqlite3.inc.php
@@ -719,12 +719,9 @@ class ADORecordset_sqlite3 extends ADORecordSet {
var $_queryID;
/** @noinspection PhpMissingParentConstructorInspection */
- function __construct($queryID,$mode=false)
+ function __construct($queryID, $mode=false)
{
- if ($mode === false) {
- global $ADODB_FETCH_MODE;
- $mode = $ADODB_FETCH_MODE;
- }
+ parent::__construct($queryID, $mode);
switch($mode) {
case ADODB_FETCH_NUM:
$this->fetchMode = SQLITE3_NUM;
@@ -736,9 +733,6 @@ class ADORecordset_sqlite3 extends ADORecordSet {
$this->fetchMode = SQLITE3_BOTH;
break;
}
- $this->adodbFetchMode = $mode;
-
- $this->_queryID = $queryID;
$this->_inited = true;
$this->fields = array();
@@ -755,7 +749,6 @@ class ADORecordset_sqlite3 extends ADORecordSet {
return $this->_queryID;
}
-
function FetchField($fieldOffset = -1)
{
$fld = new ADOFieldObject;
diff --git a/drivers/adodb-sybase.inc.php b/drivers/adodb-sybase.inc.php
index 79fb82e8..f6c8f58c 100644
--- a/drivers/adodb-sybase.inc.php
+++ b/drivers/adodb-sybase.inc.php
@@ -315,15 +315,15 @@ class ADORecordset_sybase extends ADORecordSet {
// _mths works only in non-localised system
var $_mths = array('JAN'=>1,'FEB'=>2,'MAR'=>3,'APR'=>4,'MAY'=>5,'JUN'=>6,'JUL'=>7,'AUG'=>8,'SEP'=>9,'OCT'=>10,'NOV'=>11,'DEC'=>12);
- function __construct($id,$mode=false)
+ function __construct($queryID, $mode=false)
{
- if ($mode === false) {
- global $ADODB_FETCH_MODE;
- $mode = $ADODB_FETCH_MODE;
+ parent::__construct($queryID, $mode);
+
+ if (!$mode) {
+ $this->fetchMode = ADODB_FETCH_ASSOC;
+ } else {
+ $this->fetchMode = $mode;
}
- if (!$mode) $this->fetchMode = ADODB_FETCH_ASSOC;
- else $this->fetchMode = $mode;
- parent::__construct($id);
}
/* Returns: an object containing field information.
diff --git a/replicate/adodb-replicate.inc.php b/replicate/adodb-replicate.inc.php
deleted file mode 100644
index ee5c539f..00000000
--- a/replicate/adodb-replicate.inc.php
+++ /dev/null
@@ -1,1179 +0,0 @@
-<?php
-/**
- * Replication engine
- *
- * @deprecated 5.22.0 Will be removed in 5.23.0 {@link https://github.com/ADOdb/ADOdb/issues/780)
- *
- * - Copy table structures and data from different databases
- * (e.g. mysql to oracle)
- * - Generate CREATE TABLE, CREATE INDEX, INSERT for installation scripts
- *
- * Note: this code assumes that comments such as / * * / are allowed,
- * which works with: mssql, postgresql, oracle, mssql
- *
- * Table Structure copying includes
- * - fields and limited subset of types
- * - optional default values
- * - indexes
- * - but not constraints
- *
- * Two modes of data copy:
- * 1. ReplicateData - Copy from src to dest, with update of status of copy
- * back to src, with configurable src SELECT where clause
- * 2. MergeData - Copy from src to dest based on last mod date field and/or
- * copied flag field
- *
- * Default settings are
- * - do not execute, generate sql ($rep->execute = false)
- * - do not delete records in dest table first ($rep->deleteFirst = false).
- * if $rep->deleteFirst is true and primary keys are defined,
- * then no deletion will occur unless *INSERTONLY* is defined in pkey array
- * - only commit once at the end of every ReplicateData ($rep->commitReplicate = true)
- * - do not autocommit every x records processed ($rep->commitRecs = -1)
- * - even if error occurs on one record, continue copying remaining records ($rep->neverAbort = true)
- * - debugging turned off ($rep->debug = false)
- *
- * This file is part of ADOdb, a Database Abstraction Layer library for PHP.
- *
- * @package ADOdb
- * @link https://adodb.org Project's web site and documentation
- * @link https://github.com/ADOdb/ADOdb Source code and issue tracker
- *
- * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause
- * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option,
- * any later version. This means you can use it in proprietary products.
- * See the LICENSE.md file distributed with this source code for details.
- * @license BSD-3-Clause
- * @license LGPL-2.1-or-later
- *
- * @copyright 2000-2013 John Lim
- * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community
- */
-
-define('ADODB_REPLICATE',1.2);
-
-include_once(ADODB_DIR.'/adodb-datadict.inc.php');
-
-class ADODB_Replicate {
- var $connSrc;
- var $connDest;
-
- var $connSrc2 = false;
- var $connDest2 = false;
- var $ddSrc;
- var $ddDest;
-
- var $execute = false;
- var $debug = false;
- var $deleteFirst = false;
- var $commitReplicate = true; // commit at end of replicatedata
- var $commitRecs = -1; // only commit at end of ReplicateData()
-
- var $selFilter = false;
- var $fieldFilter = false;
- var $indexFilter = false;
- var $updateFilter = false;
- var $insertFilter = false;
- var $updateSrcFn = false;
-
- var $limitRecs = false;
-
- var $neverAbort = true;
- var $copyTableDefaults = false; // turn off because functions defined as defaults will not work when copied
- var $errHandler = false; // name of error handler function, if used.
- var $htmlSpecialChars = true; // if execute false, then output with htmlspecialchars enabled.
- // Will autoconfigure itself. No need to modify
-
- var $trgSuffix = '_mrgTr';
- var $idxSuffix = '_mrgidx';
- var $trLogic = '1 = 1';
- var $datesAreTimeStamps = false;
-
- var $oracleSequence = false;
- var $readUncommitted = false; // read without obeying shared locks for fast select (mssql)
-
- var $compat = false;
- // connSrc2 and connDest2 are only required if the db driver
- // does not allow updates back to src db in first connection (the select connection),
- // so we need 2nd connection
- function __construct($connSrc, $connDest, $connSrc2=false, $connDest2=false)
- {
-
- if (strpos($connSrc->databaseType,'odbtp') !== false) {
- $connSrc->_bindInputArray = false; # bug in odbtp, binding fails
- }
-
- if (strpos($connDest->databaseType,'odbtp') !== false) {
- $connDest->_bindInputArray = false; # bug in odbtp, binding fails
- }
-
- $this->connSrc = $connSrc;
- $this->connDest = $connDest;
-
- $this->connSrc2 = ($connSrc2) ? $connSrc2 : $connSrc;
- $this->connDest2 = ($connDest2) ? $connDest2 : $connDest;
-
- $this->ddSrc = newDataDictionary($connSrc);
- $this->ddDest = newDataDictionary($connDest);
- $this->htmlSpecialChars = isset($_SERVER['HTTP_HOST']);
- }
-
- function ExecSQL($sql)
- {
- if (!is_array($sql)) $sql[] = $sql;
-
- $ret = true;
- foreach($sql as $s)
- if (!$this->execute) echo "<pre>",$s.";\n</pre>";
- else {
- $ok = $this->connDest->Execute($s);
- if (!$ok)
- if ($this->neverAbort) $ret = false;
- else return false;
- }
-
- return $ret;
- }
-
- /*
- We assume replication between $table and $desttable only works if the field names and types match for both tables.
-
- Also $table and desttable can have different names.
- */
-
- function CopyTableStruct($table,$desttable='')
- {
- $sql = $this->CopyTableStructSQL($table,$desttable);
- if (empty($sql)) return false;
- return $this->ExecSQL($sql);
- }
-
- function RunFieldFilter(&$fld, $mode = '')
- {
- if ($this->fieldFilter) {
- $fn = $this->fieldFilter;
- return $fn($fld, $mode);
- } else
- return $fld;
- }
-
- function RunUpdateFilter($table, $fld, $val)
- {
- if ($this->updateFilter) {
- $fn = $this->updateFilter;
- return $fn($table, $fld, $val);
- } else
- return $val;
- }
-
- function RunInsertFilter($table, $fld, &$val)
- {
- if ($this->insertFilter) {
- $fn = $this->insertFilter;
- return $fn($table, $fld, $val);
- } else
- return $fld;
- }
-
- /*
- $mode = INS or UPD
-
- The lastUpdateFld holds the field that counts the number of updates or the date of last mod. This ensures that
- if the rec was modified after replicatedata retrieves the data but before we update back the src record,
- we don't set the copiedflag='Y' yet.
- */
- function RunUpdateSrcFn($srcdb, $table, $fldoffsets, $row, $where, $mode, $dest_insertid=null, $lastUpdateFld='')
- {
- if (!$this->updateSrcFn) return;
-
- $bindarr = array();
- foreach($fldoffsets as $k) {
- $bindarr[$k] = $row[$k];
- }
- $last = sizeof($row);
-
- if ($lastUpdateFld && $row[$last-1]) {
- $ds = $row[$last-1];
- if (strpos($ds,':') !== false) $s = $srcdb->DBTimeStamp($ds);
- else $s = $srcdb->qstr($ds);
- $where = "WHERE $lastUpdateFld = $s and $where";
- } else
- $where = "WHERE $where";
- $fn = $this->updateSrcFn;
- if (is_array($fn)) {
- if (sizeof($fn) == 1) $set = reset($fn);
- else $set = @$fn[$mode];
- if ($set) {
-
- if (strlen($dest_insertid) == 0) $dest_insertid = 'null';
- $set = str_replace('$INSERT_ID',$dest_insertid,$set);
-
- $sql = "UPDATE $table SET $set $where ";
- $ok = $srcdb->Execute($sql,$bindarr);
- if (!$ok) {
- echo $srcdb->ErrorMsg(),"<br>\n";
- die();
- }
- }
- } else $fn($srcdb, $table, $row, $where, $bindarr, $mode, $dest_insertid);
-
- }
-
- function CopyTableStructSQL($table, $desttable='',$dropdest =false)
- {
- if (!$desttable) {
- $desttable = $table;
- $prefixidx = '';
- } else
- $prefixidx = $desttable;
-
- $conn = $this->connSrc;
- $types = $conn->MetaColumns($table);
- if (!$types) {
- echo "$table does not exist in source db<br>\n";
- return array();
- }
- if (!$dropdest && $this->connDest->MetaColumns($desttable)) {
- echo "$desttable already exists in dest db<br>\n";
- return array();
- }
- if ($this->debug) var_dump($types);
- $sa = array();
- $idxcols = array();
-
- foreach($types as $name => $t) {
- $s = '';
- $mt = $this->ddSrc->MetaType($t->type);
- $len = $t->max_length;
- $fldname = $this->RunFieldFilter($t->name,'TABLE');
- if (!$fldname) continue;
-
- $s .= $fldname . ' '.$mt;
- if (isset($t->scale)) $precision = '.'.$t->scale;
- else $precision = '';
- if ($mt == 'C' or $mt == 'X') $s .= "($len)";
- else if ($mt == 'N' && $precision) $s .= "($len$precision)";
-
- if ($mt == 'R') $idxcols[] = $fldname;
-
- if ($this->copyTableDefaults) {
- if (isset($t->default_value)) {
- $v = $t->default_value;
- if ($mt == 'C' or $mt == 'X') $v = $this->connDest->qstr($v); // might not work as this could be function
- $s .= ' DEFAULT '.$v;
- }
- }
-
- $sa[] = $s;
- }
-
- $s = implode(",\n",$sa);
-
- // dump adodb intermediate data dictionary format
- if ($this->debug) echo '<pre>'.$s.'</pre>';
-
- $sqla = $this->ddDest->CreateTableSQL($desttable,$s);
-
- /*
- if ($idxcols) {
- $idxoptions = array('UNIQUE'=>1);
- $sqla2 = $this->ddDest->_IndexSQL($table.'_'.$fldname.'_SERIAL', $desttable, $idxcols,$idxoptions);
- $sqla = array_merge($sqla,$sqla2);
- }*/
-
- $idxs = $conn->MetaIndexes($table);
- if ($idxs)
- foreach($idxs as $name => $iarr) {
- $idxoptions = array();
- $fldnames = array();
-
- if(!empty($iarr['unique'])) {
- $idxoptions['UNIQUE'] = 1;
- }
-
- foreach($iarr['columns'] as $fld) {
- $fldnames[] = $this->RunFieldFilter($fld,'TABLE');
- }
-
- $idxname = $prefixidx.str_replace($table,$desttable,$name);
-
- if (!empty($this->indexFilter)) {
- $fn = $this->indexFilter;
- $idxname = $fn($desttable,$idxname,$fldnames,$idxoptions);
- }
- $sqla2 = $this->ddDest->_IndexSQL($idxname, $desttable, $fldnames,$idxoptions);
- $sqla = array_merge($sqla,$sqla2);
- }
-
- return $sqla;
- }
-
- function _clearcache()
- {
-
- }
-
- function _concat($v)
- {
- return $this->connDest->concat("' ","chr(".ord($v).")","'");
- }
-
- function fixupbinary($v)
- {
- return str_replace(
- array("\r","\n"),
- array($this->_concat("\r"),$this->_concat("\n")),
- $v );
- }
-
- function SwapDBs()
- {
- $o = $this->connSrc;
- $this->connSrc = $this->connDest;
- $this->connDest = $o;
-
-
- $o = $this->connSrc2;
- $this->connSrc2 = $this->connDest2;
- $this->connDest2 = $o;
-
- $o = $this->ddSrc;
- $this->ddSrc = $this->ddDest;
- $this->ddDest = $o;
- }
-
- /*
- // if no uniqflds defined, then all desttable recs will be deleted before insert
- // $where clause must include the WHERE word if used
- // if $this->commitRecs is set to a +ve value, then it will autocommit every $this->commitRecs records
- // -- this should never be done with 7x24 db's
-
- Returns an array:
- $arr[0] = true if no error, false if error
- $arr[1] = number of recs processed
- $arr[2] = number of successful inserts
- $arr[3] = number of successful updates
-
- ReplicateData() params:
-
- $table = src table name
- $desttable = dest table name, leave blank to use src table name
- $uniqflds = array() = an array. If set, then inserts and updates will occur. eg. array('PK1', 'PK2');
- To prevent updates to desttable (allow only to src table), add '*INSERTONLY*' or '*ONLYINSERT*' to array.
-
- Sometimes you are replicating a src table with an autoinc primary key.
- You sometimes create recs in the dest table. The dest table has to retrieve the
- src table's autoinc key (stored in a 2nd field) so you can match the two tables.
-
- To define this, and the uniqflds contains nested arrays. Copying from autoinc table to other table:
- array(array($destpkey), array($destfld_holds_src_autoinc_pkey))
-
- Copying from normal table to autoinc table:
- array(array($destpkey), array(), array($srcfld_holds_dest_autoinc_pkey))
-
- $where = where clause for SELECT from $table $where. Include the WHERE reserved word in beginning.
- You can put ORDER BY at the end also
- $ignoreflds = array(), list of fields to ignore. e.g. array('FLD1',FLD2');
- $dstCopyDateFld = date field on $desttable to update with current date
- $extraflds allows you to add additional flds to insert/update. Format
- array(fldname => $fldval)
- $fldval itself can be an array or a string. If an array, then
- $extraflds = array($fldname => array($insertval, $updateval))
-
- Thus we have the following behaviours:
-
- a. Delete all data in $desttable then insert from src $table
-
- $rep->execute = true;
- $rep->ReplicateData($table, $desttable)
-
- b. Update $desttable if record exists (based on $uniqflds), otherwise insert.
-
- $rep->execute = true;
- $rep->ReplicateData($table, $desttable, $array($pkey1, $pkey2))
-
- c. Select from src $table all data modified since a date. Then update $desttable
- if record exists (based on $uniqflds), otherwise insert
-
- $rep->execute = true;
- $rep->ReplicateData($table, $desttable, array($pkey1, $pkey2), "WHERE update_datetime_fld > $LAST_REFRESH")
-
- d. Insert all records into $desttable modified after a certain id (or time) in src $table:
-
- $rep->execute = true;
- $rep->ReplicateData($table, $desttable, false, "WHERE id_fld > $LAST_ID_SAVED", true);
-
-
- For (a) to (d), returns array: array($boolean_ok_fail, $no_recs_selected_from_src_db, $no_recs_inserted, $no_recs_updated);
-
- e. Generate sample SQL:
-
- $rep->execute = false;
- $rep->ReplicateData(....);
-
- This returns $array, which contains:
-
- $array['SEL'] = select stmt from src db
- $array['UPD'] = update stmt to dest db
- $array['INS'] = insert stmt to dest db
-
-
- Error-handling
- ==============
- Default is never abort if error occurs. You can set $rep->neverAbort = false; to force replication to abort if an error occurs.
-
-
- Value Filtering
- ========
- Sometimes you might need to modify/massage the data before the code works. Assume that the value used for True and False is
- 'T' and 'F' in src DB, but is 'Y' and 'N' in dest DB for field[2] in select stmt. You can do this by
-
- $rep->filterSelect = 'filter';
- $rep->ReplicateData(...);
-
- function filter($table,& $fields, $deleteFirst)
- {
- if ($table == 'SOMETABLE') {
- if ($fields[2] == 'T') $fields[2] = 'Y';
- else if ($fields[2] == 'F') $fields[2] = 'N';
- }
- }
-
- We pass in $deleteFirst as that determines the order of the fields (which are numeric-based):
- TRUE: the order of fields matches the src table order
- FALSE: the order of fields is all non-primary key fields first, followed by primary key fields. This is because it needs
- to match the UPDATE statement, which is UPDATE $table SET f2 = ?, f3 = ? ... WHERE f1 = ?
-
- Name Filtering
- =========
- Sometimes field names that are legal in one RDBMS can be illegal in another.
- We allow you to handle this using a field filter.
- Also if you don't want to replicate certain fields, just return false.
-
- $rep->fieldFilter = 'ffilter';
-
- function ffilter(&$fld,$mode)
- {
- $uf = strtoupper($fld);
- switch($uf) {
- case 'GROUP':
- if ($mode == 'SELECT') $fld = '"Group"';
- return 'GroupFld';
-
- case 'PRIVATEFLD': # do not replicate
- return false;
- }
- return $fld;
- }
-
-
- UPDATE FILTERING
- ================
- Sometimes, when we want to update
- UPDATE table SET fld = val WHERE ....
-
- we want to modify val. To do so, define
-
- $rep->updateFilter = 'ufilter';
-
- function ufilter($table, $fld, $val)
- {
- return "nvl($fld, $val)";
- }
-
-
- Sending back audit info back to src Table
- =========================================
-
- Use $rep->updateSrcFn. This can be an array of strings, or the name of a php function to call.
-
- If an array of strings is defined, then it will perform an update statement...
-
- UPDATE srctable SET $string WHERE ....
-
- With $string set to the array you define. If a new record was inserted into desttable, then the
- 'INS' string is used ($INSERT_ID will be replaced with the real INSERT_ID, if any),
- and if an update then use the 'UPD' string.
-
- array(
- 'INS' => 'insertid = $INSERT_ID, copieddate=getdate(), copied = 1',
- 'UPD' => 'copieddate=getdate(), copied = 1'
- )
-
- If a single string array is defined, then it will be used for both insert and update.
- array('copieddate=getdate(), copied = 1')
-
- Note that the where clause is automatically defined by the system.
-
- If $rep->updateSrcFn is a PHP function name, then it will be called with the following params:
-
- $fn($srcConnection, $tableName, $row, $where, $bindarr, $mode, $dest_insertid)
-
- $srcConnection - source db connection
- $tableName - source tablename
- $row - array holding records updated into dest
- $where - where clause to be used (uses bind vars)
- $bindarr - array holding bind variables for where clause
- $mode - INS or UPD
- $dest_insertid - when mode=INS, then the insert_id is stored here.
-
-
- oracle mssql
- ---> insert
- mssqlid <--- insert_id
- ----> update with mssqlid
- <---- update with mssqlid
-
-
- TODO: add src pkey and dest pkey for updates. Also sql stmt needs to be tuned, so dest pkey, src pkey
- */
-
-
- function ReplicateData($table, $desttable = '', $uniqflds = array(), $where = '',$ignore_flds = array(),
- $dstCopyDateFld='', $extraflds = array(), $lastUpdateFld = '')
- {
- if (is_array($where)) {
- $wheresrc = $where[0];
- $wheredest = $where[1];
- } else {
- $wheresrc = $wheredest = $where;
- }
- $dstCopyDateName = $dstCopyDateFld;
- $dstCopyDateFld = strtoupper($dstCopyDateFld);
-
- $this->_clearcache();
- if (is_string($uniqflds) && strlen($uniqflds)) $uniqflds = array($uniqflds);
- if (!$desttable) $desttable = $table;
-
- $uniq = array();
- if ($uniqflds) {
- if (is_array(reset($uniqflds))) {
- /*
- primary key of src and dest tables differ. This means when we perform the select stmts
- we retrieve both keys. Then any insert statement will have to ignore one array element.
- Any update statement will need to use a different where clause
- */
- $destuniqflds = $uniqflds[0];
- if (sizeof($uniqflds)>1 && $uniqflds[1]) // srckey field name in dest table
- $srcuniqflds = $uniqflds[1];
- else
- $srcuniqflds = array();
-
- if (sizeof($uniqflds)>2)
- $srcPKDest = reset($uniqflds[2]);
-
- } else {
- $destuniqflds = $uniqflds;
- $srcuniqflds = array();
- }
- $onlyInsert = false;
- foreach($destuniqflds as $k => $u) {
- if ($u == '*INSERTONLY*' || $u == '*ONLYINSERT*') {
- $onlyInsert = true;
- continue;
- }
- $uniq[strtoupper($u)] = $k;
- }
- $deleteFirst = $this->deleteFirst;
- } else {
- $deleteFirst = true;
- }
-
- if ($deleteFirst) $onlyInsert = true;
-
- if ($ignore_flds) {
- foreach($ignore_flds as $u) {
- $ignoreflds[strtoupper($u)] = 1;
- }
- } else
- $ignoreflds = array();
-
- $src = $this->connSrc;
- $dest = $this->connDest;
- $src2 = $this->connSrc2;
-
- $dest->noNullStrings = false;
- $src->noNullStrings = false;
- $src2->noNullStrings = false;
-
- if ($src === $dest) $this->execute = false;
-
- $types = $src->MetaColumns($table);
- if (!$types) {
- echo "Source $table does not exist<br>\n";
- return array();
- }
- $dtypes = $dest->MetaColumns($desttable);
- if (!$dtypes) {
- echo "Destination $desttable does not exist<br>\n";
- return array();
- }
- $sa = array();
- $selflds = array();
- $wheref = array();
- $wheres = array();
- $srcwheref = array();
- $fldoffsets = array();
- $k = 0;
- foreach($types as $name => $t) {
- $name2 = strtoupper($this->RunFieldFilter($name,'SELECT'));
- // handle quotes
- if ($name2 && $name2[0] == '"' && $name2[strlen($name2)-1] == '"') $name22 = substr($name2,1,strlen($name2)-2);
- elseif ($name2 && $name2[0] == '`' && $name2[strlen($name2)-1] == '`') $name22 = substr($name2,1,strlen($name2)-2);
- else $name22 = $name2;
-
- //else $name22 = $name2; // this causes problem for quotes strip above
-
- if (!isset($dtypes[($name22)]) || !$name2) {
- if ($this->debug) echo " Skipping $name ==> $name2 as not in destination $desttable<br>";
- continue;
- }
-
- if ($name2 == $dstCopyDateFld) {
- $dstCopyDateName = $t->name;
- continue;
- }
-
- $fld = $t->name;
- $fldval = $t->name;
- $mt = $src->MetaType($t->type);
- if ($this->datesAreTimeStamps && $mt == 'D') $mt = 'T';
- if ($mt == 'D') $fldval = $dest->DBDate($fldval);
- elseif ($mt == 'T') $fldval = $dest->DBTimeStamp($fldval);
- $ufld = strtoupper($fld);
-
- if (isset($ignoreflds[($name2)]) && !isset($uniq[$ufld])) {
- continue;
- }
-
- if ($this->debug) echo " field=$fld type=$mt fldval=$fldval<br>";
-
- if (!isset($uniq[$ufld])) {
-
- $selfld = $fld;
- $fld = $this->RunFieldFilter($selfld,'SELECT');
- $selflds[] = $selfld;
-
- $p = $dest->Param($k);
-
- if ($mt == 'D') $p = $dest->DBDate($p, true);
- else if ($mt == 'T') $p = $dest->DBTimeStamp($p, true);
-
- # UPDATES
- $sets[] = "$fld = ".$this->RunUpdateFilter($desttable, $fld, $p);
-
- # INSERTS
- $insflds[] = $this->RunInsertFilter($desttable,$fld, $p); $params[] = $p;
- $k++;
- } else {
- $fld = $this->RunFieldFilter($fld);
- $wheref[] = $fld;
- if (!empty($srcuniqflds)) $srcwheref[] = $srcuniqflds[$uniq[$ufld]];
- if ($mt == 'C') { # normally we don't include the primary key in the insert if it is numeric, but ok if varchar
- $insertpkey = true;
- }
- }
- }
-
-
- foreach($extraflds as $fld => $evals) {
- if (!is_array($evals)) $evals = array($evals, $evals);
- $insflds[] = $this->RunInsertFilter($desttable,$fld, $p); $params[] = $evals[0];
- $sets[] = "$fld = ".$evals[1];
- }
-
- if ($dstCopyDateFld) {
- $sets[] = "$dstCopyDateName = ".$dest->sysTimeStamp;
- $insflds[] = $this->RunInsertFilter($desttable,$dstCopyDateName, $p); $params[] = $dest->sysTimeStamp;
- }
-
-
- if (!empty($srcPKDest)) {
- $selflds[] = $srcPKDest;
- $fldoffsets = array($k+1);
- }
-
- foreach($wheref as $uu => $fld) {
-
- $p = $dest->Param($k);
- $sp = $src->Param($k);
- if (!empty($srcuniqflds)) {
- if ($uu > 1) die("Only one primary key for srcuniqflds allowed currently");
- $destsrckey = reset($srcuniqflds);
- $wheres[] = reset($srcuniqflds).' = '.$p;
-
- $insflds[] = $this->RunInsertFilter($desttable,$destsrckey, $p);
- $params[] = $p;
- } else {
- $wheres[] = $fld.' = '.$p;
- if (!isset($ignoreflds[strtoupper($fld)]) || !empty($insertpkey)) {
- $insflds[] = $this->RunInsertFilter($desttable,$fld, $p);
- $params[] = $p;
- }
- }
-
- $selflds[] = $fld;
- $srcwheres[] = $fld.' = '.$sp;
- $fldoffsets[] = $k;
-
- $k++;
- }
-
- if (!empty($srcPKDest)) {
- $fldoffsets = array($k);
- $srcwheres = array($fld.'='.$src->Param($k));
- $k++;
- }
-
- if ($lastUpdateFld) {
- $selflds[] = $lastUpdateFld;
- } else
- $selflds[] = 'null as Z55_DUMMY_LA5TUPD';
-
- $insfldss = implode(', ', $insflds);
- $fldss = implode(', ', $selflds);
- $setss = implode(', ', $sets);
- $paramss = implode(', ', $params);
- $wheress = implode(' AND ', $wheres);
- if (isset($srcwheres))
- $srcwheress = implode(' AND ',$srcwheres);
-
-
- $seltable = $table;
- if ($this->readUncommitted && strpos($src->databaseType,'mssql')) $seltable .= ' with (NOLOCK)';
-
- $sa['SEL'] = "SELECT $fldss FROM $seltable $wheresrc";
- $sa['INS'] = "INSERT INTO $desttable ($insfldss) VALUES ($paramss) /**INS**/";
- $sa['UPD'] = "UPDATE $desttable SET $setss WHERE $wheress /**UPD**/";
-
-
-
- $DB1 = "/* <font color=green> Source DB - sample sql in case you need to adapt code\n\n";
- $DB2 = "/* <font color=green> Dest DB - sample sql in case you need to adapt code\n\n";
-
- if (!$this->execute) echo '/*<style>
-pre {
-white-space: pre-wrap; /* css-3 */
-white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */
-white-space: -pre-wrap; /* Opera 4-6 */
-white-space: -o-pre-wrap; /* Opera 7 */
-word-wrap: break-word; /* Internet Explorer 5.5+ */
-}
-</style><pre>*/
-';
- if ($deleteFirst && $this->deleteFirst) {
- $where = preg_replace('/[ \n\r\t]+order[ \n\r\t]+by.*$/i', '', $where);
- $sql = "DELETE FROM $desttable $wheredest\n";
- if (!$this->execute) echo $DB2,'</font>*/',$sql,"\n";
- else $dest->Execute($sql);
- }
-
- global $ADODB_COUNTRECS;
- $err = false;
- $savemode = $src->setFetchMode(ADODB_FETCH_NUM);
- $ADODB_COUNTRECS = false;
-
- if (!$this->execute) {
- echo $DB1,$sa['SEL'],"</font>\n*/\n\n";
- echo $DB2,$sa['INS'],"</font>\n*/\n\n";
- $suffix = ($onlyInsert) ? ' PRIMKEY=?' : '';
- echo $DB2,$sa['UPD'],"$suffix</font>\n*/\n\n";
-
- $rs = $src->Execute($sa['SEL']);
- $cnt = 1;
- $upd = 0;
- $ins = 0;
-
- $sqlarr = explode('?',$sa['INS']);
- $nparams = sizeof($sqlarr)-1;
-
- $useQmark = $dest && ($dest->dataProvider != 'oci8');
-
- while ($rs && !$rs->EOF) {
- if ($useQmark) {
- $sql = ''; $i = 0;
- $arr = array_reverse($rs->fields);
- foreach ($arr as $v) {
- $sql .= $sqlarr[$i];
- // from Ron Baldwin <ron.baldwin#sourceprose.com>
- // Only quote string types
- $typ = gettype($v);
- if ($typ == 'string')
- //New memory copy of input created here -mikefedyk
- $sql .= $dest->qstr($v);
- else if ($typ == 'double')
- $sql .= str_replace(',','.',$v); // locales fix so 1.1 does not get converted to 1,1
- else if ($typ == 'boolean')
- $sql .= $v ? $dest->true : $dest->false;
- else if ($typ == 'object') {
- if (method_exists($v, '__toString')) $sql .= $dest->qstr($v->__toString());
- else $sql .= $dest->qstr((string) $v);
- } else if ($v === null)
- $sql .= 'NULL';
- else
- $sql .= $v;
- $i += 1;
-
- if ($i == $nparams) break;
- } // while
-
- if (isset($sqlarr[$i])) {
- $sql .= $sqlarr[$i];
- }
- $INS = $sql;
- } else {
- $INS = $sa['INS'];
- $arr = array_reverse($rs->fields);
- foreach($arr as $k => $v) { // only works on oracle currently
- $k = sizeof($arr)-$k-1;
- $v = str_replace(":","%~%COLON%!%",$v);
- $INS = str_replace(':'.$k,$this->fixupbinary($dest->qstr($v)),$INS);
- }
- $INS = str_replace("%~%COLON%!%",":",$INS);
- if ($this->htmlSpecialChars) $INS = htmlspecialchars($INS);
- }
- echo "-- $cnt\n",$INS,";\n\n";
- $cnt += 1;
- $ins += 1;
- $rs->MoveNext();
- }
- $src->setFetchMode($savemode);
- return $sa;
- } else {
- $saved = $src->debug;
- #$src->debug=1;
- if ($this->limitRecs>100)
- $rs = $src->SelectLimit($sa['SEL'],$this->limitRecs);
- else
- $rs = $src->Execute($sa['SEL']);
- $src->debug = $saved;
- if (!$rs) {
- if ($this->errHandler) $this->_doerr('SEL',array());
- return array(0,0,0,0);
- }
-
-
- if ($this->commitReplicate || $commitRecs > 0) {
- $dest->BeginTrans();
- if ($this->updateSrcFn) $src2->BeginTrans();
- }
-
- if ($this->updateSrcFn && strpos($src2->databaseType,'mssql') !== false) {
- # problem is writers interfere with readers in mssql
- $rs = $src->_rs2rs($rs);
- }
- $cnt = 0;
- $upd = 0;
- $ins = 0;
-
- $sizeofrow = sizeof($selflds);
-
- $fn = $this->selFilter;
- $commitRecs = $this->commitRecs;
-
- $saved = $dest->debug;
-
- if ($this->deleteFirst) $onlyInsert = true;
- while ($origrow = $rs->FetchRow()) {
-
- if ($dest->debug) {flush(); @ob_flush();}
-
- if ($fn) {
- if (!$fn($desttable, $origrow, $deleteFirst, $this, $selflds)) continue;
- }
- $doinsert = true;
- $row = array_slice($origrow,0,$sizeofrow-1);
-
- if (!$onlyInsert) {
- $doinsert = false;
- $upderr = false;
-
- if (isset($srcPKDest)) {
- if (is_null($origrow[$sizeofrow-3])) {
- $doinsert = true;
- $upderr = true;
- }
- }
- if (!$upderr && !$dest->Execute($sa['UPD'],$row)) {
- $err = true;
- $upderr = true;
- if ($this->errHandler) $this->_doerr('UPD',$row);
- if (!$this->neverAbort) break;
- }
-
- if ($upderr || $dest->Affected_Rows() == 0) {
- $doinsert = true;
- } else {
- if (!empty($uniqflds)) $this->RunUpdateSrcFn($src2, $table, $fldoffsets, $origrow, $srcwheress, 'UPD', null, $lastUpdateFld);
- $upd += 1;
- }
- }
-
- if ($doinsert) {
- $inserr = false;
- if (isset($srcPKDest)) {
- $row = array_slice($origrow,0,$sizeofrow-2);
- }
-
- if (! $dest->Execute($sa['INS'],$row)) {
- $err = true;
- $inserr = true;
- if ($this->errHandler) $this->_doerr('INS',$row);
- if ($this->neverAbort) continue;
- else break;
- } else {
- if ($dest->dataProvider == 'oci8') {
- if ($this->oracleSequence) $lastid = $dest->GetOne("select ".$this->oracleSequence.".currVal from dual");
- else $lastid = 'null';
- } else {
- $lastid = $dest->Insert_ID();
- }
-
- if (!$inserr && !empty($uniqflds)) {
- $this->RunUpdateSrcFn($src2, $table, $fldoffsets, $origrow, $srcwheress, 'INS', $lastid,$lastUpdateFld);
- }
- $ins += 1;
- }
- }
- $cnt += 1;
-
- if ($commitRecs > 0 && ($cnt % $commitRecs) == 0) {
- $dest->CommitTrans();
- $dest->BeginTrans();
-
- if ($this->updateSrcFn) {
- $src2->CommitTrans();
- $src2->BeginTrans();
- }
- }
-
- } // while
-
-
- if ($this->commitReplicate || $commitRecs > 0) {
- if (!$this->neverAbort && $err) {
- $dest->RollbackTrans();
- if ($this->updateSrcFn) $src2->RollbackTrans();
- } else {
- $dest->CommitTrans();
- if ($this->updateSrcFn) $src2->CommitTrans();
- }
- }
- }
- if ($cnt != $ins + $upd) echo "<p>ERROR: $cnt != INS $ins + UPD $upd</p>";
- $src->setFetchMode($savemode);
- return array(!$err, $cnt, $ins, $upd);
- }
- // trigger support only for sql server and oracle
- // need to add
- function MergeSrcSetup($srcTable, $pkeys, $srcUpdateDateFld, $srcCopyDateFld, $srcCopyFlagFld,
- $srcCopyFlagType='C(1)', $srcCopyFlagVals = array('Y','N','P','='))
- {
- $sqla = array();
- $src = $this->connSrc;
- $idx = $srcTable.'_mrgIdx';
- $cols = $src->MetaColumns($srcTable);
- #adodb_pr($cols);
- if (!isset($cols[strtoupper($srcUpdateDateFld)])) {
- $sqla = $this->ddSrc->AddColumnSQL($srcTable, "$srcUpdateDateFld TS DEFTIMESTAMP");
- foreach($sqla as $sql) $src->Execute($sql);
- }
-
- if ($srcCopyDateFld && !isset($cols[strtoupper($srcCopyDateFld)])) {
- $sqla = $this->ddSrc->AddColumnSQL($srcTable, "$srcCopyDateFld TS DEFTIMESTAMP");
- foreach($sqla as $sql) $src->Execute($sql);
- }
-
- $sysdate = $src->sysTimeStamp;
- $arrv0 = $src->qstr($srcCopyFlagVals[0]);
- $arrv1 = $src->qstr($srcCopyFlagVals[1]);
- $arrv2 = $src->qstr($srcCopyFlagVals[2]);
- $arrv3 = $src->qstr($srcCopyFlagVals[3]);
-
- if ($srcCopyFlagFld && !isset($cols[strtoupper($srcCopyFlagFld)])) {
- $sqla = $this->ddSrc->AddColumnSQL($srcTable, "$srcCopyFlagFld $srcCopyFlagType DEFAULT $arrv1");
- foreach($sqla as $sql) $src->Execute($sql);
- }
-
- $sqla = array();
-
-
- $name = "{$srcTable}_mrgTr";
- if (is_array($pkeys) && strpos($src->databaseType,'mssql') !== false) {
- $pk = reset($pkeys);
-
- #$sqla[] = "DROP TRIGGER $name";
- $sqltr = "
- TRIGGER $name
- ON $srcTable /* for data replication and merge */
- AFTER UPDATE
- AS
- UPDATE $srcTable
- SET
- $srcUpdateDateFld = case when I.$srcCopyFlagFld = $arrv2 or I.$srcCopyFlagFld = $arrv3 then I.$srcUpdateDateFld
- else $sysdate end,
- $srcCopyFlagFld = case
- when I.$srcCopyFlagFld = $arrv2 then $arrv0
- when I.$srcCopyFlagFld = $arrv3 then D.$srcCopyFlagFld
- else $arrv1 end
- FROM $srcTable S Join Inserted AS I on I.$pk = S.$pk
- JOIN Deleted as D ON I.$pk = D.$pk
- WHERE I.$srcCopyFlagFld = D.$srcCopyFlagFld or I.$srcCopyFlagFld = $arrv2
- or I.$srcCopyFlagFld = $arrv3 or I.$srcCopyFlagFld is null
- ";
- $sqla[] = 'CREATE '.$sqltr; // first if does not exists
- $sqla[] = 'ALTER '.$sqltr; // second if it already exists
- } else if (strpos($src->databaseType,'oci') !== false) {
-
- if (strlen($srcTable)>22) $tableidx = substr($srcTable,0,16).substr(crc32($srcTable),6);
- else $tableidx = $srcTable;
-
- $name = $tableidx.$this->trgSuffix;
- $idx = $tableidx.$this->idxSuffix;
- $sqla[] = "
-CREATE OR REPLACE TRIGGER $name /* for data replication and merge */
-BEFORE UPDATE ON $srcTable REFERENCING NEW AS NEW OLD AS OLD
-FOR EACH ROW
-BEGIN
- if :new.$srcCopyFlagFld = $arrv2 then
- :new.$srcCopyFlagFld := $arrv0;
- elsif :new.$srcCopyFlagFld = $arrv3 then
- :new.$srcCopyFlagFld := :old.$srcCopyFlagFld;
- elsif :old.$srcCopyFlagFld = :new.$srcCopyFlagFld or :new.$srcCopyFlagFld is null then
- if $this->trLogic then
- :new.$srcUpdateDateFld := $sysdate;
- :new.$srcCopyFlagFld := $arrv1;
- end if;
- end if;
-END;
-";
- }
- foreach($sqla as $sql) $src->Execute($sql);
-
- if ($srcCopyFlagFld) $srcCopyFlagFld .= ', ';
- $src->Execute("CREATE INDEX {$idx} on $srcTable ($srcCopyFlagFld$srcUpdateDateFld)");
- }
-
-
- /*
- Perform Merge by copying all data modified from src to dest
- then update src copied flag if present.
-
- Returns array taken from ReplicateData:
-
- Returns an array:
- $arr[0] = true if no error, false if error
- $arr[1] = number of recs processed
- $arr[2] = number of successful inserts
- $arr[3] = number of successful updates
-
- $srcTable = src table
- $dstTable = dest table
- $pkeys = primary keys array. if empty, then only inserts will occur
- $srcignoreflds = ignore these flds (must be upper cased)
- $setsrc = updateSrcFn string
- $srcUpdateDateFld = field in src with the last update date
- $srcCopyFlagFld = false = optional field that holds the copied indicator
- $flagvals=array('Y','N','P','=') = array of values indicating array(copied, not copied).
- Null is assumed to mean not copied. The 3rd value 'P' indicates that we want to force 'Y', bypassing
- default trigger behaviour to reset the COPIED='N' when the record is replicated from other side.
- The last value '=' is don't change copyflag.
- $srcCopyDateFld = field that holds last copy date in src table, which will be updated on Merge()
- $dstCopyDateFld = field that holds last copy date in dst table, which will be updated on Merge()
- $defaultDestRaiseErrorFn = The adodb raiseErrorFn handler. Default is to not raise an error.
- Just output error message to stdout
-
- */
-
-
- function Merge($srcTable, $dstTable, $pkeys, $srcignoreflds, $setsrc,
- $srcUpdateDateFld,
- $srcCopyFlagFld, $flagvals=array('Y','N','P','='),
- $srcCopyDateFld = false,
- $dstCopyDateFld = false,
- $whereClauses = '',
- $orderBy = '', # MUST INCLUDE THE "ORDER BY" suffix
- $copyDoneFlagIdx = 3,
- $defaultDestRaiseErrorFn = '')
- {
- $src = $this->connSrc;
- $dest = $this->connDest;
-
- $time = $src->Time();
-
- $delfirst = $this->deleteFirst;
- $upd = $this->updateSrcFn;
-
- $this->deleteFirst = false;
- //$this->updateFirst = true;
-
- $srcignoreflds[] = $srcUpdateDateFld;
- $srcignoreflds[] = $srcCopyFlagFld;
- $srcignoreflds[] = $srcCopyDateFld;
-
- if (empty($whereClauses)) $whereClauses = '1=1';
- $where = " WHERE ($whereClauses) and ($srcCopyFlagFld = ".$src->qstr($flagvals[1]).')';
- if ($orderBy) $where .= ' '.$orderBy;
- else $where .= ' ORDER BY '.$srcUpdateDateFld;
-
- if ($setsrc) $set[] = $setsrc;
- else $set = array();
-
- if ($srcCopyFlagFld) $set[] = "$srcCopyFlagFld = ".$src->qstr($flagvals[2]);
- if ($srcCopyDateFld) $set[]= "$srcCopyDateFld = ".$src->sysTimeStamp;
- if ($set) $this->updateSrcFn = array(implode(', ',$set));
- else $this->updateSrcFn = '';
-
-
- $extra[$srcCopyFlagFld] = array($dest->qstr($flagvals[0]),$dest->qstr($flagvals[$copyDoneFlagIdx]));
-
- $saveraise = $dest->raiseErrorFn;
- $dest->raiseErrorFn = '';
-
- if ($this->compat && $this->compat == 1.0) $srcUpdateDateFld = '';
- $arr = $this->ReplicateData($srcTable, $dstTable, $pkeys, $where, $srcignoreflds,
- $dstCopyDateFld,$extra,$srcUpdateDateFld);
-
- $dest->raiseErrorFn = $saveraise;
-
- $this->updateSrcFn = $upd;
- $this->deleteFirst = $delfirst;
-
- return $arr;
- }
- /*
- If doing a 2 way merge, then call
- $rep->Merge()
- to save without modifying the COPIEDFLAG ('=').
-
- Then can the following to set the COPIEDFLAG to 'P' which forces the COPIEDFLAG = 'Y'
- $rep->MergeDone()
- */
-
- function MergeDone($srcTable, $dstTable, $pkeys, $srcignoreflds, $setsrc,
- $srcUpdateDateFld,
- $srcCopyFlagFld, $flagvals=array('Y','N','P','='),
- $srcCopyDateFld = false,
- $dstCopyDateFld = false,
- $whereClauses = '',
- $orderBy = '', # MUST INCLUDE THE "ORDER BY" suffix
- $copyDoneFlagIdx = 2,
- $defaultDestRaiseErrorFn = '')
- {
- return $this->Merge($srcTable, $dstTable, $pkeys, $srcignoreflds, $setsrc,
- $srcUpdateDateFld,
- $srcCopyFlagFld, $flagvals,
- $srcCopyDateFld,
- $dstCopyDateFld,
- $whereClauses,
- $orderBy, # MUST INCLUDE THE "ORDER BY" suffix
- $copyDoneFlagIdx,
- $defaultDestRaiseErrorFn);
- }
-
- function _doerr($reason, $selflds)
- {
- $fn = $this->errHandler;
- if ($fn) $fn($this, $reason, $selflds); // set $this->neverAbort to true or false as required inside $fn
- }
-}
diff --git a/replicate/replicate-steps.php b/replicate/replicate-steps.php
deleted file mode 100644
index fca719d2..00000000
--- a/replicate/replicate-steps.php
+++ /dev/null
@@ -1,156 +0,0 @@
-<?php
-/**
- * Replication engine
- *
- * This file is part of ADOdb, a Database Abstraction Layer library for PHP.
- *
- * @package ADOdb
- * @link https://adodb.org Project's web site and documentation
- * @link https://github.com/ADOdb/ADOdb Source code and issue tracker
- *
- * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause
- * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option,
- * any later version. This means you can use it in proprietary products.
- * See the LICENSE.md file distributed with this source code for details.
- * @license BSD-3-Clause
- * @license LGPL-2.1-or-later
- *
- * @copyright 2000-2013 John Lim
- * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community
- */
-
-# CONFIG
-
-if (empty($USER)) {
- $BA = "LOAN"; ## -- leave $BA as empty string to copy all BA. Otherwise enter 1 BA (no need to quote BA)
- $STAGES = ""; ## $STAGES = "STGCAT1,STGCAT2" -- leave $STAGES as empty string to run all stages. No need to quote stgcats.
-
- $HOST='192.168.0.2';
- $USER='JCOLLECT_BKRM';
- $PWD='natsoft';
- $DBASE='RAPTOR';
-}
-# =================================== INCLUDES
-
-include_once('../adodb.inc.php');
-include_once('adodb-replicate.inc.php');
-
-# ==================================== CONNECTION
-$DB = ADONewConnection('oci8');
-$ok = $DB->Connect($HOST,$USER,$PWD,$DBASE);
-if (!$ok) return;
-
-
-#$DB->debug=1;
-
-$bkup = 'tmp'.date('ymd_His');
-
-
-if ($BA) {
- $QTY_BA = " and qu_bacode='$BA'";
- if (1) $STP_BA = " and s_stagecat in (select stg_stagecat from kbstage where stg_bacode='$BA')"; # OLDER KBSTEP
- else $STP_BA = " and s_bacode='$BA'"; # LATEST KBSTEP format
- $STG_BA = " and stg_bacode='$BA'";
-} else {
- $QTY_BA = "";
- $STP_BA = "";
- $STG_BA = "";
-}
-
-if ($STAGES) {
-
- $STAGES = explode(',',$STAGES);
- $STAGES = "'".implode("','",$STAGES)."'";
- $QTY_STG = " and qu_stagecat in ($STAGES)";
- $STP_STG = " and s_stagecat in ($STAGES)";
- $STG_STG = " and stg_stagecat in ($STAGES)";
-} else {
- $QTY_STG = "";
- $STP_STG = "";
- $STG_STG = "";
-}
-
-echo "<pre>
-
-/******************************************************************************
-<font color=green>
- Migrate stages, steps and qtypes for the following
-
- business area: $BA
- and stages: $STAGES
-
-
- WARNING: DO NOT 'Ignore All Errors'.
- If any error occurs, make sure you stop and check the reason and fix it.
- Otherwise you could corrupt everything!!!
-
- Connected to $USER@$DBASE $HOST;
-</font>
-*******************************************************************************/
-
--- BACKUP
-create table kbstage_$bkup as select * from kbstage;
-create table kbstep_$bkup as select * from kbstep;
-create table kbqtype_$bkup as select * from kbqtype;
-
-
--- IF CODE FAILS, REMEMBER TO RENABLE ALL TRIGGERS and following CONSTRAINT
-ALTER TABLE kbstage DISABLE all triggers;
-ALTER TABLE kbstep DISABLE all triggers;
-ALTER TABLE kbqtype DISABLE all triggers;
-ALTER TABLE jqueue DISABLE CONSTRAINT QUEUE_MUST_HAVE_TYPE;
-
-
--- NOW DELETE OLD STEPS/STAGES/QUEUES
-delete from kbqtype where qu_mode in ('STAGE','STEP') $QTY_BA $QTY_STG;
-delete from kbstep where (1=1) $STP_BA$STP_STG;
-delete from kbstage where (1=1)$STG_BA$STG_STG;
-
-
-
-SET DEFINE OFF; -- disable variable handling by sqlplus
-/
-/* Assume kbstrategy and business areas are compatible for steps and stages to be copied */
-</pre>
-
-";
-
-
-$rep = new ADODB_Replicate($DB,$DB);
-$rep->execute = false;
-$rep->deleteFirst = false;
-
- // src table name, dst table name, primary key, where condition
-$rep->ReplicateData('KBSTAGE', 'KBSTAGE', array(), " where (1=1)$STG_BA$STG_STG");
-$rep->ReplicateData('KBSTEP', 'KBSTEP', array(), " where (1=1)$STP_BA$STP_STG");
-$rep->ReplicateData('KBQTYPE','KBQTYPE',array()," where qu_mode in ('STAGE','STEP')$QTY_BA$QTY_STG");
-
-echo "
-
--- Check for QUEUES not in KBQTYPE and FIX by copying from kbqtype_$bkup
-begin
-for rec in (select distinct q_type from jqueue where q_type not in (select qu_code from kbqtype)) loop
- insert into kbqtype select * from kbqtype_$bkup where qu_code = rec.q_type;
- update kbqtype set qu_name=substr('MISSING.'||qu_name,1,64) where qu_code=rec.q_type;
-end loop;
-end;
-/
-
-commit;
-
-
-ALTER TABLE kbstage ENABLE all triggers;
-ALTER TABLE kbstep ENABLE all triggers;
-ALTER TABLE kbqtype ENABLE all triggers;
-ALTER TABLE jqueue ENABLE CONSTRAINT QUEUE_MUST_HAVE_TYPE;
-
-/*
--- REMEMBER TO COMMIT
- commit;
- begin Juris.UpdateQCounts; end;
-
--- To check for bad queues after conversion, run this
- select * from kbqtype where qu_name like 'MISSING%'
-*/
-/
-";
diff --git a/replicate/test-tnb.php b/replicate/test-tnb.php
deleted file mode 100644
index 6be11072..00000000
--- a/replicate/test-tnb.php
+++ /dev/null
@@ -1,440 +0,0 @@
-<?php
-/**
- * Replication engine
- *
- * This file is part of ADOdb, a Database Abstraction Layer library for PHP.
- *
- * @package ADOdb
- * @link https://adodb.org Project's web site and documentation
- * @link https://github.com/ADOdb/ADOdb Source code and issue tracker
- *
- * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause
- * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option,
- * any later version. This means you can use it in proprietary products.
- * See the LICENSE.md file distributed with this source code for details.
- * @license BSD-3-Clause
- * @license LGPL-2.1-or-later
- *
- * @copyright 2000-2013 John Lim
- * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community
- */
-include_once('../adodb.inc.php');
-include_once('adodb-replicate.inc.php');
-
-set_time_limit(0);
-
-function IndexFilter($dtable, $idxname,$flds,$options)
-{
- if (strlen($idxname) > 28) $idxname = substr($idxname,0,24).rand(1000,9999);
- return $idxname;
-}
-
-function SelFilter($table, &$arr, $delfirst)
-{
- return true;
-}
-
-function updatefilter($table, $fld, $val)
-{
- return "nvl($fld, $val)";
-}
-
-
-function FieldFilter(&$fld,$mode)
-{
- $uf = strtoupper($fld);
- switch($uf) {
- case 'SIZEFLD':
- return 'Size';
-
- case 'GROUPFLD':
- return 'Group';
-
- case 'GROUP':
- if ($mode == 'SELECT') $fld = '"Group"';
- return 'GroupFld';
- case 'SIZE':
- if ($mode == 'SELECT') $fld = '"Size"';
- return 'SizeFld';
- }
- return $fld;
-}
-
-function ParseTable(&$table, &$pkey)
-{
- $table = trim($table);
- if (strlen($table) == 0) return false;
- if (strpos($table, '#') !== false) {
- $at = strpos($table, '#');
- $table = trim(substr($table,0,$at));
- if (strlen($table) == 0) return false;
- }
-
- $tabarr = explode(',',$table);
- if (sizeof($tabarr) == 1) {
- $table = $tabarr[0];
- $pkey = '';
- echo "No primary key for $table **** **** <br>";
- } else {
- $table = trim($tabarr[0]);
- $pkey = trim($tabarr[1]);
- if (strpos($pkey,' ') !== false) echo "Bad PKEY for $table $pkey<br>";
- }
-
- return true;
-}
-
-global $TARR;
-
-function TableStats($rep, $table, $pkey)
-{
-global $TARR;
-
- if (empty($TARR)) $TARR = array();
- $cnt = $rep->connSrc->GetOne("select count(*) from $table");
- if (isset($TARR[$table])) echo "<h1>Table $table repeated twice</h1>";
- $TARR[$table] = $cnt;
-
- if ($pkey) {
- $ok = $rep->connSrc->SelectLimit("select $pkey from $table",1);
- if (!$ok) echo "<h1>$table: $pkey does not exist</h1>";
- } else
- echo "<h1>$table: no primary key</h1>";
-}
-
-function CreateTable($rep, $table)
-{
-## CREATE TABLE
- #$DB2->Execute("drop table $table");
-
- $rep->execute = true;
- $ok = $rep->CopyTableStruct($table);
- if ($ok) echo "Table Created<br>\n";
- else {
- echo "<hr>Error: Cannot Create Table<hr>\n";
- }
- flush();@ob_flush();
-}
-
-function CopyData($rep, $table, $pkey)
-{
- $dtable = $table;
-
- $rep->execute = true;
- $rep->deleteFirst = true;
-
- $secs = time();
- $rows = $rep->ReplicateData($table,$dtable,array($pkey));
- $secs = time() - $secs;
- if (!$rows || !$rows[0] || !$rows[1] || $rows[1] != $rows[2]+$rows[3]) {
- echo "<hr>Error: "; var_dump($rows); echo " (secs=$secs) <hr>\n";
- } else
- echo date('H:i:s'),': ',$rows[1]," record(s) copied, ",$rows[2]," inserted, ",$rows[3]," updated (secs=$secs)<br>\n";
- flush();@ob_flush();
-}
-
-function MergeDataJohnTest($rep, $table, $pkey)
-{
- $rep->SwapDBs();
-
- $dtable = $table;
- $rep->oracleSequence = 'LGBSEQUENCE';
-
-# $rep->MergeSrcSetup($table, array($pkey),'UpdatedOn','CopiedFlag');
- if (strpos($rep->connDest->databaseType,'mssql') !== false) { # oracle ==> mssql
- $ignoreflds = array($pkey);
- $ignoreflds[] = 'MSSQL_ID';
- $set = 'MSSQL_ID=nvl($INSERT_ID,MSSQL_ID)';
- $pkeyarr = array(array($pkey),false,array('MSSQL_ID'));# array('MSSQL_ID', 'ORA_ID'));
- } else { # mssql ==> oracle
- $ignoreflds = array($pkey);
- $ignoreflds[] = 'ORA_ID';
- $set = '';
- #$set = 'ORA_ID=isnull($INSERT_ID,ORA_ID)';
- $pkeyarr = array(array($pkey),array('MSSQL_ID'));
- }
- $rep->execute = true;
- #$rep->updateFirst = false;
- $ok = $rep->Merge($table, $dtable, $pkeyarr, $ignoreflds, $set, 'UpdatedOn','CopiedFlag',array('Y','N','P','='), 'CopyDate');
- var_dump($ok);
-
- #$rep->connSrc->Execute("update JohnTest set name='Apple' where id=4");
-}
-
-$DB = ADONewConnection('odbtp');
-#$ok = $DB->Connect('localhost','root','','northwind');
-$ok = $DB->Connect('192.168.0.1','DRIVER={SQL Server};SERVER=(local);UID=sa;PWD=natsoft;DATABASE=OIR;','','');
-$DB->_bindInputArray = false;
-
-$DB2 = ADONewConnection('oci8');
-$ok2 = $DB2->Connect('192.168.0.2','tnb','natsoft','RAPTOR','');
-
-if (!$ok || !$ok2) die("Failed connection DB=$ok DB2=$ok2<br>");
-
-$tables =
-"
-JohnTest,id
-";
-
-# net* are ERMS, need last updated field from LGBnet
-# tblRep* are tables insert or update from Juris, need last updated field also
-# The rest are lookup tables, can copy all from LGBnet
-
-$tablesOrig =
-"
-SysVoltSubLevel,id
-# Lookup table for Restoration Details screen
-sysefi,ID # (not identity)
-sysgenkva,ID #(not identity)
-sysrestoredby,ID #(not identity)
-# Sel* table added on 24 Oct
-SELSGManufacturer,ID
-SelABCCondSizeLV,ID
-SelABCCondSizeMV,ID
-SelArchingHornSize,ID
-SelBallastSize,ID
-SelBallastType,ID
-SelBatteryType,ID #(not identity)
-SelBreakerCapacity,ID
-SelBreakerType,ID #(not identity)
-SelCBreakerManuf,ID
-SelCTRatio,ID #(not identity)
-SelCableBrand,ID
-SelCableSize,ID
-SelCableSizeLV,ID # (not identity)
-SelCapacitorSize,ID
-SelCapacitorType,ID
-SelColourCode,ID
-SelCombineSealingChamberSize,ID
-SelConductorBrand,ID
-SelConductorSize4,ID
-SelConductorSizeLV,ID
-SelConductorSizeMV,ID
-SelContactorSize,ID
-SelContractor,ID
-SelCoverType,ID
-SelCraddleSize,ID
-SelDeadEndClampBrand,ID
-SelDeadEndClampSize,ID
-SelDevTermination,ID
-SelFPManuf,ID
-SelFPillarRating,ID
-SelFalseTrue,ID
-SelFuseManuf,ID
-SelFuseType,ID
-SelIPCBrand,ID
-SelIPCSize,ID
-SelIgnitorSize,ID
-SelIgnitorType,ID
-SelInsulatorBrand,ID
-SelJoint,ID
-SelJointBrand,ID
-SelJunctionBoxBrand,ID
-SelLVBoardBrand,ID
-SelLVBoardSize,ID
-SelLVOHManuf,ID
-SelLVVoltage,ID
-SelLightningArresterBrand,ID
-SelLightningShieldwireSize,ID
-SelLineTapSize,ID
-SelLocation,ID
-SelMVVoltage,ID
-SelMidSpanConnectorsSize,ID
-SelMidSpanJointSize,ID
-SelNERManuf,ID
-SelNERType,ID
-SelNLinkSize,ID
-SelPVCCondSizeLV,ID
-SelPoleBrand,ID
-SelPoleConcreteSize,ID
-SelPoleSize,ID
-SelPoleSpunConcreteSize,ID
-SelPoleSteelSize,ID
-SelPoleType,ID
-SelPoleWoodSize,ID
-SelPorcelainFuseSize,ID
-SelRatedFaultCurrentBreaker,ID
-SelRatedVoltageSG,ID #(not identity)
-SelRelayType,ID # (not identity)
-SelResistanceValue,ID
-SelSGEquipmentType,ID # (not identity)
-SelSGInsulationType,ID # (not identity)
-SelSGManufacturer,ID
-SelStayInsulatorSize,ID
-SelSuspensionClampBrand,ID
-SelSuspensionClampSize,ID
-SelTSwitchType,ID
-SelTowerType,ID
-SelTransformerCapacity,ID
-SelTransformerManuf,ID
-SelTransformerType,ID #(not identity)
-SelTypeOfArchingHorn,ID
-SelTypeOfCable,ID #(not identity)
-SelTypeOfConductor,ID # (not identity)
-SelTypeOfInsulationCB,ID # (not identity)
-SelTypeOfMidSpanJoint,ID
-SelTypeOfSTJoint,ID
-SelTypeSTCable,ID
-SelUGVoltage,ID # (not identity)
-SelVoltageInOut,ID
-SelWireSize,ID
-SelWireType,ID
-SelWonpieceBrand,ID
-#
-# Net* tables added on 24 Oct
-NetArchingHorn,Idx
-NetBatteryBank,Idx # identity, FunctLocation Pri
-NetBiMetal,Idx
-NetBoxFuse,Idx
-NetCable,Idx # identity, FunctLocation Pri
-NetCapacitorBank,Idx # identity, FunctLocation Pri
-NetCircuitBreaker,Idx # identity, FunctLocation Pri
-NetCombineSealingChamber,Idx
-NetCommunication,Idx
-NetCompInfras,Idx
-NetControl,Idx
-NetCraddle,Idx
-NetDeadEndClamp,Idx
-NetEarthing,Idx
-NetFaultIndicator,Idx
-NetFeederPillar,Idx # identity, FunctLocation Pri
-NetGenCable,Idx # identity , FunctLocation Not Null
-NetGenerator,Idx
-NetGrid,Idx
-NetHVOverhead,Idx #identity, FunctLocation Pri
-NetHVUnderground,Idx #identity, FunctLocation Pri
-NetIPC,Idx
-NetInductorBank,Idx
-NetInsulator,Idx
-NetJoint,Idx
-NetJunctionBox,Idx
-NetLVDB,Idx #identity, FunctLocation Pri
-NetLVOverhead,Idx
-NetLVUnderground,Idx # identity, FunctLocation Not Null
-NetLightningArrester,Idx
-NetLineTap,Idx
-NetMidSpanConnectors,Idx
-NetMidSpanJoint,Idx
-NetNER,Idx # identity , FunctLocation Pri
-NetOilPump,Idx
-NetOtherComponent,Idx
-NetPole,Idx
-NetRMU,Idx # identity, FunctLocation Pri
-NetStreetLight,Idx
-NetStrucSupp,Idx
-NetSuspensionClamp,Idx
-NetSwitchGear,Idx # identity, FunctLocation Pri
-NetTermination,Idx
-NetTransition,Idx
-NetWonpiece,Idx
-#
-# comment1
-SelMVFuseType,ID
-selFuseSize,ID
-netRelay,Idx # identity, FunctLocation Pri
-SysListVolt,ID
-sysVoltLevel,ID_SVL
-sysRestoration,ID_SRE
-sysRepairMethod,ID_SRM # (not identity)
-
-sysInterruptionType,ID_SIN
-netTransformer,Idx # identity, FunctLocation Pri
-#
-#
-sysComponent,ID_SC
-sysCodecibs #-- no idea, UpdatedOn(the only column is unique),Ermscode,Cibscode is unique but got null value
-sysCodeno,id
-sysProtection,ID_SP
-sysEquipment,ID_SEQ
-sysAddress #-- no idea, ID_SAD(might be auto gen No)
-sysWeather,ID_SW
-sysEnvironment,ID_SE
-sysPhase,ID_SPH
-sysFailureCause,ID_SFC
-sysFailureMode,ID_SFM
-SysSchOutageMode,ID_SSM
-SysOutageType,ID_SOT
-SysInstallation,ID_SI
-SysInstallationCat,ID_SIC
-SysInstallationType,ID_SIT
-SysFaultCategory,ID_SF #(not identity)
-SysResponsible,ID_SR
-SysProtectionOperation,ID_SPO #(not identity)
-netCodename,CodeNo #(not identity)
-netSubstation,Idx #identity, FunctLocation Pri
-netLvFeeder,Idx # identity, FunctLocation Pri
-#
-#
-tblReport,ReportNo
-tblRepRestoration,ID_RR
-tblRepResdetail,ID_RRD
-tblRepFailureMode,ID_RFM
-tblRepFailureCause,ID_RFC
-tblRepRepairMethod,ReportNo # (not identity)
-tblInterruptionType,ID_TIN
-tblProtType,ID_PT #--capital letter
-tblRepProtection,ID_RP
-tblRepComponent,ID_RC
-tblRepWeather,ID_RW
-tblRepEnvironment,ID_RE
-tblRepSubstation,ID_RSS
-tblInstallationType,ID_TIT
-tblInstallationCat,ID_TIC
-tblFailureCause,ID_TFC
-tblFailureMode,ID_TFM
-tblProtection,ID_TP
-tblComponent,ID_TC
-tblProtdetail,Id # (Id)--capital letter for I
-tblInstallation,ID_TI
-#
-";
-
-
-$tables = explode("\n",$tables);
-
-$rep = new ADODB_Replicate($DB,$DB2);
-$rep->fieldFilter = 'FieldFilter';
-$rep->selFilter = 'SELFILTER';
-$rep->indexFilter = 'IndexFilter';
-
-if (1) {
- $rep->debug = 1;
- $DB->debug=1;
- $DB2->debug=1;
-}
-
-# $rep->SwapDBs();
-
-$cnt = sizeof($tables);
-foreach($tables as $k => $table) {
- $pkey = '';
- if (!ParseTable($table, $pkey)) continue;
-
- #######################
-
- $kcnt = $k+1;
- echo "<h1>($kcnt/$cnt) $table -- $pkey</h1>\n";
- flush();@ob_flush();
-
- CreateTable($rep,$table);
-
-
- # COPY DATA
-
-
- TableStats($rep, $table, $pkey);
-
- if ($table == 'JohnTest') MergeDataJohnTest($rep, $table, $pkey);
- else CopyData($rep, $table, $pkey);
-
-}
-
-
-if (!empty($TARR)) {
- ksort($TARR);
- adodb_pr($TARR);
- asort($TARR);
- adodb_pr($TARR);
-}
-
-echo "<hr>",date('H:i:s'),": Done</hr>";
diff --git a/scripts/adodbutil.py b/scripts/adodbutil.py
new file mode 100644
index 00000000..c0bcfb4d
--- /dev/null
+++ b/scripts/adodbutil.py
@@ -0,0 +1,182 @@
+"""
+ADOdb release management scripts utilities and helper classes.
+
+- Environment class
+ Reads configuration variables from the environment file, and makes them
+ available in the 'env' global variable..
+- Gitter class
+ Use Gitter REST API to post announcements
+
+This file is part of ADOdb, a Database Abstraction Layer library for PHP.
+
+@package ADOdb
+@link https://adodb.org Project's web site and documentation
+@link https://github.com/ADOdb/ADOdb Source code and issue tracker
+
+The ADOdb Library is dual-licensed, released under both the BSD 3-Clause
+and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option,
+any later version. This means you can use it in proprietary products.
+See the LICENSE.md file distributed with this source code for details.
+@license BSD-3-Clause
+@license LGPL-2.1-or-later
+
+@copyright 2022 Damien Regad, Mark Newnham and the ADOdb community
+@author Damien Regad
+"""
+import re
+import urllib.parse
+from os import path
+
+import requests
+import yaml
+from markdown import markdown
+
+
+class Environment:
+ # See env.yml.sample for details about these config variables
+ sf_api_key = None
+
+ github_token = None
+ github_repo = 'ADOdb/ADOdb'
+
+ gitter_token = None
+ gitter_room = 'ADOdb/ADOdb'
+
+ matrix_token = None
+ matrix_domain = 'gitter.im'
+ matrix_room = '#ADOdb_ADOdb:' + matrix_domain
+
+ twitter_account = 'ADOdb_announce'
+ twitter_api_key = None
+ twitter_api_secret = None
+ twitter_bearer_token = None # Currently unused
+ twitter_access_token = None
+ twitter_access_secret = None
+
+ def __init__(self, filename='env.yml'):
+ """
+ Constructor - load the config file and initialize properties.
+
+ :param filename: Name of YAML config file to load
+ """
+ env_file = path.join(path.dirname(path.abspath(__file__)), filename)
+
+ # Read the config file
+ try:
+ with open(env_file, 'r') as stream:
+ config = yaml.safe_load(stream)
+ except yaml.parser.ParserError as e:
+ raise Exception("Invalid Environment file") from e
+
+ # Assign class properties from config
+ for key, value in config.items():
+ setattr(self, key, value)
+
+
+class Matrix:
+ """
+ Posting messages to a Matrix room via REST API
+ """
+ api_root = '_matrix/client/v3/'
+ domain = ''
+ base_url = ''
+ room_alias = ''
+ room_id = ''
+
+ _headers = ''
+
+ def __init__(self, domain, token, room_alias):
+ """
+ Class Constructor.
+
+ :param domain: Matrix Server's domain name
+ :param token: Matrix REST API token
+ :param room_alias: Matrix Room alias, e.g. `#room:server.id`
+ """
+ self._headers = {
+ 'Content-Type': 'application/json',
+ 'Accept': 'application/json',
+ 'Authorization': 'Bearer ' + token.strip()
+ }
+
+ self.domain = domain
+ self._set_base_url()
+ self._set_room(room_alias)
+
+
+ def url(self, endpoint):
+ """
+ Get Matrix REST API URL for the given endpoint.
+
+ :param endpoint: REST API endpoint
+ :return: URL
+ """
+ return self.base_url + endpoint
+
+ def _set_base_url(self):
+ """
+ Retrieve the Matrix API base URL for the given Domain and initialize
+ the self.base_url property.
+ """
+ r = requests.get(f'https://{self.domain}/.well-known/matrix/client')
+
+ if r.status_code != requests.codes.ok:
+ raise Exception(r.text)
+
+ self.base_url = r.json()['m.homeserver']['base_url'] + \
+ '/' + self.api_root
+
+ def _set_room(self, alias):
+ """
+ Retrieve the Matrix Room ID from the given alias (after adding the
+ leading '#' and the Server name if not provided) and initialize the
+ room_alias and room_id properties.
+
+ :param alias:
+ """
+ if not alias:
+ raise Exception("Matrix Room Alias not defined")
+
+ # Add leading '#' if needed
+ if alias[0] != '#':
+ alias = '#' + alias
+ # If the alias does not include the Server, add the domain
+ if ':' not in alias:
+ alias += ':' + self.domain
+ self.room_alias = alias
+
+ # Retrieve Room ID
+ url = self.url('directory/room/') + urllib.parse.quote(alias)
+ r = requests.get(url, headers=self._headers)
+ if r.status_code != requests.codes.ok:
+ raise Exception(r.json()['error'])
+
+ self.room_id = r.json()['room_id']
+
+ def post(self, message):
+ """
+ Post a message to a Matrix room.
+
+ :param message: Message text in Markdown format
+
+ :return: Posted message's ID
+ """
+ html = markdown(message)
+ plain_text = re.sub(r'(<!--.*?-->|<[^>]*>)', '', html)
+ payload = {
+ 'msgtype': 'm.text',
+ 'body': plain_text,
+ 'format': 'org.matrix.custom.html',
+ 'formatted_body': html,
+ }
+
+ url = self.url(f'rooms/{self.room_id}/send/m.room.message')
+ r = requests.post(url, headers=self._headers, json=payload)
+ if r.status_code != requests.codes.ok:
+ raise Exception(r.text)
+
+ return r.json()['event_id']
+
+
+# Initialize environment
+env = Environment()
diff --git a/scripts/announce.py b/scripts/announce.py
new file mode 100755
index 00000000..51b2dd3a
--- /dev/null
+++ b/scripts/announce.py
@@ -0,0 +1,253 @@
+#!/usr/bin/env -S python3 -u
+"""
+ADOdb announcements script.
+
+Posts release announcements to
+- Gitter
+- Twitter
+
+This file is part of ADOdb, a Database Abstraction Layer library for PHP.
+
+@package ADOdb
+@link https://adodb.org Project's web site and documentation
+@link https://github.com/ADOdb/ADOdb Source code and issue tracker
+
+The ADOdb Library is dual-licensed, released under both the BSD 3-Clause
+and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option,
+any later version. This means you can use it in proprietary products.
+See the LICENSE.md file distributed with this source code for details.
+@license BSD-3-Clause
+@license LGPL-2.1-or-later
+
+@copyright 2022 Damien Regad, Mark Newnham and the ADOdb community
+@author Damien Regad
+"""
+
+import argparse
+from datetime import date
+import json
+import re
+from pathlib import Path
+
+import tweepy # https://www.tweepy.org/
+from git import Repo # https://gitpython.readthedocs.io
+# https://github.com/PyGithub/PyGithub
+from github import Github, GithubException, Milestone
+
+from adodbutil import env, Matrix
+
+
+def process_command_line():
+ """
+ Parse command-line options
+ :return: Namespace
+ """
+ # Get most recent Git tag
+ repo = Repo(path=Path(__file__).parents[1])
+ tags = sorted(repo.tags, key=lambda t: t.tag.tagged_date)
+ latest_tag = str(tags[-1])
+
+ parser = argparse.ArgumentParser(
+ description="Post ADOdb release announcement messages to Gitter."
+ )
+ parser.add_argument('version',
+ nargs='?',
+ default=latest_tag,
+ help="Version number to announce; if not specified, "
+ "the latest tag will be used.")
+ parser.add_argument('-m', '--message',
+ help="Additional text to add to announcement message")
+ parser.add_argument('-b', '--batch',
+ action="store_true",
+ help="Batch mode - do not ask for confirmation "
+ "before posting")
+
+ only = parser.add_mutually_exclusive_group()
+ only.add_argument('-g', '--gitter-only',
+ action="store_true",
+ help="Only post the announcement to Gitter")
+ only.add_argument('-t', '--twitter-only',
+ action="store_true",
+ help="Only post the announcement to Twitter")
+ only.add_argument('-u', '--github-only',
+ action="store_true",
+ help="Only post the announcement to GitHub")
+
+ return parser.parse_args()
+
+
+def github_close_milestone(repo, version):
+ print(f"Closing Milestone '{version}'")
+
+ # Search Milestone for version
+ milestone_found = False
+ milestone: Milestone.Milestone
+ for milestone in repo.get_milestones():
+ if milestone.title == version:
+ milestone_found = True
+ break
+
+ # Milestone not found, check if already closed
+ if not milestone_found:
+ # Process closed Milestones in reverse order of due_on, to minimize
+ # number of iterations
+ for milestone in repo.get_milestones(state='closed',
+ sort='due_on',
+ direction='desc'):
+ if milestone.title == version:
+ print(f"Already closed {milestone.raw_data['html_url']}")
+ return
+ raise Exception(f"Milestone '{version}' not found")
+
+ # Close the milestone
+ # noinspection PyUnboundLocalVariable
+ milestone.edit(title=milestone.title,
+ state='closed',
+ due_on=date.today())
+
+
+def post_github(version, message, changelog_link):
+ print(f"GitHub Release for repository '{env.github_repo}'")
+
+ gh = Github(env.github_token)
+ repo = gh.get_repo(env.github_repo)
+
+ # Check if Release already exists
+ version = 'v' + version
+ try:
+ rel = repo.get_release(version)
+ print(f"Existing release '{version}' found", rel.html_url)
+
+ # Discard the message provided on command-line, and use the one from
+ # the Release's description, inform user to update it on GitHub.
+ if message:
+ print(f"Your message will be discarded; "
+ "the Release's description will be used instead.\n"
+ "Edit it on GitHub if needed")
+ else:
+ print("Retrieving the Release's description for the "
+ "announcement message")
+
+ # Remove the changelog link to keep only the release's message
+ message = re.sub(r"[,.]?\s*(Please )?See .*$",
+ "",
+ rel.body,
+ flags=re.IGNORECASE).strip()
+ if message:
+ message += ".\n"
+ except GithubException as err:
+ if err.status != 404:
+ raise err
+ print(f"Release '{version}' does not exist yet")
+
+ # Make sure the version has been tagged
+ try:
+ repo.get_git_ref('tags/' + version)
+ print(f"Tag '{version}' found")
+ except GithubException:
+ print(f"ERROR: Tag '{version}' does not exist on GitHub, "
+ "please push it first")
+ exit(1)
+
+ # Create the release
+ rel = repo.create_git_release(version,
+ version,
+ message + changelog_link)
+ print("Release created successfully", rel.html_url)
+
+ print()
+
+ # Closing the Milestone
+ try:
+ github_close_milestone(repo, version)
+ except Exception as e:
+ print("WARNING: " + str(e) + "\n")
+
+ # Return message to be used for remaining announcements
+ return message
+
+
+def post_gitter(message):
+ print(f"Posting to Gitter ({env.matrix_room})... ")
+ matrix = Matrix(env.matrix_domain, env.matrix_token, env.matrix_room)
+ message_id = matrix.post('# ' + message)
+ print("Message posted successfully\n"
+ f"https://matrix.to/#/{matrix.room_id}/{message_id}")
+ print()
+
+
+def post_twitter(message):
+ print(f"Posting to Twitter ({env.twitter_account})... ",)
+ twitter = tweepy.Client(
+ consumer_key=env.twitter_api_key,
+ consumer_secret=env.twitter_api_secret,
+ access_token=env.twitter_access_token,
+ access_token_secret=env.twitter_access_secret
+ )
+ try:
+ r = twitter.create_tweet(text=message)
+ except tweepy.errors.HTTPException as e:
+ print("ERROR:", e)
+ return
+ print("Tweeted successfully\n"
+ f"https://twitter.com/{env.twitter_account}/status/{r.data['id']}")
+ print()
+
+
+def main():
+ args = process_command_line()
+
+ post_everywhere = not args.gitter_only \
+ and not args.github_only \
+ and not args.twitter_only
+ version = args.version.lstrip('v')
+ changelog_url = f"https://github.com/ADOdb/ADOdb/blob/v{version}" \
+ "/docs/changelog.md"
+ message = args.message.rstrip(".") + ".\n" if args.message else ""
+
+ # Tell user where the release will be announced
+ print(f"Posting to: ", end='')
+ if post_everywhere or args.github_only:
+ print(f"GitHub ({env.github_repo})",
+ end=', ' if post_everywhere else '\n')
+ if post_everywhere or args.gitter_only:
+ print(f"Gitter ({env.matrix_room})",
+ end=', ' if post_everywhere else '\n')
+ if post_everywhere or args.twitter_only:
+ print(f"Twitter ({env.twitter_account})")
+ print()
+
+ # Create GitHub release, retrieve message from it if it already exists
+ if post_everywhere or args.github_only:
+ message = post_github(version,
+ message,
+ f"See [Changelog]({changelog_url}) for details")
+ if args.github_only:
+ return
+
+ # Build announcement message
+ msg_announce = f"ADOdb Version {version} released\n{message}" \
+ "See Changelog " + changelog_url
+
+ # Get confirmation
+ if not args.batch:
+ print("Review ", end='')
+ print("Announcement message")
+ print("-" * 27)
+ print(msg_announce)
+ print("-" * 27)
+ if not args.batch:
+ reply = input("Proceed with posting ? ")
+ if not reply.casefold() == 'y':
+ print("Aborting")
+ exit(1)
+ print()
+
+ if post_everywhere or args.gitter_only:
+ post_gitter(msg_announce)
+ if post_everywhere or args.twitter_only:
+ post_twitter(msg_announce)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/env.yml.sample b/scripts/env.yml.sample
index fce3840d..3b257b3e 100644
--- a/scripts/env.yml.sample
+++ b/scripts/env.yml.sample
@@ -4,4 +4,29 @@
# SourceForge API key
# Get it from https://sourceforge.net/auth/preferences/
# under "Releases API Key"
-api_key:
+sf_api_key:
+
+# Matrix
+# Get API Token from Element: click profile icon (top left), All Settings,
+# Help & About, scroll down to Advanced section (bottom), expand Access Token
+matrix_token:
+# Home server of the user ID owning the Token
+matrix_domain: gitter.im
+# Room alias. If ':server' is not specified, matrix_domain will be appended
+matrix_room: "#ADOdb_ADOdb:gitter.im"
+
+# Twitter
+# Manage API keys from https://developer.twitter.com/en/portal/dashboard
+twitter_account: ADOdb_announce
+# Consumer Keys
+twitter_api_key:
+twitter_api_secret:
+# Authentication Token (must have write permission to post tweets)
+twitter_access_token:
+twitter_access_secret:
+
+# GitHub
+# Get Personal access token from https://github.com/settings/tokens
+# (must have public_repo scope)
+github_token:
+github_repo: ADOdb/ADOdb
diff --git a/scripts/fix-static-docs.php b/scripts/fix-static-docs.php
index c4159dd5..07da8812 100644
--- a/scripts/fix-static-docs.php
+++ b/scripts/fix-static-docs.php
@@ -1,4 +1,4 @@
-<?php
+<?php
/**
* Post-processing of the DokuWiki documentation export.
*
@@ -22,209 +22,240 @@
*/
/**
+ *
+ */
+$source_dir = 'documentation-base';
+$target_dir = 'documentation';
+
+/**
* Recurses a directory and deletes files inside
*
* Copied from php.net
*
-* @param string $dir The driectory name
-* $return null
+* @param string $dir The directory name
+* $return bool
*/
-function delTree($dir) {
- $files = array_diff(scandir($dir), array('.','..'));
- foreach ($files as $file) {
- (is_dir("$dir/$file")) ? delTree("$dir/$file") : unlink("$dir/$file");
- }
- return rmdir($dir);
-}
+function delTree($dir)
+{
+ $files = @scandir($dir);
+ if ($files === false) {
+ return false;
+ }
+ $files = array_diff($files, array('.', '..'));
+
+ foreach ($files as $file) {
+ $result = (is_dir("$dir/$file") ? delTree("$dir/$file") : unlink("$dir/$file"));
+ if ($result === false) {
+ return false;
+ }
+ }
+ return rmdir($dir);
+}
/**
* Initializes the listdiraux method with a starting directory point
*
* copied from php.net
*
-* @param string $dir Starting directory
-* @return array FQ list of files
-*/
-function listdir($dir='.') {
- if (!is_dir($dir)) {
- return false;
- }
- $files = array();
- listdiraux($dir, $files);
+* @param string $dir Starting directory
+* @return array|false FQ list of files
+*/
+function listdir($dir='.')
+{
+ if (!is_dir($dir)) {
+ return false;
+ }
+ $files = array();
+ listdiraux($dir, $files);
- return $files;
-}
+ return $files;
+}
/**
* Recurses a directory structure and creates a list of files
*
* @param string $dir Starting directory
* @param string[] $files By reference, the current file list
-* @return null
-*/
-function listdiraux($dir, &$files) {
- $handle = opendir($dir);
- while (($file = readdir($handle)) !== false) {
- if ($file == '.' || $file == '..') {
- continue;
- }
-
- if (preg_match('/v6$/',$file))
- /*
- * This is only v5 documentation
- */
+* @return void
+*/
+function listdiraux($dir, &$files)
+{
+ $handle = opendir($dir);
+ while (($file = readdir($handle)) !== false) {
+ if ($file == '.' || $file == '..') {
continue;
-
- $filepath = $dir == '.' ? $file : $dir . '/' . $file;
- if (is_link($filepath))
- continue;
- if (is_file($filepath))
- $files[] = $filepath;
- else if (is_dir($filepath))
- listdiraux($filepath, $files);
- }
- closedir($handle);
-}
+ }
+
+ // Exclude internal use namespaces
+ if (preg_match('/^(?:admin|playground|wiki)/', $file)) {
+ continue;
+ }
+
+ // This is only v5 documentation
+ if (preg_match('/v6$/', $file)) {
+ continue;
+ }
+
+ $filepath = $dir == '.' ? $file : $dir . '/' . $file;
+ if (is_link($filepath)) {
+ continue;
+ }
+ if (is_file($filepath)) {
+ $files[] = $filepath;
+ } else {
+ if (is_dir($filepath)) {
+ listdiraux($filepath, $files);
+ }
+ }
+ }
+ closedir($handle);
+}
+
/*
* Clean up the documentation directory from prior use
*/
-if (is_dir('documentation'))
- deltree('documentation');
-mkdir('documentation');
+if (is_dir($target_dir)) {
+ if(!deltree($target_dir)) {
+ echo "ERROR: unable to remove target directory '$target_dir'\n";
+ die(1);
+ }
+}
+mkdir($target_dir);
-$files = listdir('documentation-base');
-sort($files, SORT_LOCALE_STRING);
+$files = listdir($source_dir);
+if (!$files) {
+ echo "ERROR: Source directory '$source_dir' not found, not accessible or empty\n";
+ die(1);
+}
+sort($files, SORT_LOCALE_STRING);
/*
-* Loop through files in documentation-base directory, creating a mirror
-* structure in documentation, and applying the post-process rules defined
-* below
+* Loop through files in source directory, creating a mirror structure
+* in target directory, and applying the post-process rules defined below
*/
-foreach ($files as $f) {
+foreach ($files as $f) {
- $r = str_replace('documentation-base','documentation',$f);
- $dList = explode ('/',$r);
+ $r = str_replace($source_dir, $target_dir, $f);
+ $dList = explode('/', $r);
$titleList = $dList;
/*
* Get rid of the initial directory
*/
array_shift($titleList);
-
- $depth = count($dList) -2;
+
+ $depth = count($dList) - 2;
$dSlash = '';
- while(count($dList) > 1)
- {
+ while (count($dList) > 1) {
$dSlash .= array_shift($dList) . '/';
- if (!is_dir($dSlash))
+ if (!is_dir($dSlash)) {
mkdir($dSlash);
+ }
}
- if (!is_file($f))
+ if (!is_file($f)) {
continue;
- if (substr($f,-4) <> 'html')
- {
+ }
+ if (substr($f, -4) <> 'html') {
/*
* An image or something else, copy unmodified
*/
- copy ($f,$r);
+ copy($f, $r);
continue;
}
-
- $prepend = str_repeat('../',$depth);
-
+
+ $prepend = str_repeat('../', $depth);
+
$doc = new DOMDocument();
@$doc->loadHTMLFile($f);
-
+
/*
* Remove Page Tools Group
*/
$xpath = new DOMXPath($doc);
-
+
/*
* Remove Top Menu Tools Group, and add a link to the ADOdb site
*/
$nodes = $xpath->query("//div[@class='tools group']");
- foreach($nodes as $node) {
+ foreach ($nodes as $node) {
$pn = $node->parentNode;
$pn->removeChild($node);
- $newChild = $doc->createElement('div','');
+ $newChild = $doc->createElement('div');
$newDiv = $pn->appendChild($newChild);
- $newDiv->setAttribute('style','text-align:right');
- $newChild = $doc->createElement('a','ADOdb Web Site');
+ $newDiv->setAttribute('style', 'text-align:right');
+ $newChild = $doc->createElement('a', 'ADOdb Web Site');
$newA = $newDiv->appendChild($newChild);
- $newA->setAttribute('href','https://adodb.org');
- }
-
+ $newA->setAttribute('href', 'https://adodb.org');
+ }
+
/*
* Remove Trace
*/
$nodes = $xpath->query("//div[@class='breadcrumbs']");
- foreach($nodes as $node) {
+ foreach ($nodes as $node) {
$node->parentNode->removeChild($node);
- }
-
+ }
+
/*
* Remove Side Menu Tools Group
*/
$nodes = $xpath->query("//div[@id='dokuwiki__pagetools']");
- foreach($nodes as $node) {
+ foreach ($nodes as $node) {
$node->parentNode->removeChild($node);
- }
-
+ }
+
/*
* Fix main links
*/
$nodes = $xpath->query("//a[@class='wikilink1']");
- foreach($nodes as $node) {
- $n = $node->getAttribute('title');
- $p = $prepend . str_replace(':','/',$n) . '.html';
+ foreach ($nodes as $node) {
+ $n = $node->getAttribute('title');
+ $p = $prepend . str_replace(':', '/', $n) . '.html';
$node->setAttribute('href', $p);
- }
-
+ }
+
/*
* Fix In Page links
*/
$nodes = $xpath->query("//a[@class='wikilink2']");
- foreach($nodes as $node) {
- $n = $node->getAttribute('title');
- $p = $prepend . str_replace(':','/',$n) . '.html';
+ foreach ($nodes as $node) {
+ $n = $node->getAttribute('title');
+ $p = $prepend . str_replace(':', '/', $n) . '.html';
$node->setAttribute('href', $p);
- }
-
+ }
+
/*
* Make Graphic point to first page. This will break if the image size
* ever changes.
*/
$corePage = $prepend . '/index.html';
$nodes = $xpath->query("//img[@width='176']");
- foreach($nodes as $node) {
+ foreach ($nodes as $node) {
$node->parentNode->setAttribute('href', $corePage);
- }
-
+ }
+
/*
* Change title of page
*/
$nodes = $xpath->query("//title");
- foreach($nodes as $node) {
-
-
- $docTitle = implode(':',$titleList);
- $docTitle = str_replace('.html','',$docTitle);
- $pn = $node->parentNode;
+ foreach ($nodes as $node) {
+ $docTitle = implode(':', $titleList);
+ $docTitle = str_replace('.html', '', $docTitle);
+ $pn = $node->parentNode;
$pn->removeChild($node);
- $newChild = $doc->createElement('title',$docTitle);
+ $newChild = $doc->createElement('title', $docTitle);
$pn->appendChild($newChild);
-
- }
-
+ }
+
$doc->saveHTMLFile($r);
-
- echo $r, "\n";
+
+ echo $r, "\n";
}
+
/*
* Now remove the original index and replace it with the hardcopy documentation one
*/
-unlink ('documentation/index.html');
-rename('documentation/adodb_index.html','documentation/index.html');
+unlink ($target_dir . '/index.html');
+rename($target_dir . '/adodb_index.html',$target_dir . '/index.html');
/*
* We could add in an auto zip and upload here, but this is a good place to
diff --git a/scripts/uploadrelease.py b/scripts/uploadrelease.py
index 7d801eed..812a479b 100755
--- a/scripts/uploadrelease.py
+++ b/scripts/uploadrelease.py
@@ -21,18 +21,19 @@ See the LICENSE.md file distributed with this source code for details.
@author Damien Regad
"""
-from distutils.version import LooseVersion
import getopt
import getpass
import glob
import json
import os
-from os import path
import re
-import requests
import subprocess
import sys
-import yaml
+from os import path
+
+import requests
+
+from adodbutil import env
# Directories and files to exclude from release tarballs
@@ -53,7 +54,6 @@ long_options = ["help", "user=", "dry-run", "skip-upload"]
# Global flags
dry_run = False
-api_key = ''
username = getpass.getuser()
release_path = ''
skip_upload = False
@@ -129,7 +129,7 @@ def get_release_version():
try:
version = re.search(
- r"^adodb-([\d]+\.[\d]+\.[\d]+)(-(alpha|beta|rc)\.[\d]+)?\.zip$",
+ r"^adodb-(\d+\.\d+\.\d+)(-(alpha|beta|rc)\.\d+)?\.zip$",
zipfile
).group(1)
except AttributeError:
@@ -165,36 +165,11 @@ def sourceforge_target_dir(version):
# Keep only X.Y (discard patch number and pre-release suffix)
short_version = version.split('-')[0].rsplit('.', 1)[0]
- if LooseVersion(version) >= LooseVersion('5.21'):
- directory += "adodb-" + short_version
- else:
- directory += "adodb-{}-for-php5".format(short_version.replace('.', ''))
+ directory += "adodb-" + short_version
return directory
-def load_env():
- """
- Load environment from env.yml config file.
- """
- global api_key
-
- # Load the config file
- env_file = path.join(path.dirname(path.abspath(__file__)), 'env.yml')
- try:
- stream = open(env_file, 'r')
- y = yaml.safe_load(stream)
- except IOError:
- print("ERROR: Environment file {} not found".format(env_file))
- sys.exit(3)
- except yaml.parser.ParserError as e:
- print("ERROR: Invalid Environment file")
- print(e)
- sys.exit(3)
-
- api_key = y['api_key']
-
-
def process_command_line():
"""
Retrieve command-line options and set global variables accordingly.
@@ -261,7 +236,7 @@ def upload_release_files():
def set_sourceforge_file_info():
- global api_key, dry_run
+ global dry_run
print("Updating uploaded files information")
@@ -288,7 +263,7 @@ def set_sourceforge_file_info():
url = path.join(base_url, file)
payload = {
'default': defaults,
- 'api_key': api_key
+ 'api_key': env.sf_api_key
}
if dry_run:
req = requests.Request('PUT', url, headers=headers, params=payload)
@@ -314,7 +289,6 @@ def main():
# Start upload process
print("ADOdb release upload script")
- load_env()
process_command_line()
global skip_upload
diff --git a/session/adodb-session2.php b/session/adodb-session2.php
index 19793960..3a03f989 100644
--- a/session/adodb-session2.php
+++ b/session/adodb-session2.php
@@ -315,8 +315,9 @@ class ADODB_Session {
/**
* Get/Set garbage collection function.
*
- * @param callable $expire_notify Function name
- * @return callable|false
+ * @param array $expire_notify [Expired Session ref, Callback function]
+ *
+ * @return array|false
*/
static function expireNotify($expire_notify = null)
{
@@ -560,6 +561,22 @@ class ADODB_Session {
}
/**
+ * Returns a MySQL "CAST(... AS BINARY)" function for the given value.
+ *
+ * For other DB types, the value is returned as-is.
+ *
+ * @param string $value
+ * @return string
+ */
+ static protected function castBinary(string $value): string
+ {
+ if (self::isConnectionMysql()) {
+ return "CAST($value AS BINARY)";
+ }
+ return $value;
+ }
+
+ /**
* Check if Session Connection's DB type is PostgreSQL.
*
* @return bool
@@ -711,17 +728,17 @@ class ADODB_Session {
return '';
}
- $binary = ADODB_Session::isConnectionMysql() ? '/*! BINARY */' : '';
-
global $ADODB_SESSION_SELECT_FIELDS;
if (!isset($ADODB_SESSION_SELECT_FIELDS)) $ADODB_SESSION_SELECT_FIELDS = 'sessdata';
- $sql = "SELECT $ADODB_SESSION_SELECT_FIELDS FROM $table WHERE sesskey = $binary ".$conn->Param(0)." AND expiry >= " . $conn->sysTimeStamp;
+ $sql = "SELECT $ADODB_SESSION_SELECT_FIELDS FROM $table "
+ . "WHERE sesskey = " . self::castBinary($conn->Param(0))
+ . " AND expiry >= " . $conn->sysTimeStamp;
/* Lock code does not work as it needs to hold transaction within whole page, and we don't know if
developer has committed elsewhere... :(
*/
#if (ADODB_Session::Lock())
- # $rs = $conn->RowLock($table, "$binary sesskey = $qkey AND expiry >= " . time(), sessdata);
+ # $rs = $conn->RowLock($table, "sesskey = " . self::castBinary($qkey). " AND expiry >= " . time(), sessdata);
#else
$rs = $conn->Execute($sql, array($key));
//ADODB_Session::_dumprs($rs);
@@ -782,8 +799,7 @@ class ADODB_Session {
$sysTimeStamp = $conn->sysTimeStamp;
$expiry = $conn->OffsetDate($lifetime/(24*3600),$sysTimeStamp);
-
- $binary = ADODB_Session::isConnectionMysql() ? '/*! BINARY */' : '';
+ $expireref = $expire_notify ? $GLOBALS[$expire_notify[0]] ?? '' : '';
// crc32 optimization since adodb 2.1
// now we only update expiry date, thx to sebastian thom in adodb 2.32
@@ -792,19 +808,10 @@ class ADODB_Session {
echo '<p>Session: Only updating date - crc32 not changed</p>';
}
- $expirevar = '';
- if ($expire_notify) {
- $var = reset($expire_notify);
- global $$var;
- if (isset($$var)) {
- $expirevar = $$var;
- }
- }
-
$sql = "UPDATE $table SET expiry = $expiry, expireref=" . $conn->Param('0')
- . ", modified = $sysTimeStamp WHERE sesskey = $binary " . $conn->Param('1')
+ . ", modified = $sysTimeStamp WHERE sesskey = " . self::castBinary($conn->Param('1'))
. " AND expiry >= $sysTimeStamp";
- $rs = $conn->Execute($sql,array($expirevar,$key));
+ $rs = $conn->execute($sql,array($expireref, $key));
return true;
}
$val = rawurlencode($oval);
@@ -814,18 +821,12 @@ class ADODB_Session {
}
}
- $expireref = '';
- if ($expire_notify) {
- $var = reset($expire_notify);
- global $$var;
- if (isset($$var)) {
- $expireref = $$var;
- }
- }
-
if (!$clob) {
// no lobs, simply use replace()
- $rs = $conn->Execute("SELECT COUNT(*) AS cnt FROM $table WHERE $binary sesskey = ".$conn->Param(0),array($key));
+ $rs = $conn->execute(
+ "SELECT COUNT(*) AS cnt FROM $table WHERE sesskey = " . self::castBinary($conn->Param(0)),
+ array($key)
+ );
if ($rs) $rs->Close();
if ($rs && reset($rs->fields) > 0) {
@@ -845,7 +846,10 @@ class ADODB_Session {
$conn->StartTrans();
- $rs = $conn->Execute("SELECT COUNT(*) AS cnt FROM $table WHERE $binary sesskey = ".$conn->Param(0),array($key));
+ $rs = $conn->execute(
+ "SELECT COUNT(*) AS cnt FROM $table WHERE sesskey = " . self::castBinary($conn->Param(0)),
+ array($key)
+ );
if ($rs && reset($rs->fields) > 0) {
$sql = "UPDATE $table SET expiry=$expiry, sessdata=$lob_value, expireref= ".$conn->Param(0).",modified=$sysTimeStamp WHERE sesskey = ".$conn->Param('1');
@@ -870,7 +874,7 @@ class ADODB_Session {
// bug in access driver (could be odbc?) means that info is not committed
// properly unless select statement executed in Win2000
if ($conn->databaseType == 'access') {
- $sql = "SELECT sesskey FROM $table WHERE $binary sesskey = $qkey";
+ $sql = "SELECT sesskey FROM $table WHERE sesskey = " . self::castBinary($qkey);
$rs = $conn->Execute($sql);
ADODB_Session::_dumprs($rs);
if ($rs) {
@@ -902,13 +906,11 @@ class ADODB_Session {
if ($debug) $conn->debug = 1;
$qkey = $conn->quote($key);
- $binary = ADODB_Session::isConnectionMysql() ? '/*! BINARY */' : '';
if ($expire_notify) {
- reset($expire_notify);
- $fn = next($expire_notify);
+ $fn = $expire_notify[1];
$savem = $conn->SetFetchMode(ADODB_FETCH_NUM);
- $sql = "SELECT expireref, sesskey FROM $table WHERE sesskey = $binary $qkey";
+ $sql = "SELECT expireref, sesskey FROM $table WHERE sesskey = " . self::castBinary($qkey);
$rs = $conn->Execute($sql);
ADODB_Session::_dumprs($rs);
$conn->SetFetchMode($savem);
@@ -923,7 +925,7 @@ class ADODB_Session {
$rs->Close();
}
- $sql = "DELETE FROM $table WHERE sesskey = $binary $qkey";
+ $sql = "DELETE FROM $table WHERE sesskey = " . self::castBinary($qkey);
$rs = $conn->Execute($sql);
if ($rs) {
$rs->Close();
@@ -958,14 +960,8 @@ class ADODB_Session {
}
$time = $conn->OffsetDate(-$maxlifetime/24/3600,$conn->sysTimeStamp);
- $binary = ADODB_Session::isConnectionMysql() ? '/*! BINARY */' : '';
- if ($expire_notify) {
- reset($expire_notify);
- $fn = next($expire_notify);
- } else {
- $fn = false;
- }
+ $fn = $expire_notify[1] ?? false;
$savem = $conn->SetFetchMode(ADODB_FETCH_NUM);
$sql = "SELECT expireref, sesskey FROM $table WHERE expiry < $time ORDER BY 2"; # add order by to prevent deadlock
@@ -980,7 +976,10 @@ class ADODB_Session {
$ref = $rs->fields[0];
$key = $rs->fields[1];
if ($fn) $fn($ref, $key);
- $conn->Execute("DELETE FROM $table WHERE sesskey = $binary " . $conn->Param('0'), array($key));
+ $conn->execute(
+ "DELETE FROM $table WHERE sesskey = " . self::castBinary($conn->Param('0') ),
+ array($key)
+ );
$rs->MoveNext();
$ccnt += 1;
if ($tr && $ccnt % $COMMITNUM == 0) {
diff --git a/session/old/adodb-cryptsession.php b/session/old/adodb-cryptsession.php
deleted file mode 100644
index 6616de3d..00000000
--- a/session/old/adodb-cryptsession.php
+++ /dev/null
@@ -1,331 +0,0 @@
-<?php
-/**
- * ADOdb Session Management
- *
- * This file provides PHP4 session management using the ADODB database
- * wrapper library.
- *
- * @deprecated
- *
- * This file is part of ADOdb, a Database Abstraction Layer library for PHP.
- *
- * @package ADOdb
- * @link https://adodb.org Project's web site and documentation
- * @link https://github.com/ADOdb/ADOdb Source code and issue tracker
- *
- * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause
- * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option,
- * any later version. This means you can use it in proprietary products.
- * See the LICENSE.md file distributed with this source code for details.
- * @license BSD-3-Clause
- * @license LGPL-2.1-or-later
- *
- * @copyright 2000-2013 John Lim
- * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community
- */
-/*
- Example
- =======
-
- include('adodb.inc.php');
- #---------------------------------#
- include('adodb-cryptsession.php');
- #---------------------------------#
- session_start();
- session_register('AVAR');
- $_SESSION['AVAR'] += 1;
- print "
--- \$_SESSION['AVAR']={$_SESSION['AVAR']}</p>";
-
-
- Installation
- ============
- 1. Create a new database in MySQL or Access "sessions" like
-so:
-
- create table sessions (
- SESSKEY char(32) not null,
- EXPIRY int(11) unsigned not null,
- EXPIREREF varchar(64),
- DATA CLOB,
- primary key (sesskey)
- );
-
- 2. Then define the following parameters. You can either modify
- this file, or define them before this file is included:
-
- $ADODB_SESSION_DRIVER='database driver, eg. mysql or ibase';
- $ADODB_SESSION_CONNECT='server to connect to';
- $ADODB_SESSION_USER ='user';
- $ADODB_SESSION_PWD ='password';
- $ADODB_SESSION_DB ='database';
- $ADODB_SESSION_TBL = 'sessions'
-
- 3. Recommended is PHP 4.0.2 or later. There are documented
-session bugs in earlier versions of PHP.
-
-*/
-
-
-include_once('crypt.inc.php');
-
-if (!defined('_ADODB_LAYER')) {
- include (dirname(__FILE__).'/adodb.inc.php');
-}
-
- /* if database time and system time is difference is greater than this, then give warning */
- define('ADODB_SESSION_SYNCH_SECS',60);
-
-if (!defined('ADODB_SESSION')) {
-
- define('ADODB_SESSION',1);
-
-GLOBAL $ADODB_SESSION_CONNECT,
- $ADODB_SESSION_DRIVER,
- $ADODB_SESSION_USER,
- $ADODB_SESSION_PWD,
- $ADODB_SESSION_DB,
- $ADODB_SESS_CONN,
- $ADODB_SESS_LIFE,
- $ADODB_SESS_DEBUG,
- $ADODB_SESS_INSERT,
- $ADODB_SESSION_EXPIRE_NOTIFY,
- $ADODB_SESSION_TBL;
-
- //$ADODB_SESS_DEBUG = true;
-
- /* SET THE FOLLOWING PARAMETERS */
-if (empty($ADODB_SESSION_DRIVER)) {
- $ADODB_SESSION_DRIVER='mysql';
- $ADODB_SESSION_CONNECT='localhost';
- $ADODB_SESSION_USER ='root';
- $ADODB_SESSION_PWD ='';
- $ADODB_SESSION_DB ='xphplens_2';
-}
-
-if (empty($ADODB_SESSION_TBL)){
- $ADODB_SESSION_TBL = 'sessions';
-}
-
-if (empty($ADODB_SESSION_EXPIRE_NOTIFY)) {
- $ADODB_SESSION_EXPIRE_NOTIFY = false;
-}
-
-function ADODB_Session_Key()
-{
-$ADODB_CRYPT_KEY = 'CRYPTED ADODB SESSIONS ROCK!';
-
- /* USE THIS FUNCTION TO CREATE THE ENCRYPTION KEY FOR CRYPTED SESSIONS */
- /* Crypt the used key, $ADODB_CRYPT_KEY as key and session_ID as SALT */
- return crypt($ADODB_CRYPT_KEY, session_ID());
-}
-
-$ADODB_SESS_LIFE = ini_get('session.gc_maxlifetime');
-if ($ADODB_SESS_LIFE <= 1) {
- // bug in PHP 4.0.3 pl 1 -- how about other versions?
- //print "<h3>Session Error: PHP.INI setting <i>session.gc_maxlifetime</i>not set: $ADODB_SESS_LIFE</h3>";
- $ADODB_SESS_LIFE=1440;
-}
-
-function adodb_sess_open($save_path, $session_name)
-{
-GLOBAL $ADODB_SESSION_CONNECT,
- $ADODB_SESSION_DRIVER,
- $ADODB_SESSION_USER,
- $ADODB_SESSION_PWD,
- $ADODB_SESSION_DB,
- $ADODB_SESS_CONN,
- $ADODB_SESS_DEBUG;
-
- $ADODB_SESS_INSERT = false;
-
- if (isset($ADODB_SESS_CONN)) return true;
-
- $ADODB_SESS_CONN = ADONewConnection($ADODB_SESSION_DRIVER);
- if (!empty($ADODB_SESS_DEBUG)) {
- $ADODB_SESS_CONN->debug = true;
- print" conn=$ADODB_SESSION_CONNECT user=$ADODB_SESSION_USER pwd=$ADODB_SESSION_PWD db=$ADODB_SESSION_DB ";
- }
- return $ADODB_SESS_CONN->PConnect($ADODB_SESSION_CONNECT,
- $ADODB_SESSION_USER,$ADODB_SESSION_PWD,$ADODB_SESSION_DB);
-
-}
-
-function adodb_sess_close()
-{
-global $ADODB_SESS_CONN;
-
- if ($ADODB_SESS_CONN) $ADODB_SESS_CONN->Close();
- return true;
-}
-
-function adodb_sess_read($key)
-{
-$Crypt = new MD5Crypt;
-global $ADODB_SESS_CONN,$ADODB_SESS_INSERT,$ADODB_SESSION_TBL;
- $rs = $ADODB_SESS_CONN->Execute("SELECT data FROM $ADODB_SESSION_TBL WHERE sesskey = '$key' AND expiry >= " . time());
- if ($rs) {
- if ($rs->EOF) {
- $ADODB_SESS_INSERT = true;
- $v = '';
- } else {
- // Decrypt session data
- $v = rawurldecode($Crypt->Decrypt(reset($rs->fields), ADODB_Session_Key()));
- }
- $rs->Close();
- return $v;
- }
- else $ADODB_SESS_INSERT = true;
-
- return '';
-}
-
-function adodb_sess_write($key, $val)
-{
-$Crypt = new MD5Crypt;
- global $ADODB_SESS_INSERT,$ADODB_SESS_CONN, $ADODB_SESS_LIFE, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY;
-
- $expiry = time() + $ADODB_SESS_LIFE;
-
- // encrypt session data..
- $val = $Crypt->Encrypt(rawurlencode($val), ADODB_Session_Key());
-
- $arr = array('sesskey' => $key, 'expiry' => $expiry, 'data' => $val);
- if ($ADODB_SESSION_EXPIRE_NOTIFY) {
- $var = reset($ADODB_SESSION_EXPIRE_NOTIFY);
- global $$var;
- $arr['expireref'] = $$var;
- }
- $rs = $ADODB_SESS_CONN->Replace($ADODB_SESSION_TBL,
- $arr,
- 'sesskey',$autoQuote = true);
-
- if (!$rs) {
- ADOConnection::outp( '
--- Session Replace: '.$ADODB_SESS_CONN->ErrorMsg().'</p>',false);
- } else {
- // bug in access driver (could be odbc?) means that info is not committed
- // properly unless select statement executed in Win2000
-
- if ($ADODB_SESS_CONN->databaseType == 'access') $rs = $ADODB_SESS_CONN->Execute("select sesskey from $ADODB_SESSION_TBL WHERE sesskey='$key'");
- }
- return isset($rs);
-}
-
-function adodb_sess_destroy($key)
-{
- global $ADODB_SESS_CONN, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY;
-
- if ($ADODB_SESSION_EXPIRE_NOTIFY) {
- reset($ADODB_SESSION_EXPIRE_NOTIFY);
- $fn = next($ADODB_SESSION_EXPIRE_NOTIFY);
- $savem = $ADODB_SESS_CONN->SetFetchMode(ADODB_FETCH_NUM);
- $rs = $ADODB_SESS_CONN->Execute("SELECT expireref,sesskey FROM $ADODB_SESSION_TBL WHERE sesskey='$key'");
- $ADODB_SESS_CONN->SetFetchMode($savem);
- if ($rs) {
- $ADODB_SESS_CONN->BeginTrans();
- while (!$rs->EOF) {
- $ref = $rs->fields[0];
- $key = $rs->fields[1];
- $fn($ref,$key);
- $del = $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE sesskey='$key'");
- $rs->MoveNext();
- }
- $ADODB_SESS_CONN->CommitTrans();
- }
- } else {
- $qry = "DELETE FROM $ADODB_SESSION_TBL WHERE sesskey = '$key'";
- $rs = $ADODB_SESS_CONN->Execute($qry);
- }
- return $rs ? true : false;
-}
-
-
-function adodb_sess_gc($maxlifetime) {
- global $ADODB_SESS_CONN, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY,$ADODB_SESS_DEBUG;
-
- if ($ADODB_SESSION_EXPIRE_NOTIFY) {
- reset($ADODB_SESSION_EXPIRE_NOTIFY);
- $fn = next($ADODB_SESSION_EXPIRE_NOTIFY);
- $savem = $ADODB_SESS_CONN->SetFetchMode(ADODB_FETCH_NUM);
- $t = time();
- $rs = $ADODB_SESS_CONN->Execute("SELECT expireref,sesskey FROM $ADODB_SESSION_TBL WHERE expiry < $t");
- $ADODB_SESS_CONN->SetFetchMode($savem);
- if ($rs) {
- $ADODB_SESS_CONN->BeginTrans();
- while (!$rs->EOF) {
- $ref = $rs->fields[0];
- $key = $rs->fields[1];
- $fn($ref,$key);
- //$del = $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE sesskey='$key'");
- $rs->MoveNext();
- }
- $rs->Close();
-
- $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE expiry < $t");
- $ADODB_SESS_CONN->CommitTrans();
- }
- } else {
- $qry = "DELETE FROM $ADODB_SESSION_TBL WHERE expiry < " . time();
- $ADODB_SESS_CONN->Execute($qry);
- }
-
- // suggested by Cameron, "GaM3R" <gamr@outworld.cx>
- if (defined('ADODB_SESSION_OPTIMIZE'))
- {
- global $ADODB_SESSION_DRIVER;
-
- switch( $ADODB_SESSION_DRIVER ) {
- case 'mysql':
- case 'mysqlt':
- $opt_qry = 'OPTIMIZE TABLE '.$ADODB_SESSION_TBL;
- break;
- case 'postgresql':
- case 'postgresql7':
- $opt_qry = 'VACUUM '.$ADODB_SESSION_TBL;
- break;
- }
- }
-
- if ($ADODB_SESS_CONN->dataProvider === 'oci8') $sql = 'select TO_CHAR('.($ADODB_SESS_CONN->sysTimeStamp).', \'RRRR-MM-DD HH24:MI:SS\') from '. $ADODB_SESSION_TBL;
- else $sql = 'select '.$ADODB_SESS_CONN->sysTimeStamp.' from '. $ADODB_SESSION_TBL;
-
- $rs = $ADODB_SESS_CONN->SelectLimit($sql,1);
- if ($rs && !$rs->EOF) {
-
- $dbts = reset($rs->fields);
- $rs->Close();
- $dbt = $ADODB_SESS_CONN->UnixTimeStamp($dbts);
- $t = time();
- if (abs($dbt - $t) >= ADODB_SESSION_SYNCH_SECS) {
- $msg =
- __FILE__.": Server time for webserver {$_SERVER['HTTP_HOST']} not in synch with database: database=$dbt ($dbts), webserver=$t (diff=".(abs($dbt-$t)/3600)." hrs)";
- error_log($msg);
- if ($ADODB_SESS_DEBUG) ADOConnection::outp("
--- $msg</p>");
- }
- }
-
- return true;
-}
-
-session_set_save_handler(
- "adodb_sess_open",
- "adodb_sess_close",
- "adodb_sess_read",
- "adodb_sess_write",
- "adodb_sess_destroy",
- "adodb_sess_gc");
-}
-
-/* TEST SCRIPT -- UNCOMMENT */
-/*
-if (0) {
-
- session_start();
- session_register('AVAR');
- $_SESSION['AVAR'] += 1;
- print "
--- \$_SESSION['AVAR']={$_SESSION['AVAR']}</p>";
-}
-*/
diff --git a/session/old/adodb-session-clob.php b/session/old/adodb-session-clob.php
deleted file mode 100644
index 864fdfd7..00000000
--- a/session/old/adodb-session-clob.php
+++ /dev/null
@@ -1,457 +0,0 @@
-<?php
-/**
- * ADOdb Session Management
- *
- * This file provides PHP4 session management using the ADODB database
- * wrapper library.
- *
- * @deprecated
- *
- * This file is part of ADOdb, a Database Abstraction Layer library for PHP.
- *
- * @package ADOdb
- * @link https://adodb.org Project's web site and documentation
- * @link https://github.com/ADOdb/ADOdb Source code and issue tracker
- *
- * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause
- * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option,
- * any later version. This means you can use it in proprietary products.
- * See the LICENSE.md file distributed with this source code for details.
- * @license BSD-3-Clause
- * @license LGPL-2.1-or-later
- *
- * @copyright 2000-2013 John Lim
- * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community
- */
-/*
- Example
- =======
-
- include('adodb.inc.php');
- include('adodb-session.php');
- session_start();
- session_register('AVAR');
- $_SESSION['AVAR'] += 1;
- print "
--- \$_SESSION['AVAR']={$_SESSION['AVAR']}</p>";
-
-To force non-persistent connections, call adodb_session_open first before session_start():
-
- include('adodb.inc.php');
- include('adodb-session.php');
- adodb_session_open(false,false,false);
- session_start();
- session_register('AVAR');
- $_SESSION['AVAR'] += 1;
- print "
--- \$_SESSION['AVAR']={$_SESSION['AVAR']}</p>";
-
-
- Installation
- ============
- 1. Create this table in your database (syntax might vary depending on your db):
-
- create table sessions (
- SESSKEY char(32) not null,
- EXPIRY int(11) unsigned not null,
- EXPIREREF varchar(64),
- DATA CLOB,
- primary key (sesskey)
- );
-
-
- 2. Then define the following parameters in this file:
- $ADODB_SESSION_DRIVER='database driver, eg. mysql or ibase';
- $ADODB_SESSION_CONNECT='server to connect to';
- $ADODB_SESSION_USER ='user';
- $ADODB_SESSION_PWD ='password';
- $ADODB_SESSION_DB ='database';
- $ADODB_SESSION_TBL = 'sessions'
- $ADODB_SESSION_USE_LOBS = false; (or, if you wanna use CLOBS (= 'CLOB') or ( = 'BLOB')
-
- 3. Recommended is PHP 4.1.0 or later. There are documented
- session bugs in earlier versions of PHP.
-
- 4. If you want to receive notifications when a session expires, then
- you can tag a session with an EXPIREREF, and before the session
- record is deleted, we can call a function that will pass the EXPIREREF
- as the first parameter, and the session key as the second parameter.
-
- To do this, define a notification function, say NotifyFn:
-
- function NotifyFn($expireref, $sesskey)
- {
- }
-
- Then you need to define a global variable $ADODB_SESSION_EXPIRE_NOTIFY.
- This is an array with 2 elements, the first being the name of the variable
- you would like to store in the EXPIREREF field, and the 2nd is the
- notification function's name.
-
- In this example, we want to be notified when a user's session
- has expired, so we store the user id in the global variable $USERID,
- store this value in the EXPIREREF field:
-
- $ADODB_SESSION_EXPIRE_NOTIFY = array('USERID','NotifyFn');
-
- Then when the NotifyFn is called, we are passed the $USERID as the first
- parameter, eg. NotifyFn($userid, $sesskey).
-*/
-
-if (!defined('_ADODB_LAYER')) {
- include (dirname(__FILE__).'/adodb.inc.php');
-}
-
-if (!defined('ADODB_SESSION')) {
-
- define('ADODB_SESSION',1);
-
- /* if database time and system time is difference is greater than this, then give warning */
- define('ADODB_SESSION_SYNCH_SECS',60);
-
-/****************************************************************************************\
- Global definitions
-\****************************************************************************************/
-GLOBAL $ADODB_SESSION_CONNECT,
- $ADODB_SESSION_DRIVER,
- $ADODB_SESSION_USER,
- $ADODB_SESSION_PWD,
- $ADODB_SESSION_DB,
- $ADODB_SESS_CONN,
- $ADODB_SESS_LIFE,
- $ADODB_SESS_DEBUG,
- $ADODB_SESSION_EXPIRE_NOTIFY,
- $ADODB_SESSION_CRC,
- $ADODB_SESSION_USE_LOBS,
- $ADODB_SESSION_TBL;
-
- if (!isset($ADODB_SESSION_USE_LOBS)) $ADODB_SESSION_USE_LOBS = 'CLOB';
-
- $ADODB_SESS_LIFE = ini_get('session.gc_maxlifetime');
- if ($ADODB_SESS_LIFE <= 1) {
- // bug in PHP 4.0.3 pl 1 -- how about other versions?
- //print "<h3>Session Error: PHP.INI setting <i>session.gc_maxlifetime</i>not set: $ADODB_SESS_LIFE</h3>";
- $ADODB_SESS_LIFE=1440;
- }
- $ADODB_SESSION_CRC = false;
- //$ADODB_SESS_DEBUG = true;
-
- //////////////////////////////////
- /* SET THE FOLLOWING PARAMETERS */
- //////////////////////////////////
-
- if (empty($ADODB_SESSION_DRIVER)) {
- $ADODB_SESSION_DRIVER='mysql';
- $ADODB_SESSION_CONNECT='localhost';
- $ADODB_SESSION_USER ='root';
- $ADODB_SESSION_PWD ='';
- $ADODB_SESSION_DB ='xphplens_2';
- }
-
- if (empty($ADODB_SESSION_EXPIRE_NOTIFY)) {
- $ADODB_SESSION_EXPIRE_NOTIFY = false;
- }
- // Made table name configurable - by David Johnson djohnson@inpro.net
- if (empty($ADODB_SESSION_TBL)){
- $ADODB_SESSION_TBL = 'sessions';
- }
-
-
- // defaulting $ADODB_SESSION_USE_LOBS
- if (!isset($ADODB_SESSION_USE_LOBS) || empty($ADODB_SESSION_USE_LOBS)) {
- $ADODB_SESSION_USE_LOBS = false;
- }
-
- /*
- $ADODB_SESS['driver'] = $ADODB_SESSION_DRIVER;
- $ADODB_SESS['connect'] = $ADODB_SESSION_CONNECT;
- $ADODB_SESS['user'] = $ADODB_SESSION_USER;
- $ADODB_SESS['pwd'] = $ADODB_SESSION_PWD;
- $ADODB_SESS['db'] = $ADODB_SESSION_DB;
- $ADODB_SESS['life'] = $ADODB_SESS_LIFE;
- $ADODB_SESS['debug'] = $ADODB_SESS_DEBUG;
-
- $ADODB_SESS['debug'] = $ADODB_SESS_DEBUG;
- $ADODB_SESS['table'] = $ADODB_SESS_TBL;
- */
-
-/****************************************************************************************\
- Create the connection to the database.
-
- If $ADODB_SESS_CONN already exists, reuse that connection
-\****************************************************************************************/
-function adodb_sess_open($save_path, $session_name,$persist=true)
-{
-GLOBAL $ADODB_SESS_CONN;
- if (isset($ADODB_SESS_CONN)) return true;
-
-GLOBAL $ADODB_SESSION_CONNECT,
- $ADODB_SESSION_DRIVER,
- $ADODB_SESSION_USER,
- $ADODB_SESSION_PWD,
- $ADODB_SESSION_DB,
- $ADODB_SESS_DEBUG;
-
- // cannot use & below - do not know why...
- $ADODB_SESS_CONN = ADONewConnection($ADODB_SESSION_DRIVER);
- if (!empty($ADODB_SESS_DEBUG)) {
- $ADODB_SESS_CONN->debug = true;
- ADOConnection::outp( " conn=$ADODB_SESSION_CONNECT user=$ADODB_SESSION_USER pwd=$ADODB_SESSION_PWD db=$ADODB_SESSION_DB ");
- }
- if ($persist) $ok = $ADODB_SESS_CONN->PConnect($ADODB_SESSION_CONNECT,
- $ADODB_SESSION_USER,$ADODB_SESSION_PWD,$ADODB_SESSION_DB);
- else $ok = $ADODB_SESS_CONN->Connect($ADODB_SESSION_CONNECT,
- $ADODB_SESSION_USER,$ADODB_SESSION_PWD,$ADODB_SESSION_DB);
-
- if (!$ok) ADOConnection::outp( "
--- Session: connection failed</p>",false);
-}
-
-/****************************************************************************************\
- Close the connection
-\****************************************************************************************/
-function adodb_sess_close()
-{
-global $ADODB_SESS_CONN;
-
- if ($ADODB_SESS_CONN) $ADODB_SESS_CONN->Close();
- return true;
-}
-
-/****************************************************************************************\
- Slurp in the session variables and return the serialized string
-\****************************************************************************************/
-function adodb_sess_read($key)
-{
-global $ADODB_SESS_CONN,$ADODB_SESSION_TBL,$ADODB_SESSION_CRC;
-
- $rs = $ADODB_SESS_CONN->Execute("SELECT data FROM $ADODB_SESSION_TBL WHERE sesskey = '$key' AND expiry >= " . time());
- if ($rs) {
- if ($rs->EOF) {
- $v = '';
- } else
- $v = rawurldecode(reset($rs->fields));
-
- $rs->Close();
-
- // new optimization adodb 2.1
- $ADODB_SESSION_CRC = strlen($v).crc32($v);
-
- return $v;
- }
-
- return ''; // thx to Jorma Tuomainen, webmaster#wizactive.com
-}
-
-/****************************************************************************************\
- Write the serialized data to a database.
-
- If the data has not been modified since adodb_sess_read(), we do not write.
-\****************************************************************************************/
-function adodb_sess_write($key, $val)
-{
- global
- $ADODB_SESS_CONN,
- $ADODB_SESS_LIFE,
- $ADODB_SESSION_TBL,
- $ADODB_SESS_DEBUG,
- $ADODB_SESSION_CRC,
- $ADODB_SESSION_EXPIRE_NOTIFY,
- $ADODB_SESSION_DRIVER, // added
- $ADODB_SESSION_USE_LOBS; // added
-
- $expiry = time() + $ADODB_SESS_LIFE;
-
- // crc32 optimization since adodb 2.1
- // now we only update expiry date, thx to sebastian thom in adodb 2.32
- if ($ADODB_SESSION_CRC !== false && $ADODB_SESSION_CRC == strlen($val).crc32($val)) {
- if ($ADODB_SESS_DEBUG) echo "
--- Session: Only updating date - crc32 not changed</p>";
- $qry = "UPDATE $ADODB_SESSION_TBL SET expiry=$expiry WHERE sesskey='$key' AND expiry >= " . time();
- $rs = $ADODB_SESS_CONN->Execute($qry);
- return true;
- }
- $val = rawurlencode($val);
-
- $arr = array('sesskey' => $key, 'expiry' => $expiry, 'data' => $val);
- if ($ADODB_SESSION_EXPIRE_NOTIFY) {
- $var = reset($ADODB_SESSION_EXPIRE_NOTIFY);
- global $$var;
- $arr['expireref'] = $$var;
- }
-
-
- if ($ADODB_SESSION_USE_LOBS === false) { // no lobs, simply use replace()
- $rs = $ADODB_SESS_CONN->Replace($ADODB_SESSION_TBL,$arr, 'sesskey',$autoQuote = true);
- if (!$rs) {
- $err = $ADODB_SESS_CONN->ErrorMsg();
- }
- } else {
- // what value shall we insert/update for lob row?
- switch ($ADODB_SESSION_DRIVER) {
- // empty_clob or empty_lob for oracle dbs
- case "oracle":
- case "oci8":
- case "oci8po":
- case "oci805":
- $lob_value = sprintf("empty_%s()", strtolower($ADODB_SESSION_USE_LOBS));
- break;
-
- // null for all other
- default:
- $lob_value = "null";
- break;
- }
-
- // do we insert or update? => as for sesskey
- $res = $ADODB_SESS_CONN->Execute("select count(*) as cnt from $ADODB_SESSION_TBL where sesskey = '$key'");
- if ($res && reset($res->fields) > 0) {
- $qry = sprintf("update %s set expiry = %d, data = %s where sesskey = '%s'", $ADODB_SESSION_TBL, $expiry, $lob_value, $key);
- } else {
- // insert
- $qry = sprintf("insert into %s (sesskey, expiry, data) values ('%s', %d, %s)", $ADODB_SESSION_TBL, $key, $expiry, $lob_value);
- }
-
- $err = "";
- $rs1 = $ADODB_SESS_CONN->Execute($qry);
- if (!$rs1) {
- $err .= $ADODB_SESS_CONN->ErrorMsg()."\n";
- }
- $rs2 = $ADODB_SESS_CONN->UpdateBlob($ADODB_SESSION_TBL, 'data', $val, "sesskey='$key'", strtoupper($ADODB_SESSION_USE_LOBS));
- if (!$rs2) {
- $err .= $ADODB_SESS_CONN->ErrorMsg()."\n";
- }
- $rs = ($rs1 && $rs2) ? true : false;
- }
-
- if (!$rs) {
- ADOConnection::outp( '
--- Session Replace: '.nl2br($err).'</p>',false);
- } else {
- // bug in access driver (could be odbc?) means that info is not committed
- // properly unless select statement executed in Win2000
- if ($ADODB_SESS_CONN->databaseType == 'access')
- $rs = $ADODB_SESS_CONN->Execute("select sesskey from $ADODB_SESSION_TBL WHERE sesskey='$key'");
- }
- return !empty($rs);
-}
-
-function adodb_sess_destroy($key)
-{
- global $ADODB_SESS_CONN, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY;
-
- if ($ADODB_SESSION_EXPIRE_NOTIFY) {
- reset($ADODB_SESSION_EXPIRE_NOTIFY);
- $fn = next($ADODB_SESSION_EXPIRE_NOTIFY);
- $savem = $ADODB_SESS_CONN->SetFetchMode(ADODB_FETCH_NUM);
- $rs = $ADODB_SESS_CONN->Execute("SELECT expireref,sesskey FROM $ADODB_SESSION_TBL WHERE sesskey='$key'");
- $ADODB_SESS_CONN->SetFetchMode($savem);
- if ($rs) {
- $ADODB_SESS_CONN->BeginTrans();
- while (!$rs->EOF) {
- $ref = $rs->fields[0];
- $key = $rs->fields[1];
- $fn($ref,$key);
- $del = $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE sesskey='$key'");
- $rs->MoveNext();
- }
- $ADODB_SESS_CONN->CommitTrans();
- }
- } else {
- $qry = "DELETE FROM $ADODB_SESSION_TBL WHERE sesskey = '$key'";
- $rs = $ADODB_SESS_CONN->Execute($qry);
- }
- return $rs ? true : false;
-}
-
-function adodb_sess_gc($maxlifetime)
-{
- global $ADODB_SESS_DEBUG, $ADODB_SESS_CONN, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY;
-
- if ($ADODB_SESSION_EXPIRE_NOTIFY) {
- reset($ADODB_SESSION_EXPIRE_NOTIFY);
- $fn = next($ADODB_SESSION_EXPIRE_NOTIFY);
- $savem = $ADODB_SESS_CONN->SetFetchMode(ADODB_FETCH_NUM);
- $t = time();
- $rs = $ADODB_SESS_CONN->Execute("SELECT expireref,sesskey FROM $ADODB_SESSION_TBL WHERE expiry < $t");
- $ADODB_SESS_CONN->SetFetchMode($savem);
- if ($rs) {
- $ADODB_SESS_CONN->BeginTrans();
- while (!$rs->EOF) {
- $ref = $rs->fields[0];
- $key = $rs->fields[1];
- $fn($ref,$key);
- $del = $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE sesskey='$key'");
- $rs->MoveNext();
- }
- $rs->Close();
-
- //$ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE expiry < $t");
- $ADODB_SESS_CONN->CommitTrans();
-
- }
- } else {
- $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE expiry < " . time());
-
- if ($ADODB_SESS_DEBUG) ADOConnection::outp("
--- <b>Garbage Collection</b>: $qry</p>");
- }
- // suggested by Cameron, "GaM3R" <gamr@outworld.cx>
- if (defined('ADODB_SESSION_OPTIMIZE')) {
- global $ADODB_SESSION_DRIVER;
-
- switch( $ADODB_SESSION_DRIVER ) {
- case 'mysql':
- case 'mysqlt':
- $opt_qry = 'OPTIMIZE TABLE '.$ADODB_SESSION_TBL;
- break;
- case 'postgresql':
- case 'postgresql7':
- $opt_qry = 'VACUUM '.$ADODB_SESSION_TBL;
- break;
- }
- if (!empty($opt_qry)) {
- $ADODB_SESS_CONN->Execute($opt_qry);
- }
- }
- if ($ADODB_SESS_CONN->dataProvider === 'oci8') $sql = 'select TO_CHAR('.($ADODB_SESS_CONN->sysTimeStamp).', \'RRRR-MM-DD HH24:MI:SS\') from '. $ADODB_SESSION_TBL;
- else $sql = 'select '.$ADODB_SESS_CONN->sysTimeStamp.' from '. $ADODB_SESSION_TBL;
-
- $rs = $ADODB_SESS_CONN->SelectLimit($sql,1);
- if ($rs && !$rs->EOF) {
-
- $dbts = reset($rs->fields);
- $rs->Close();
- $dbt = $ADODB_SESS_CONN->UnixTimeStamp($dbts);
- $t = time();
- if (abs($dbt - $t) >= ADODB_SESSION_SYNCH_SECS) {
- $msg =
- __FILE__.": Server time for webserver {$_SERVER['HTTP_HOST']} not in synch with database: database=$dbt ($dbts), webserver=$t (diff=".(abs($dbt-$t)/3600)." hrs)";
- error_log($msg);
- if ($ADODB_SESS_DEBUG) ADOConnection::outp("
--- $msg</p>");
- }
- }
-
- return true;
-}
-
-session_set_save_handler(
- "adodb_sess_open",
- "adodb_sess_close",
- "adodb_sess_read",
- "adodb_sess_write",
- "adodb_sess_destroy",
- "adodb_sess_gc");
-}
-
-/* TEST SCRIPT -- UNCOMMENT */
-
-if (0) {
-
- session_start();
- session_register('AVAR');
- $_SESSION['AVAR'] += 1;
- ADOConnection::outp( "
--- \$_SESSION['AVAR']={$_SESSION['AVAR']}</p>",false);
-}
diff --git a/session/old/adodb-session.php b/session/old/adodb-session.php
deleted file mode 100644
index 5fd43abc..00000000
--- a/session/old/adodb-session.php
+++ /dev/null
@@ -1,449 +0,0 @@
-<?php
-/**
- * ADOdb Session Management
- *
- * This file provides PHP4 session management using the ADODB database
- * wrapper library.
- *
- * @deprecated
- *
- * This file is part of ADOdb, a Database Abstraction Layer library for PHP.
- *
- * @package ADOdb
- * @link https://adodb.org Project's web site and documentation
- * @link https://github.com/ADOdb/ADOdb Source code and issue tracker
- *
- * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause
- * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option,
- * any later version. This means you can use it in proprietary products.
- * See the LICENSE.md file distributed with this source code for details.
- * @license BSD-3-Clause
- * @license LGPL-2.1-or-later
- *
- * @copyright 2000-2013 John Lim
- * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community
- */
-
-/*
- Example
- =======
-
- include('adodb.inc.php');
- include('adodb-session.php');
- session_start();
- session_register('AVAR');
- $_SESSION['AVAR'] += 1;
- print "
--- \$_SESSION['AVAR']={$_SESSION['AVAR']}</p>";
-
-To force non-persistent connections, call adodb_session_open first before session_start():
-
- include('adodb.inc.php');
- include('adodb-session.php');
- adodb_sess_open(false,false,false);
- session_start();
- session_register('AVAR');
- $_SESSION['AVAR'] += 1;
- print "
--- \$_SESSION['AVAR']={$_SESSION['AVAR']}</p>";
-
-
- Installation
- ============
- 1. Create this table in your database (syntax might vary depending on your db):
-
- create table sessions (
- SESSKEY char(32) not null,
- EXPIRY int(11) unsigned not null,
- EXPIREREF varchar(64),
- DATA text not null,
- primary key (sesskey)
- );
-
- For oracle:
- create table sessions (
- SESSKEY char(32) not null,
- EXPIRY DECIMAL(16) not null,
- EXPIREREF varchar(64),
- DATA varchar(4000) not null,
- primary key (sesskey)
- );
-
-
- 2. Then define the following parameters. You can either modify
- this file, or define them before this file is included:
-
- $ADODB_SESSION_DRIVER='database driver, eg. mysql or ibase';
- $ADODB_SESSION_CONNECT='server to connect to';
- $ADODB_SESSION_USER ='user';
- $ADODB_SESSION_PWD ='password';
- $ADODB_SESSION_DB ='database';
- $ADODB_SESSION_TBL = 'sessions'
-
- 3. Recommended is PHP 4.1.0 or later. There are documented
- session bugs in earlier versions of PHP.
-
- 4. If you want to receive notifications when a session expires, then
- you can tag a session with an EXPIREREF, and before the session
- record is deleted, we can call a function that will pass the EXPIREREF
- as the first parameter, and the session key as the second parameter.
-
- To do this, define a notification function, say NotifyFn:
-
- function NotifyFn($expireref, $sesskey)
- {
- }
-
- Then you need to define a global variable $ADODB_SESSION_EXPIRE_NOTIFY.
- This is an array with 2 elements, the first being the name of the variable
- you would like to store in the EXPIREREF field, and the 2nd is the
- notification function's name.
-
- In this example, we want to be notified when a user's session
- has expired, so we store the user id in the global variable $USERID,
- store this value in the EXPIREREF field:
-
- $ADODB_SESSION_EXPIRE_NOTIFY = array('USERID','NotifyFn');
-
- Then when the NotifyFn is called, we are passed the $USERID as the first
- parameter, eg. NotifyFn($userid, $sesskey).
-*/
-
-if (!defined('_ADODB_LAYER')) {
- include (dirname(__FILE__).'/adodb.inc.php');
-}
-
-if (!defined('ADODB_SESSION')) {
-
- define('ADODB_SESSION',1);
-
- /* if database time and system time is difference is greater than this, then give warning */
- define('ADODB_SESSION_SYNCH_SECS',60);
-
- /*
- Thanks Joe Li. See PHPLens Issue No: 11487&x=1
-*/
-function adodb_session_regenerate_id()
-{
- $conn = ADODB_Session::_conn();
- if (!$conn) return false;
-
- $old_id = session_id();
- if (function_exists('session_regenerate_id')) {
- session_regenerate_id();
- } else {
- session_id(md5(uniqid(rand(), true)));
- $ck = session_get_cookie_params();
- setcookie(session_name(), session_id(), false, $ck['path'], $ck['domain'], $ck['secure']);
- //@session_start();
- }
- $new_id = session_id();
- $ok = $conn->Execute('UPDATE '. ADODB_Session::table(). ' SET sesskey='. $conn->qstr($new_id). ' WHERE sesskey='.$conn->qstr($old_id));
-
- /* it is possible that the update statement fails due to a collision */
- if (!$ok) {
- session_id($old_id);
- if (empty($ck)) $ck = session_get_cookie_params();
- setcookie(session_name(), session_id(), false, $ck['path'], $ck['domain'], $ck['secure']);
- return false;
- }
-
- return true;
-}
-
-/****************************************************************************************\
- Global definitions
-\****************************************************************************************/
-GLOBAL $ADODB_SESSION_CONNECT,
- $ADODB_SESSION_DRIVER,
- $ADODB_SESSION_USER,
- $ADODB_SESSION_PWD,
- $ADODB_SESSION_DB,
- $ADODB_SESS_CONN,
- $ADODB_SESS_LIFE,
- $ADODB_SESS_DEBUG,
- $ADODB_SESSION_EXPIRE_NOTIFY,
- $ADODB_SESSION_CRC,
- $ADODB_SESSION_TBL;
-
-
- $ADODB_SESS_LIFE = ini_get('session.gc_maxlifetime');
- if ($ADODB_SESS_LIFE <= 1) {
- // bug in PHP 4.0.3 pl 1 -- how about other versions?
- //print "<h3>Session Error: PHP.INI setting <i>session.gc_maxlifetime</i>not set: $ADODB_SESS_LIFE</h3>";
- $ADODB_SESS_LIFE=1440;
- }
- $ADODB_SESSION_CRC = false;
- //$ADODB_SESS_DEBUG = true;
-
- //////////////////////////////////
- /* SET THE FOLLOWING PARAMETERS */
- //////////////////////////////////
-
- if (empty($ADODB_SESSION_DRIVER)) {
- $ADODB_SESSION_DRIVER='mysql';
- $ADODB_SESSION_CONNECT='localhost';
- $ADODB_SESSION_USER ='root';
- $ADODB_SESSION_PWD ='';
- $ADODB_SESSION_DB ='xphplens_2';
- }
-
- if (empty($ADODB_SESSION_EXPIRE_NOTIFY)) {
- $ADODB_SESSION_EXPIRE_NOTIFY = false;
- }
- // Made table name configurable - by David Johnson djohnson@inpro.net
- if (empty($ADODB_SESSION_TBL)){
- $ADODB_SESSION_TBL = 'sessions';
- }
-
- /*
- $ADODB_SESS['driver'] = $ADODB_SESSION_DRIVER;
- $ADODB_SESS['connect'] = $ADODB_SESSION_CONNECT;
- $ADODB_SESS['user'] = $ADODB_SESSION_USER;
- $ADODB_SESS['pwd'] = $ADODB_SESSION_PWD;
- $ADODB_SESS['db'] = $ADODB_SESSION_DB;
- $ADODB_SESS['life'] = $ADODB_SESS_LIFE;
- $ADODB_SESS['debug'] = $ADODB_SESS_DEBUG;
-
- $ADODB_SESS['debug'] = $ADODB_SESS_DEBUG;
- $ADODB_SESS['table'] = $ADODB_SESS_TBL;
- */
-
-/****************************************************************************************\
- Create the connection to the database.
-
- If $ADODB_SESS_CONN already exists, reuse that connection
-\****************************************************************************************/
-function adodb_sess_open($save_path, $session_name,$persist=true)
-{
-GLOBAL $ADODB_SESS_CONN;
- if (isset($ADODB_SESS_CONN)) return true;
-
-GLOBAL $ADODB_SESSION_CONNECT,
- $ADODB_SESSION_DRIVER,
- $ADODB_SESSION_USER,
- $ADODB_SESSION_PWD,
- $ADODB_SESSION_DB,
- $ADODB_SESS_DEBUG;
-
- // cannot use & below - do not know why...
- $ADODB_SESS_CONN = ADONewConnection($ADODB_SESSION_DRIVER);
- if (!empty($ADODB_SESS_DEBUG)) {
- $ADODB_SESS_CONN->debug = true;
- ADOConnection::outp( " conn=$ADODB_SESSION_CONNECT user=$ADODB_SESSION_USER pwd=$ADODB_SESSION_PWD db=$ADODB_SESSION_DB ");
- }
- if ($persist) $ok = $ADODB_SESS_CONN->PConnect($ADODB_SESSION_CONNECT,
- $ADODB_SESSION_USER,$ADODB_SESSION_PWD,$ADODB_SESSION_DB);
- else $ok = $ADODB_SESS_CONN->Connect($ADODB_SESSION_CONNECT,
- $ADODB_SESSION_USER,$ADODB_SESSION_PWD,$ADODB_SESSION_DB);
-
- if (!$ok) ADOConnection::outp( "
--- Session: connection failed</p>",false);
-}
-
-/****************************************************************************************\
- Close the connection
-\****************************************************************************************/
-function adodb_sess_close()
-{
-global $ADODB_SESS_CONN;
-
- if ($ADODB_SESS_CONN) $ADODB_SESS_CONN->Close();
- return true;
-}
-
-/****************************************************************************************\
- Slurp in the session variables and return the serialized string
-\****************************************************************************************/
-function adodb_sess_read($key)
-{
-global $ADODB_SESS_CONN,$ADODB_SESSION_TBL,$ADODB_SESSION_CRC;
-
- $rs = $ADODB_SESS_CONN->Execute("SELECT data FROM $ADODB_SESSION_TBL WHERE sesskey = '$key' AND expiry >= " . time());
- if ($rs) {
- if ($rs->EOF) {
- $v = '';
- } else
- $v = rawurldecode(reset($rs->fields));
-
- $rs->Close();
-
- // new optimization adodb 2.1
- $ADODB_SESSION_CRC = strlen($v).crc32($v);
-
- return $v;
- }
-
- return ''; // thx to Jorma Tuomainen, webmaster#wizactive.com
-}
-
-/****************************************************************************************\
- Write the serialized data to a database.
-
- If the data has not been modified since adodb_sess_read(), we do not write.
-\****************************************************************************************/
-function adodb_sess_write($key, $val)
-{
- global
- $ADODB_SESS_CONN,
- $ADODB_SESS_LIFE,
- $ADODB_SESSION_TBL,
- $ADODB_SESS_DEBUG,
- $ADODB_SESSION_CRC,
- $ADODB_SESSION_EXPIRE_NOTIFY;
-
- $expiry = time() + $ADODB_SESS_LIFE;
-
- // crc32 optimization since adodb 2.1
- // now we only update expiry date, thx to sebastian thom in adodb 2.32
- if ($ADODB_SESSION_CRC !== false && $ADODB_SESSION_CRC == strlen($val).crc32($val)) {
- if ($ADODB_SESS_DEBUG) echo "
--- Session: Only updating date - crc32 not changed</p>";
- $qry = "UPDATE $ADODB_SESSION_TBL SET expiry=$expiry WHERE sesskey='$key' AND expiry >= " . time();
- $rs = $ADODB_SESS_CONN->Execute($qry);
- return true;
- }
- $val = rawurlencode($val);
-
- $arr = array('sesskey' => $key, 'expiry' => $expiry, 'data' => $val);
- if ($ADODB_SESSION_EXPIRE_NOTIFY) {
- $var = reset($ADODB_SESSION_EXPIRE_NOTIFY);
- global $$var;
- $arr['expireref'] = $$var;
- }
- $rs = $ADODB_SESS_CONN->Replace($ADODB_SESSION_TBL,$arr,
- 'sesskey',$autoQuote = true);
-
- if (!$rs) {
- ADOConnection::outp( '
--- Session Replace: '.$ADODB_SESS_CONN->ErrorMsg().'</p>',false);
- } else {
- // bug in access driver (could be odbc?) means that info is not committed
- // properly unless select statement executed in Win2000
- if ($ADODB_SESS_CONN->databaseType == 'access')
- $rs = $ADODB_SESS_CONN->Execute("select sesskey from $ADODB_SESSION_TBL WHERE sesskey='$key'");
- }
- return !empty($rs);
-}
-
-function adodb_sess_destroy($key)
-{
- global $ADODB_SESS_CONN, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY;
-
- if ($ADODB_SESSION_EXPIRE_NOTIFY) {
- reset($ADODB_SESSION_EXPIRE_NOTIFY);
- $fn = next($ADODB_SESSION_EXPIRE_NOTIFY);
- $savem = $ADODB_SESS_CONN->SetFetchMode(ADODB_FETCH_NUM);
- $rs = $ADODB_SESS_CONN->Execute("SELECT expireref,sesskey FROM $ADODB_SESSION_TBL WHERE sesskey='$key'");
- $ADODB_SESS_CONN->SetFetchMode($savem);
- if ($rs) {
- $ADODB_SESS_CONN->BeginTrans();
- while (!$rs->EOF) {
- $ref = $rs->fields[0];
- $key = $rs->fields[1];
- $fn($ref,$key);
- $del = $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE sesskey='$key'");
- $rs->MoveNext();
- }
- $ADODB_SESS_CONN->CommitTrans();
- }
- } else {
- $qry = "DELETE FROM $ADODB_SESSION_TBL WHERE sesskey = '$key'";
- $rs = $ADODB_SESS_CONN->Execute($qry);
- }
- return $rs ? true : false;
-}
-
-function adodb_sess_gc($maxlifetime)
-{
- global $ADODB_SESS_DEBUG, $ADODB_SESS_CONN, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY;
-
- if ($ADODB_SESSION_EXPIRE_NOTIFY) {
- reset($ADODB_SESSION_EXPIRE_NOTIFY);
- $fn = next($ADODB_SESSION_EXPIRE_NOTIFY);
- $savem = $ADODB_SESS_CONN->SetFetchMode(ADODB_FETCH_NUM);
- $t = time();
- $rs = $ADODB_SESS_CONN->Execute("SELECT expireref,sesskey FROM $ADODB_SESSION_TBL WHERE expiry < $t");
- $ADODB_SESS_CONN->SetFetchMode($savem);
- if ($rs) {
- $ADODB_SESS_CONN->BeginTrans();
- while (!$rs->EOF) {
- $ref = $rs->fields[0];
- $key = $rs->fields[1];
- $fn($ref,$key);
- $del = $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE sesskey='$key'");
- $rs->MoveNext();
- }
- $rs->Close();
-
- $ADODB_SESS_CONN->CommitTrans();
-
- }
- } else {
- $qry = "DELETE FROM $ADODB_SESSION_TBL WHERE expiry < " . time();
- $ADODB_SESS_CONN->Execute($qry);
-
- if ($ADODB_SESS_DEBUG) ADOConnection::outp("
--- <b>Garbage Collection</b>: $qry</p>");
- }
- // suggested by Cameron, "GaM3R" <gamr@outworld.cx>
- if (defined('ADODB_SESSION_OPTIMIZE')) {
- global $ADODB_SESSION_DRIVER;
-
- switch( $ADODB_SESSION_DRIVER ) {
- case 'mysql':
- case 'mysqlt':
- $opt_qry = 'OPTIMIZE TABLE '.$ADODB_SESSION_TBL;
- break;
- case 'postgresql':
- case 'postgresql7':
- $opt_qry = 'VACUUM '.$ADODB_SESSION_TBL;
- break;
- }
- if (!empty($opt_qry)) {
- $ADODB_SESS_CONN->Execute($opt_qry);
- }
- }
- if ($ADODB_SESS_CONN->dataProvider === 'oci8') $sql = 'select TO_CHAR('.($ADODB_SESS_CONN->sysTimeStamp).', \'RRRR-MM-DD HH24:MI:SS\') from '. $ADODB_SESSION_TBL;
- else $sql = 'select '.$ADODB_SESS_CONN->sysTimeStamp.' from '. $ADODB_SESSION_TBL;
-
- $rs = $ADODB_SESS_CONN->SelectLimit($sql,1);
- if ($rs && !$rs->EOF) {
-
- $dbts = reset($rs->fields);
- $rs->Close();
- $dbt = $ADODB_SESS_CONN->UnixTimeStamp($dbts);
- $t = time();
-
- if (abs($dbt - $t) >= ADODB_SESSION_SYNCH_SECS) {
-
- $msg =
- __FILE__.": Server time for webserver {$_SERVER['HTTP_HOST']} not in synch with database: database=$dbt ($dbts), webserver=$t (diff=".(abs($dbt-$t)/3600)." hrs)";
- error_log($msg);
- if ($ADODB_SESS_DEBUG) ADOConnection::outp("
--- $msg</p>");
- }
- }
-
- return true;
-}
-
-session_set_save_handler(
- "adodb_sess_open",
- "adodb_sess_close",
- "adodb_sess_read",
- "adodb_sess_write",
- "adodb_sess_destroy",
- "adodb_sess_gc");
-}
-
-/* TEST SCRIPT -- UNCOMMENT */
-
-if (0) {
-
- session_start();
- session_register('AVAR');
- $_SESSION['AVAR'] += 1;
- ADOConnection::outp( "
--- \$_SESSION['AVAR']={$_SESSION['AVAR']}</p>",false);
-}
diff --git a/session/old/crypt.inc.php b/session/old/crypt.inc.php
deleted file mode 100644
index 089e24a0..00000000
--- a/session/old/crypt.inc.php
+++ /dev/null
@@ -1,83 +0,0 @@
-<?php
-/**
- * ADOdb Session Management
- *
- * @deprecated
- *
- * This file is part of ADOdb, a Database Abstraction Layer library for PHP.
- *
- * @package ADOdb
- * @link https://adodb.org Project's web site and documentation
- * @link https://github.com/ADOdb/ADOdb Source code and issue tracker
- *
- * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause
- * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option,
- * any later version. This means you can use it in proprietary products.
- * See the LICENSE.md file distributed with this source code for details.
- * @license BSD-3-Clause
- * @license LGPL-2.1-or-later
- *
- * @copyright 2000-2013 John Lim
- * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community
- * @author Ari Kuorikoski <ari.kuorikoski@finebyte.com>
- */
-
-class MD5Crypt{
- function keyED($txt,$encrypt_key)
- {
- $encrypt_key = md5($encrypt_key);
- $ctr=0;
- $tmp = "";
- for ($i=0;$i<strlen($txt);$i++){
- if ($ctr==strlen($encrypt_key)) $ctr=0;
- $tmp.= substr($txt,$i,1) ^ substr($encrypt_key,$ctr,1);
- $ctr++;
- }
- return $tmp;
- }
-
- function Encrypt($txt,$key)
- {
- $encrypt_key = md5(rand(0,32000));
- $ctr=0;
- $tmp = "";
- for ($i=0;$i<strlen($txt);$i++)
- {
- if ($ctr==strlen($encrypt_key)) $ctr=0;
- $tmp.= substr($encrypt_key,$ctr,1) .
- (substr($txt,$i,1) ^ substr($encrypt_key,$ctr,1));
- $ctr++;
- }
- return base64_encode($this->keyED($tmp,$key));
- }
-
- function Decrypt($txt,$key)
- {
- $txt = $this->keyED(base64_decode($txt),$key);
- $tmp = "";
- for ($i=0;$i<strlen($txt);$i++){
- $md5 = substr($txt,$i,1);
- $i++;
- $tmp.= (substr($txt,$i,1) ^ $md5);
- }
- return $tmp;
- }
-
- function RandPass()
- {
- $randomPassword = "";
- for($i=0;$i<8;$i++)
- {
- $randnumber = rand(48,120);
-
- while (($randnumber >= 58 && $randnumber <= 64) || ($randnumber >= 91 && $randnumber <= 96))
- {
- $randnumber = rand(48,120);
- }
-
- $randomPassword .= chr($randnumber);
- }
- return $randomPassword;
- }
-
-}
diff --git a/tests/PdoDriverTest.php b/tests/PdoDriverTest.php
new file mode 100644
index 00000000..c22b291e
--- /dev/null
+++ b/tests/PdoDriverTest.php
@@ -0,0 +1,160 @@
+<?php
+/**
+ * Tests cases for adodb-lib.inc.php
+ *
+ * This file is part of ADOdb, a Database Abstraction Layer library for PHP.
+ *
+ * @package ADOdb
+ * @link https://adodb.org Project's web site and documentation
+ * @link https://github.com/ADOdb/ADOdb Source code and issue tracker
+ *
+ * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause
+ * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option,
+ * any later version. This means you can use it in proprietary products.
+ * See the LICENSE.md file distributed with this source code for details.
+ * @license BSD-3-Clause
+ * @license LGPL-2.1-or-later
+ *
+ * @copyright 2000-2013 John Lim
+ * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community
+ */
+
+use PHPUnit\Framework\TestCase;
+
+require_once dirname(__FILE__) . '/../drivers/adodb-pdo.inc.php';
+
+/**
+ * Class PdoDriverTest.
+ *
+ * Test cases for drivers/adodb-pdo.inc.php
+ */
+class PdoDriverTest extends TestCase
+{
+ /**
+ * Test for {@see ADODB_pdo#containsQuestionMarkPlaceholder)
+ *
+ * @dataProvider providerContainsQuestionMarkPlaceholder
+ */
+ public function testContainsQuestionMarkPlaceholder($result, $sql): void
+ {
+ $method = new ReflectionMethod('ADODB_pdo', 'containsQuestionMarkPlaceholder');
+ $method->setAccessible(true);
+
+ $pdoDriver = new ADODB_pdo();
+ $this->assertSame($result, $method->invoke($pdoDriver, $sql));
+ }
+
+ /**
+ * Data provider for {@see testContainsQuestionMarkPlaceholder()}
+ *
+ * @return array [result, SQL statement]
+ */
+ public function providerContainsQuestionMarkPlaceholder(): array
+ {
+ return [
+ [true, 'SELECT * FROM employees WHERE emp_no = ?;'],
+ [true, 'SELECT * FROM employees WHERE emp_no = ?'],
+ [true, 'SELECT * FROM employees WHERE emp_no=?'],
+ [true, 'SELECT * FROM employees WHERE emp_no>?'],
+ [true, 'SELECT * FROM employees WHERE emp_no<?'],
+ [true, 'SELECT * FROM employees WHERE emp_no>=?'],
+ [true, 'SELECT * FROM employees WHERE emp_no<=?'],
+ [true, 'SELECT * FROM employees WHERE emp_no<>?'],
+ [true, 'SELECT * FROM employees WHERE emp_no!=?'],
+ [true, 'SELECT * FROM employees WHERE emp_no IN (?)'],
+ [true, 'SELECT * FROM employees WHERE emp_no=`?` OR emp_no=?'],
+ [true, 'UPDATE employees SET emp_name=? WHERE emp_no=?'],
+
+ [false, 'SELECT * FROM employees'],
+ [false, 'SELECT * FROM employees WHERE emp_no=`?`'],
+ [false, 'SELECT * FROM employees WHERE emp_no=??'],
+ [false, 'SELECT * FROM employees WHERE emp_no=:emp_no'],
+ ];
+ }
+
+ /**
+ * Test for {@see ADODB_pdo#conformToBindParameterStyle)
+ *
+ * @dataProvider providerConformToBindParameterStyle
+ */
+ public function testConformToBindParameterStyle($expected, $inputarr, $bindParameterStyle, $sql): void
+ {
+ $method = new ReflectionMethod('ADODB_pdo', 'conformToBindParameterStyle');
+ $method->setAccessible(true);
+
+ $pdoDriver = new ADODB_pdo();
+ $pdoDriver->bindParameterStyle = $bindParameterStyle;
+ $this->assertSame($expected, $method->invoke($pdoDriver, $sql, $inputarr));
+ }
+
+ /**
+ * Data provider for {@see testConformToBindParameterStyle()}
+ *
+ * @return array [expected, inputarr, bindParameterStyle, SQL statement]
+ */
+ public function providerConformToBindParameterStyle(): array
+ {
+ return [
+ [
+ [1, 2, 3],
+ [1, 2, 3],
+ ADODB_pdo::BIND_USE_QUESTION_MARKS,
+ null
+ ],
+ [
+ [1, 2, 3],
+ ['a' => 1, 'b' => 2, 'c' => 3],
+ ADODB_pdo::BIND_USE_QUESTION_MARKS,
+ null
+ ],
+ [
+ [1, 2, 3],
+ [1, 2, 3],
+ ADODB_pdo::BIND_USE_NAMED_PARAMETERS,
+ null
+ ],
+ [
+ ['a' => 1, 'b' => 2, 'c' => 3],
+ ['a' => 1, 'b' => 2, 'c' => 3],
+ ADODB_pdo::BIND_USE_NAMED_PARAMETERS,
+ null
+ ],
+ [
+ [1, 2, 3],
+ [1, 2, 3],
+ ADODB_pdo::BIND_USE_BOTH,
+ 'SELECT * FROM employees WHERE emp_no = ?'
+ ],
+ [
+ [1, 2, 3],
+ ['a' => 1, 'b' => 2, 'c' => 3],
+ ADODB_pdo::BIND_USE_BOTH,
+ 'SELECT * FROM employees WHERE emp_no = ?'
+ ],
+ [
+ [1, 2, 3],
+ [1, 2, 3],
+ ADODB_pdo::BIND_USE_BOTH,
+ 'SELECT * FROM employees WHERE emp_no = :id'
+ ],
+ [
+ ['a' => 1, 'b' => 2, 'c' => 3],
+ ['a' => 1, 'b' => 2, 'c' => 3],
+ ADODB_pdo::BIND_USE_BOTH,
+ 'SELECT * FROM employees WHERE emp_no = :id'
+ ],
+ [
+ [1, 2, 3],
+ [1, 2, 3],
+ 9999, // Incorrect values result in default behavior.
+ null
+ ],
+ [
+ [1, 2, 3],
+ ['a' => 1, 'b' => 2, 'c' => 3],
+ 9999, // Incorrect values result in default behavior.
+ null
+ ],
+ ];
+ }
+}
diff --git a/tests/test.php b/tests/test.php
index 08a2e301..37709004 100644
--- a/tests/test.php
+++ b/tests/test.php
@@ -1764,9 +1764,6 @@ Test <a href=test4.php>GetInsertSQL/GetUpdateSQL</a> &nbsp;
<a href=test-perf.php>Perf Monitor</a><p>
<?php
-
-include_once('../adodb-time.inc.php');
-if (isset($_GET['time'])) adodb_date_test();
flush();
include_once('./testdatabases.inc.php');
diff --git a/tests/time.php b/tests/time.php
deleted file mode 100644
index 8760ccd4..00000000
--- a/tests/time.php
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-/**
- * ADOdb tests - Time.
- *
- * This file is part of ADOdb, a Database Abstraction Layer library for PHP.
- *
- * @package ADOdb
- * @link https://adodb.org Project's web site and documentation
- * @link https://github.com/ADOdb/ADOdb Source code and issue tracker
- *
- * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause
- * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option,
- * any later version. This means you can use it in proprietary products.
- * See the LICENSE.md file distributed with this source code for details.
- * @license BSD-3-Clause
- * @license LGPL-2.1-or-later
- *
- * @copyright 2000-2013 John Lim
- * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community
- */
-
-include_once('../adodb-time.inc.php');
-adodb_date_test();
-?>
-<?php
-//require("adodb-time.inc.php");
-
-$datestring = "2063-12-24"; // string normally from mySQL
-$stringArray = explode("-", $datestring);
-$date = adodb_mktime(0,0,0,$stringArray[1],$stringArray[2],$stringArray[0]);
-
-$convertedDate = adodb_date("d-M-Y", $date); // converted string to UK style date
-
-echo( "Original: $datestring<br>" );
-echo( "Converted: $convertedDate" ); //why is string returned as one day (3 not 4) less for this example??