Initial commit.

This commit is contained in:
2026-03-10 21:25:26 +08:00
commit 78739bf725
3089 changed files with 472990 additions and 0 deletions

View File

@@ -0,0 +1,628 @@
<?php
// File name: mysql.inc.php
// Description: PHP subroutines to handle MySQL operation
// Date: 2001-02-13
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2001-2008 Pristine Communications
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines with high precedence
require_once "monica/sqlconst.inc.php";
// Referenced subroutines
require_once "monica/errhndl.inc.php";
require_once "monica/getlang.inc.php";
require_once "monica/lninfo.inc.php";
require_once "monica/requri.inc.php";
require_once "monica/sqllogin.inc.php";
// Settings
$_MYSQL_CONN = null;
// xmysql_connect: Connect to the MySQL database
function xmysql_connect($database = null)
{
global $_MYSQL_CONN;
// Connected
if (!is_null($_MYSQL_CONN)) {
return;
}
// Obtain the SQL log-in information
if (is_null($database)) {
if (getenv("MYSQL_DB") !== false) {
$database = getenv("MYSQL_DB");
} elseif (defined("PACKAGE")) {
$database = PACKAGE;
}
}
if (getenv("MYSQL_HOST") !== false) {
$host = getenv("MYSQL_HOST");
} else {
$host = null;
}
// Login with from SQLLOGIN environment variable as a web application
// php-cgi does not have STDIN and STDERR even on console
if (PHP_SAPI != "cli") {
$r = get_sql_login_info(SQL_MYSQL, $database, $host);
// Connect it
$_MYSQL_CONN = mysql_connect($r["MYSQL_HOST"], $r["MYSQL_USER"], $r["MYSQL_PW"]);
if ($_MYSQL_CONN === false) {
$_MYSQL_CONN = null;
trigger_error("Failed connecting to the MySQL server.\n"
. mysql_errno() . " " . mysql_error(), E_USER_ERROR);
}
// Ask the password from the console
} else {
$user = null;
$subseq = false;
set_error_handler("null_error_handler");
$_MYSQL_CONN = mysql_connect();
restore_error_handler();
while ($_MYSQL_CONN === false) {
if ($subseq) {
fprintf(STDERR, "%s\n", $GLOBALS["php_errormsg"]);
sleep(5);
}
// Obtain the current login user
if ( is_null($user)
&& preg_match("/ denied for user '(.+?)'\@'.+?'/", $GLOBALS["php_errormsg"], $m)) {
$user = $m[1];
}
$subseq = true;
// Disable console echo
system("/bin/stty -echo");
fprintf(STDERR, !is_null($user)? "MySQL password for $user: ":
"MySQL password: ");
$passwd = fgets(STDIN);
fprintf(STDERR, "\n");
// Restore console echo status
system("/bin/stty echo");
// STDIN is not available
if ($passwd === false) {
die(THIS_FILE . ": Failed connecting to the PostgreSQL server\n");
}
$passwd = trim($passwd);
set_error_handler("null_error_handler");
$_MYSQL_CONN = mysql_connect(null, null, $passwd);
restore_error_handler();
}
}
// Select the database
$result = mysql_select_db($database);
if ($result === false) {
trigger_error("Failed mysql_select_db(\"$database\").\n"
. mysql_errno() . " " . mysql_error(), E_USER_ERROR);
}
// Set the character set
$charset = defined("SQL_CHARSET")? SQL_CHARSET: "utf8";
$set = "SET NAMES '" . mysql_escape_string($charset) . "';\n";
xmysql_query($set);
return;
}
// xmysql_close: Disconnect from the MySQL database
function xmysql_close()
{
global $_MYSQL_CONN;
if (is_null($_MYSQL_CONN)) {
return;
}
$result = mysql_close($_MYSQL_CONN);
if ($result !== true) {
trigger_error("Failed disconnecting from the MySQL server.\n"
. mysql_errno() . " " . mysql_error(), E_USER_ERROR);
}
$_MYSQL_CONN = null;
return;
}
/////////////////////////
// Concurrency Control: Transactions and Locks
/////////////////////////
$_MYSQL_IN_TRANSACTION = false;
// mysql_begin: Begin a MySQL transaction
function mysql_begin()
{
if (!$GLOBALS["_MYSQL_IN_TRANSACTION"]) {
$begin = "START TRANSACTION;\n";
xmysql_query($begin);
$GLOBALS["_MYSQL_IN_TRANSACTION"] = true;
}
}
// mysql_commit: Commit a MySQL transaction
function mysql_commit()
{
if ($GLOBALS["_MYSQL_IN_TRANSACTION"]) {
$commit = "COMMIT;\n";
xmysql_query($commit);
$GLOBALS["_MYSQL_IN_TRANSACTION"] = false;
}
}
// mysql_rollback: Rollback a MySQL transaction
function mysql_rollback()
{
if ($GLOBALS["_MYSQL_IN_TRANSACTION"]) {
$rollback = "ROLLBACK;\n";
// This generate errors under MyIASM
//xmysql_query($rollback);
mysql_query($rollback);
$GLOBALS["_MYSQL_IN_TRANSACTION"] = false;
}
}
// mysql_lock: MySQL table-locking handler
// We need this to wrok around the stupid MySQL table locking mechanism
// Input: An associative array, where its keys are the tables to lock,
// and its values can be one of the following:
// LOCK_SH: Request a read lock
// LOCK_EX: Request a write lock
// LOCK_UN: Unlock the previously obtained lock
// Or null to unlock everything.
// Return: None. Errors are directed to error handlers
function mysql_lock($newlocks = null)
{
// Keep the current lock table static
static $curlocks = array();
// Save the previous locks
$lastlocks = $curlocks;
// Unlock everything
if (is_null($newlocks)) {
$curlocks = array();
} else {
// Adjust the current lock table
foreach (array_keys($newlocks) as $table) {
switch ($newlocks[$table]) {
case LOCK_SH:
case LOCK_EX:
$curlocks[$table] = $newlocks[$table];
break;
case LOCK_UN:
unset($curlocks[$table]);
break;
default:
trigger_error("Bad SQL lock request: \"$newlocks[$table]\" on table \"$table\".", E_USER_ERROR);
}
}
}
$lockstr = _mysql_locks2str($curlocks);
// Return if nothing is changed
if ($lockstr == _mysql_locks2str($lastlocks)) {
return;
}
// Rollback everything if not committed yet
// LOCK TABLE/UNLOCK TABLE implicitly COMMIT the previous transaction.
// This is bad.
if ($GLOBALS["_MYSQL_IN_TRANSACTION"]) {
mysql_rollback();
}
// Has something to lock
if ($lockstr !== "") {
$locktable = "LOCK TABLES $lockstr;\n";
// Nothing to lock - release all locks
} else {
$locktable = "UNLOCK TABLES;\n";
}
xmysql_query($locktable);
return;
}
// xmysql_query: Do a MySQL query and report the error
function xmysql_query($query)
{
$result = mysql_query($query);
if ($result === false) {
trigger_error("Failed mysql_query().\n$query\n"
. mysql_errno() . " " . mysql_error(), E_USER_ERROR);
}
return $result;
}
// mysql_seek: Move the MySQL result pointer
function mysql_seek($result, $offset)
{
$result = mysql_data_seek($result, $offset);
if ($result === false) {
trigger_error("Failed mysql_data_seek().\n"
. mysql_errno() . " " . mysql_error(), E_USER_ERROR);
}
return $result;
}
// xmysql_fetch_assoc: Return a MySQL row as an associative array
function xmysql_fetch_assoc($result)
{
// Fetch the raw data now
$row = mysql_fetch_assoc($result);
// Return the error
if (!is_array($row)) {
return $row;
}
// Adjust the boolean columns
foreach (mysql_cols_of_type($result, SQL_TYPE_BOOLEAN, SQL_FETCH_ASSOC) as $col) {
$row[$col] = !is_null($row[$col]);
}
// Adjust the integer columns
foreach (mysql_cols_of_type($result, SQL_TYPE_INTEGER, SQL_FETCH_ASSOC) as $col) {
if (!is_null($row[$col])) {
settype($row[$col], "integer");
}
}
// Adjust the big integer columns
foreach (mysql_cols_of_type($result, SQL_TYPE_BIGINT, SQL_FETCH_ASSOC) as $col) {
if ( !is_null($row[$col])
&& $row[$col] >= -2147483647
&& $row[$col] <= 2147483647) {
settype($row[$col], "integer");
}
}
// Adjust the float columns
foreach (mysql_cols_of_type($result, SQL_TYPE_FLOAT, SQL_FETCH_ASSOC) as $col) {
if (!is_null($row[$col])) {
settype($row[$col], "float");
}
}
return $row;
}
// xmysql_fetch_row: Return a MySQL row as an numeric array
function xmysql_fetch_row($result)
{
// Fetch the raw data now
$row = mysql_fetch_row($result);
// Return the error
if (!is_array($row)) {
return $row;
}
// Adjust the boolean columns
foreach (mysql_cols_of_type($result, SQL_TYPE_BOOLEAN, SQL_FETCH_ROW) as $col) {
$row[$col] = !is_null($row[$col]);
}
// Adjust the integer columns
foreach (mysql_cols_of_type($result, SQL_TYPE_INTEGER, SQL_FETCH_ROW) as $col) {
if (!is_null($row[$col])) {
settype($row[$col], "integer");
}
}
// Adjust the big integer columns
foreach (mysql_cols_of_type($result, SQL_TYPE_BIGINT, SQL_FETCH_ROW) as $col) {
if ( !is_null($row[$col])
&& $row[$col] >= -2147483647
&& $row[$col] <= 2147483647) {
settype($row[$col], "integer");
}
}
// Adjust the float columns
foreach (mysql_cols_of_type($result, SQL_TYPE_FLOAT, SQL_FETCH_ROW) as $col) {
if (!is_null($row[$col])) {
settype($row[$col], "float");
}
}
return $row;
}
// mysql_tables: Obtain a list of available MySQL tables
// and report the error
function mysql_tables($db = null)
{
if (is_null($db)) {
$select = "SHOW TABLES;\n";
} else {
$select = "SHOW TABLES FROM $db;\n";
}
$result = xmysql_query($select);
$count = mysql_num_rows($result);
for ($i = 0, $tables = array(); $i < $count; $i++) {
$row = mysql_fetch_row($result);
$tables[] = $row[0];
}
sort($tables);
return $tables;
}
// mysql_cols: Obtain the column list of a MySQL table
function mysql_cols($table)
{
// Cache the result
static $cache = array();
// Return the cache
if (array_key_exists($table, $cache)) {
return $cache[$table];
}
$select = "SHOW COLUMNS FROM $table;\n";
$result = xmysql_query($select);
$count = mysql_num_rows($result);
for ($i = 0, $cache[$table] = array(); $i < $count; $i++) {
$row = mysql_fetch_row($result);
$cache[$table][] = $row[0];
}
return $cache[$table];
}
// mysql_cols_ml: Return a list of multi-lingual columns in a MySQL table
function mysql_cols_ml($table)
{
// Cache the result
static $cache = array();
// Return the cache
if (array_key_exists($table, $cache)) {
return $cache[$table];
}
// Get the columns that have language variants
$cols = mysql_cols($table);
$cache[$table] = array();
$suffix = "_" . getlang(LN_DATABASE);
$len = strlen($suffix);
for ($i = 0; $i < count($cols); $i++) {
// It has a language suffix
if (substr($cols[$i], -$len) == $suffix) {
$cache[$table][] = substr($cols[$i], 0, -$len);
}
}
return $cache[$table];
}
// mysql_cols_nl: Return a list of columns without their multi-lingual
// deviants in a MySQL table
function mysql_cols_nl($table)
{
// Cache the result
static $cache = array();
// Return the cache
if (array_key_exists($table, $cache)) {
return $cache[$table];
}
// Get the columns that have language variants
$cols = mysql_cols($table);
$langcols = mysql_cols_ml($table);
// Remove those language variants
$cache[$table] = array();
for ($i = 0; $i < count($cols); $i++) {
$pos = strrpos($cols[$i], "_");
// No suffix
if ($pos === false) {
$cache[$table][] = $cols[$i];
// Check the prefix
} else {
$prefix = substr($cols[$i], 0, $pos);
// The prefix is one of the language columns
if (in_array($prefix, $langcols)) {
// Not counted yet
if (!in_array($prefix, $cache[$table])) {
$cache[$table][] = $prefix;
}
// An ordinary prefix
} else {
$cache[$table][] = $cols[$i];
}
}
}
return $cache[$table];
}
// mysql_cols_of_type: Return the columns in a certain data type
function mysql_cols_of_type($result, $type, $format = SQL_FETCH_ASSOC)
{
$result_key = _mysql_result_hashkey($result);
// Cache the result
static $cache = array();
// Return the cache
if (array_key_exists($result_key, $cache)) {
return $cache[$result_key][$type][$format];
}
// Check each field type
$count = mysql_num_fields($result);
$cols = array(
SQL_TYPE_BOOLEAN => array(
SQL_FETCH_ASSOC => array(),
SQL_FETCH_ROW => array(),
),
SQL_TYPE_BLOB => array(
SQL_FETCH_ASSOC => array(),
SQL_FETCH_ROW => array(),
),
SQL_TYPE_INTEGER => array(
SQL_FETCH_ASSOC => array(),
SQL_FETCH_ROW => array(),
),
SQL_TYPE_BIGINT => array(
SQL_FETCH_ASSOC => array(),
SQL_FETCH_ROW => array(),
),
SQL_TYPE_FLOAT => array(
SQL_FETCH_ASSOC => array(),
SQL_FETCH_ROW => array(),
),
);
for ($i = 0; $i < $count; $i++) {
$coltype = mysql_field_type($result, $i);
$colname = mysql_field_name($result, $i);
$collen = mysql_field_len($result, $i);
if ($coltype == "string" && $collen == 0) {
$cols[SQL_TYPE_BOOLEAN][SQL_FETCH_ROW][] = $i;
$cols[SQL_TYPE_BOOLEAN][SQL_FETCH_ASSOC][] = $colname;
} elseif ($coltype == "blob") {
$cols[SQL_TYPE_BLOB][SQL_FETCH_ROW][] = $i;
$cols[SQL_TYPE_BLOB][SQL_FETCH_ASSOC][] = $colname;
} elseif ($coltype == "int" && $collen <= 11) {
$cols[SQL_TYPE_INTEGER][SQL_FETCH_ROW][] = $i;
$cols[SQL_TYPE_INTEGER][SQL_FETCH_ASSOC][] = $colname;
} elseif ($coltype == "int" && $collen == 20) {
$cols[SQL_TYPE_BIGINT][SQL_FETCH_ROW][] = $i;
$cols[SQL_TYPE_BIGINT][SQL_FETCH_ASSOC][] = $colname;
} elseif ($coltype == "real") {
$cols[SQL_TYPE_FLOAT][SQL_FETCH_ROW][] = $i;
$cols[SQL_TYPE_FLOAT][SQL_FETCH_ASSOC][] = $colname;
}
}
// Cache it
$cache[$result_key] = $cols;
return $cols[$type][$format];
}
// mysql_col_lens: Obtain the column lengths of a MySQL table
function mysql_col_lens($table)
{
// Cache the result
static $cache = array();
// Return the cache
if (array_key_exists($table, $cache)) {
return $cache[$table];
}
$select = "SELECT * FROM $table LIMIT 1;\n";
$result = xmysql_query($select);
$count = mysql_num_fields($result);
for ($i = 0, $cache[$table] = array(); $i < $count; $i++) {
$cache[$table][mysql_field_name($result, $i)] = mysql_field_len($result, $i);
}
// Hash the multi-lingual columns
$lndb = getlang(LN_DATABASE);
foreach (mysql_cols_ml($table) as $col) {
$cache[$table][$col] = $cache[$table][$col . "_" . $lndb];
}
return $cache[$table];
}
// mysql_strcat: Concatenate strings in MySQL
// MySQL uses the CONCAT() function to concatenate strings
function mysql_strcat()
{
$strs = func_get_args();
return "CONCAT(" . implode(", ", $strs) . ")";
}
// mysql_lastupd: Obtain the last updated time of a list of tables
function mysql_lastupd($tables)
{
// Bounce if no tables supplied
if (is_null($tables) || count($tables) == 0) {
return;
}
// Remove duplicates
$tables = array_values(array_unique($tables));
// Query
$conds = array();
foreach ($tables as $table) {
$conds[] = "tabname='" . mysql_escape_string($table) . "'";
}
$select = "SELECT mtime FROM mtime"
. " WHERE " . implode(" OR ", $conds)
. " ORDER BY mtime DESC LIMIT 1;\n";
$result = xmysql_query($select);
// Bounce if no data found
if (mysql_num_rows($result) != 1) {
return;
}
// Return the result
$row = xmysql_fetch_assoc($result);
return $row["mtime"];
}
// mysql_dbsize: Obtain the size of the database
function mysql_dbsize()
{
$select = "SHOW TABLE STATUS;\n";
$result = xmysql_query($select);
$count = mysql_num_rows($result);
for ($i = 0, $size = 0; $i < $count; $i++) {
$row = xmysql_fetch_row($result);
$size += $row["Data_length"];
}
return $size;
}
// mysql_date: Return date in a predefined format
function mysql_date($expr, $format)
{
switch ($format) {
case SQL_YYYYMMDD:
return "DATE_FORMAT($expr, '%Y%m%d')";
case SQL_YYYY_YYYYMMDD:
return "DATE_FORMAT($expr, '%Y/%Y%m%d')";
case SQL_MM_DD:
return "DATE_FORMAT($expr, '%m-%d')";
case SQL_M_D_EN:
return "DATE_FORMAT($expr, '%c/%e')";
case SQL_M_D_ZHTW:
return "DATE_FORMAT($expr, '%c月%e日')";
case SQL_M_D_DE:
return "DATE_FORMAT($expr, '%e.%c')";
case SQL_HH_MM:
return "TIME_FORMAT($expr, '%H:%i')";
}
}
// mysql_re: Return the MySQL regular expression operator
function mysql_re()
{
return "REGEXP";
}
// _mysql_result_hashkey: Generate a hash key from a MySQL query result
function _mysql_result_hashkey($result)
{
// Use the output of var_dump
ob_start();
var_dump($result);
$key = ob_get_contents();
ob_end_clean();
return $key;
}
// _mysql_locks2str: Convert lock array to SQL text string
function _mysql_locks2str($locks)
{
$reads = array();
$writes = array();
// Adjust the current lock table
foreach (array_keys($locks) as $table) {
switch ($locks[$table]) {
case LOCK_SH:
$reads[] = $table;
break;
case LOCK_EX:
$writes[] = $table;
break;
}
}
sort($reads);
sort($writes);
$phrases = array();
foreach ($writes as $table) {
$phrases[] = "$table WRITE";
}
foreach ($reads as $table) {
$phrases[] = "$table READ";
}
return implode(", ", $phrases);
}
?>