/** * This function is the central function for handling database interaction. * The function can be used for setting up a database connection, for running * a SQL query and for returning query rows. Which of these actions the * function will handle and what the function return data will be, is * determined by the $return function parameter. * * @param $return - What to return. Options are the following constants: * DB_RETURN_CONN a db connection handle * DB_RETURN_QUOTED a quoted parameter * DB_RETURN_RES result resource handle * DB_RETURN_ROW single row as array * DB_RETURN_ROWS all rows as arrays * DB_RETURN_ASSOC single row as associative array * DB_RETURN_ASSOCS all rows as associative arrays * DB_RETURN_VALUE single row, single column * DB_RETURN_ROWCOUNT number of selected rows * DB_RETURN_NEWID new row id for insert query * DB_RETURN_ERROR an error message if the query * failed or NULL if there was no error * DB_CLOSE_CONN close the connection, no return data * * @param $sql - The SQL query to run or the parameter to quote if * DB_RETURN_QUOTED is used. * * @param $keyfield - When returning an array of rows, the indexes are * numerical by default (0, 1, 2, etc.). However, if * the $keyfield parameter is set, then from each * row the $keyfield index is taken as the key for the * return array. This way, you can create a direct * mapping between some id field and its row in the * return data. Mind that there is no error checking * at all, so you have to make sure that you provide * a valid $keyfield here! * * @param $flags - Special flags for modifying the function's behavior. * These flags can be OR'ed if multiple flags are needed. * DB_NOCONNECTOK Failure to connect is not fatal but * lets the call return FALSE (useful * in combination with DB_RETURN_CONN). * DB_MISSINGTABLEOK Missing table errors not fatal. * DB_DUPFIELDNAMEOK Duplicate field errors not fatal. * DB_DUPKEYNAMEOK Duplicate key name errors not fatal. * DB_DUPKEYOK Duplicate key errors not fatal. * * @return $res - The result of the query, based on the $return parameter. */ function phorum_db_interact($return, $sql = NULL, $keyfield = NULL, $flags = 0) { static $conn; // Close the database connection. if ($return == DB_CLOSE_CONN) { if (!empty($conn)) { mysqli_close($conn); $conn = null; } return; } // Setup a database connection if no database connection is available yet. if (empty($conn)) { $PHORUM = $GLOBALS['PHORUM']; $conn = mysqli_connect($PHORUM['DBCONFIG']['server'], $PHORUM['DBCONFIG']['user'], $PHORUM['DBCONFIG']['password'], $PHORUM['DBCONFIG']['name'], $PHORUM['DBCONFIG']['port'], $PHORUM['DBCONFIG']['socket']); if ($conn === FALSE) { if ($flags & DB_NOCONNECTOK) { return FALSE; } phorum_database_error('Failed to connect to the database.'); exit; } if (!empty($PHORUM['DBCONFIG']['charset'])) { mysqli_query($conn, "SET NAMES '{$PHORUM['DBCONFIG']['charset']}'"); } // putting this here for testing mainly // All of Phorum should work in strict mode if (!empty($PHORUM["DBCONFIG"]["strict_mode"])) { mysqli_query($conn, "SET SESSION sql_mode='STRICT_ALL_TABLES'"); } } // Return a quoted parameter. if ($return === DB_RETURN_QUOTED) { return mysqli_real_escape_string($conn, $sql); } // RETURN: database connection handle if ($return === DB_RETURN_CONN) { return $conn; } // By now, we really need a SQL query. if ($sql === NULL) { trigger_error('Internal error: phorum_db_interact(): ' . 'missing sql query statement!', E_USER_ERROR); } // Execute the SQL query. // For queries where we are going to retrieve multiple rows, we // use an unuffered query result. if ($return === DB_RETURN_ASSOCS || $return === DB_RETURN_ROWS) { $res = FALSE; if (mysqli_real_query($conn, $sql) !== FALSE) { $res = mysqli_use_result($conn); } } else { $res = mysqli_query($conn, $sql); } // Execute the SQL query. if ($res === FALSE) { // See if the $flags tell us to ignore the error. $ignore_error = FALSE; $errno = mysqli_errno($conn); switch ($errno) { // Table does not exist. case 1146: if ($flags & DB_MISSINGTABLEOK) { $ignore_error = TRUE; } break; // Table already exists. // Table already exists. case 1050: if ($flags & DB_TABLEEXISTSOK) { $ignore_error = TRUE; } break; // Duplicate column name. // Duplicate column name. case 1060: if ($flags & DB_DUPFIELDNAMEOK) { $ignore_error = TRUE; } break; // Duplicate key name. // Duplicate key name. case 1061: if ($flags & DB_DUPKEYNAMEOK) { $ignore_error = TRUE; } break; // Duplicate entry for key. // Duplicate entry for key. case 1062: // For MySQL server versions 5.1.15 up to 5.1.20. // See bug #28842 (http://bugs.mysql.com/bug.php?id=28842) // For MySQL server versions 5.1.15 up to 5.1.20. // See bug #28842 (http://bugs.mysql.com/bug.php?id=28842) case 1582: if ($flags & DB_DUPKEYOK) { $ignore_error = TRUE; } break; } // Handle this error if it's not to be ignored. if (!$ignore_error) { $err = mysqli_error($conn); // RETURN: error message or NULL if ($return === DB_RETURN_ERROR) { return $err; } // Trigger an error. phorum_database_error("{$err} ({$errno}): {$sql}"); exit; } } // RETURN: error message or NULL if ($return === DB_RETURN_ERROR) { return NULL; } // RETURN: query resource handle if ($return === DB_RETURN_RES) { return $res; } elseif ($return === DB_RETURN_ROWCOUNT) { return $res ? mysqli_num_rows($res) : 0; } elseif ($return === DB_RETURN_ROW || $return === DB_RETURN_ROWS || $return === DB_RETURN_VALUE) { // Keyfields are only valid for DB_RETURN_ROWS. if ($return !== DB_RETURN_ROWS) { $keyfield = NULL; } $rows = array(); if ($res) { while ($row = mysqli_fetch_row($res)) { if ($keyfield === NULL) { $rows[] = $row; } else { $rows[$row[$keyfield]] = $row; } } } // Return all rows. if ($return === DB_RETURN_ROWS) { /* Might be FALSE in case of ignored errors. */ if (!is_bool($res)) { mysqli_free_result($res); } return $rows; } // Return a single row. if ($return === DB_RETURN_ROW) { if (count($rows) == 0) { return NULL; } else { return $rows[0]; } } // Return a single value. if (count($rows) == 0) { return NULL; } else { return $rows[0][0]; } } elseif ($return === DB_RETURN_ASSOC || $return === DB_RETURN_ASSOCS) { // Keyfields are only valid for DB_RETURN_ASSOCS. if ($return !== DB_RETURN_ASSOCS) { $keyfield = NULL; } $rows = array(); if ($res) { while ($row = mysqli_fetch_assoc($res)) { if ($keyfield === NULL) { $rows[] = $row; } else { $rows[$row[$keyfield]] = $row; } } } // Return all rows. if ($return === DB_RETURN_ASSOCS) { /* Might be FALSE in case of ignored errors. */ if (!is_bool($res)) { mysqli_free_result($res); } return $rows; } // Return a single row. if ($return === DB_RETURN_ASSOC) { if (count($rows) == 0) { return NULL; } else { return $rows[0]; } } } elseif ($return === DB_RETURN_NEWID) { return mysqli_insert_id($conn); } trigger_error('Internal error: phorum_db_interact(): ' . 'illegal return type specified!', E_USER_ERROR); }
/** * Write a new message to the event logging table. * * This function will automatically fill the log information with * user_id, ip, hostname (if hostname resolving is enabled for the log module) * datestamp and vroot information. Other log info can be provided throught * the $loginfo argument. * * @param $loginfo - An array containing logging information. This array * can contain the following fields: * * message A short log message on one line. * details Details about the log message, which can * span multiple lines. This could for example * be used for providing a debug backtrace. * source The source of the log message. This is a * free 32 char text field, which can be used * to specifiy what part of Phorum generated the * log message (e.g. "mod_smileys"). If no * source is provided, the "phorum_page" * constant will be used instead. * category A high level category for the message. * Options for this field are: * EVENTLOG_CAT_APPLICATION (default) * EVENTLOG_CAT_DATABASE * EVENTLOG_CAT_SECURITY * EVENTLOG_CAT_SYSTEM * EVENTLOG_CAT_MODULE * loglevel This indicates the severety of the message. * Options for this field are: * EVENTLOG_LVL_DEBUG * Messages that are used by programmers * for tracking low level Phorum operation. * EVENTLOG_LVL_INFO * Messages that provide logging for events * that occur during normal operation. These * messages could be harvested for usage * reporting and other types of reports. * EVENTLOG_LVL_WARNING * Warning messages do not indicate errors, * but they do report events that are not * considered to belong to normal operation * (e.g. a user which enters a wrong password * or a duplicate message being posted). * EVENTLOG_LVL_ERROR * Error messages indicate non urgent failures * in Phorum operation. These should be * relayed to administrators and/or developers * to have them solved. * EVENTLOG_LVL_ALERT * Alert messages indicate errors which should * be corrected as soon as possible (e.g. loss * of network connectivity or a full disk). * These should be relayed to the system * administrator). * * vroot vroot for which a message is generated. * forum_id forum_id for which a message is generated. * thread_id thread_id for which a message is generated * message_id message_id for which a message is generated * * user_id Filled automatically, but can be overridden * ip Filled automatically, but can be overridden * hostname Filled automatically, but can be overridden * datestamp Filled automatically, but can be overridden */ function event_logging_writelog($loginfo) { $PHORUM = $GLOBALS["PHORUM"]; // Check the minimum log level. Only write to the log if the // log level of the event is at or above the configured minimum. $lvl = isset($loginfo["loglevel"]) ? (int) $loginfo["loglevel"] : 0; if ($lvl < $PHORUM["mod_event_logging"]["min_log_level"]) { return; } // The record that we will insert in the database. $record = array(); // Handle messages that exceed the maximum message length. if ($loginfo["message"] !== NULL && strlen($loginfo["message"]) > 255) { if (!isset($loginfo["details"])) { $loginfo["details"] = ''; } $loginfo["details"] = "Message:\n\n{$loginfo["message"]}\n\n" . $loginfo["details"]; $loginfo["message"] = substr($loginfo["message"], 0, 100) . "... (see event details for the full message)\n"; } elseif (isset($loginfo["details"])) { $loginfo["details"] = "Message:\n\n{$loginfo["message"]}\n\n" . $loginfo["details"]; } // Add the fields from the $loginfo argument. foreach ($loginfo as $key => $val) { switch ($key) { case "datestamp": case "user_id": case "vroot": case "forum_id": case "thread_id": case "message_id": case "category": case "loglevel": settype($val, "int"); $record[$key] = $val; break; case "message": case "details": case "source": case "ip": case "hostname": $record[$key] = "'" . phorum_db_interact(DB_RETURN_QUOTED, $val) . "'"; break; default: phorum_database_error("event_logging_log(): Illegal key " . "field \"{$key}\" in the \$loginfo argument"); } } // Add the message source. $from_module = FALSE; if (!isset($record["source"])) { list($source, $from_module) = event_logging_find_source(1); $record["source"] = "'" . phorum_db_interact(DB_RETURN_QUOTED, $source) . "'"; } // Add the category. if (!isset($record["category"])) { $record["category"] = $from_module ? EVENTLOG_CAT_MODULE : EVENTLOG_CAT_APPLICATION; } // Add the datestamp. if (!isset($record["datestamp"])) { $record["datestamp"] = time(); } // Add the IP address for the current visitor. if (!isset($record["ip"]) && isset($_SERVER["REMOTE_ADDR"])) { $ip = $_SERVER["REMOTE_ADDR"]; $record["ip"] = "'" . phorum_db_interact(DB_RETURN_QUOTED, $ip) . "'"; } // Add the hostname for the current visitor. if (!isset($record["hostname"]) && isset($record["ip"]) && $PHORUM["mod_event_logging"]["resolve_hostnames"]) { $hostname = gethostbyaddr($ip); if ($hostname != $ip) { $record["hostname"] = "'" . phorum_db_interact(DB_RETURN_QUOTED, $hostname) . "'"; } } // Add the user_id in case the visitor is an authenticated user. if (!isset($record["user_id"]) && isset($PHORUM["user"]["user_id"]) && $PHORUM["user"]["user_id"]) { $record["user_id"] = $PHORUM["user"]["user_id"]; } // Add the current vroot. if (!isset($record["vroot"]) && isset($PHORUM["vroot"])) { $record["vroot"] = $PHORUM["vroot"]; } // Insert the logging record in the database. phorum_db_interact(DB_RETURN_RES, "INSERT INTO {$PHORUM["event_logging_table"]}\n (" . implode(', ', array_keys($record)) . ")\n VALUES (" . implode(', ', $record) . ")", NULL, DB_MASTERQUERY); }
/** * This method is the central method for handling database * interaction. The method can be used for setting up a database * connection, for running a SQL query and for returning query rows. * Which of these actions the method will handle and what the method * return data will be, is determined by the $return method parameter. * * @param $return - What to return. Options are the following constants: * DB_RETURN_CONN a db connection handle * DB_RETURN_QUOTED a quoted parameter * DB_RETURN_RES result resource handle * DB_RETURN_ROW single row as array * DB_RETURN_ROWS all rows as arrays * DB_RETURN_ASSOC single row as associative array * DB_RETURN_ASSOCS all rows as associative arrays * DB_RETURN_VALUE single row, single column * DB_RETURN_ROWCOUNT number of selected rows * DB_RETURN_NEWID new row id for insert query * DB_RETURN_ERROR an error message if the query * failed or NULL if there was * no error * DB_CLOSE_CONN close the connection, no * return data * * @param $sql - The SQL query to run or the parameter to quote if * DB_RETURN_QUOTED is used. * * @param $keyfield - When returning an array of rows, the indexes are * numerical by default (0, 1, 2, etc.). However, if * the $keyfield parameter is set, then from each * row the $keyfield index is taken as the key for the * return array. This way, you can create a direct * mapping between some id field and its row in the * return data. Mind that there is no error checking * at all, so you have to make sure that you provide * a valid $keyfield here! * * @param $flags - Special flags for modifying the method's behavior. * These flags can be OR'ed if multiple flags are needed. * DB_NOCONNECTOK Failure to connect is not fatal * but lets the call return FALSE * (useful in combination with * DB_RETURN_CONN). * DB_MISSINGTABLEOK Missing table errors not fatal. * DB_DUPFIELDNAMEOK Duplicate field errors not fatal. * DB_DUPKEYNAMEOK Duplicate key name errors * not fatal. * DB_DUPKEYOK Duplicate key errors not fatal. * * @param $limit - The maximum number of rows to return. * @param $offset - The number of rows to skip in the result set, * before returning rows to the caller. * * @return $res - The result of the query, based on the $return * parameter. */ public function interact($return, $sql = NULL, $keyfield = NULL, $flags = 0, $limit = 0, $offset = 0) { global $PHORUM; static $conn; // Close the database connection. if ($return == DB_CLOSE_CONN) { // PDO disconnects when the PDO object is destroyed. $conn = NULL; return; } // Setup a database connection if no database connection is // available yet. if (empty($conn)) { if (empty($PHORUM['DBCONFIG']['dbfile'])) { print 'The Phorum database configuration does not define ' . 'the path for the sqlite database file in the ' . '"dbfile" option.'; exit; } try { $conn = new PDO('sqlite:' . $PHORUM['DBCONFIG']['dbfile']); } catch (PDOException $e) { if ($flags & DB_NOCONNECTOK) { return FALSE; } phorum_database_error('Failed to open the database: ' . $e->getMessage()); exit; } } // RETURN: database connection handle. if ($return === DB_RETURN_CONN) { return $conn; } // Return a quoted parameter. if ($return === DB_RETURN_QUOTED) { $quoted = $conn->quote($sql); // PDO adds the outer single quotes, but our DB layer adds those // on its own. Strip the quotes from the quoted string. $quoted = preg_replace('/(?:^\'|\'$)/', '', $quoted); return $quoted; } // By now, we really need a SQL query. if ($sql === NULL) { trigger_error(__METHOD__ . ': Internal error: ' . 'missing sql query statement!', E_USER_ERROR); } // Apply limit and offset to the query. settype($limit, 'int'); settype($offset, 'int'); if ($limit > 0) { $sql .= " LIMIT {$limit}"; } if ($offset > 0) { $sql .= " OFFSET {$offset}"; } // Tweak the syntax of the queries. $sql = preg_replace('/^(INSERT|UPDATE)\\s+IGNORE\\s/i', '\\1 OR IGNORE ', $sql); // Execute the SQL query. $res = $conn->query($sql); if ($res === FALSE) { // An error has occurred. Fetch the error code and message. $error_info = $conn->errorInfo(); $errno = $error_info[1]; $error = $error_info[2]; // See if the $flags tell us to ignore the error. $ignore_error = FALSE; if (strstr($error, "no such table") && $flags & DB_MISSINGTABLEOK) { $ignore_error = TRUE; } if ($errno == 19 && $flags & DB_DUPKEYOK) { $ignore_error = TRUE; } # # if (strstr($exec_error, "already exists") && # substr($exec_error, 0, 5) == 'table' && # ($flags & DB_TABLEEXISTSOK)) { # $ignore_error = TRUE; # } # # if (strstr($exec_error, "already exists") && # substr($exec_error, 0, 5) == 'index' && # ($flags & DB_DUPKEYNAMEOK)) { # $ignore_error = TRUE; # } ##### HURDLE: no alter table for Sqlite2, which is the version supported ##### by php5-sqlite. Maybe PDO can be used, which seems to support Sqlite3. ##### // Duplicate column name. ##### case '42701': ##### if ($flags & DB_DUPFIELDNAMEOK) $ignore_error = TRUE; ##### break; ##### ##### // Duplicate entry for key. ##### case '23505': ##### if ($flags & DB_DUPKEYOK) { ##### $ignore_error = TRUE; ##### ##### # the code expects res to have no value upon error ##### $res = NULL; ##### } ##### break; // Handle this error if it's not to be ignored. if (!$ignore_error) { // RETURN: error message or NULL if ($return === DB_RETURN_ERROR) { return $error; } // Trigger an error. phorum_database_error("{$error} ({$errno}): {$sql}"); exit; } } // RETURN: NULL (no error) if ($return === DB_RETURN_ERROR) { return NULL; } // RETURN: query resource handle if ($return === DB_RETURN_RES) { return $res; } // RETURN: number of rows if ($return === DB_RETURN_ROWCOUNT) { if (!$res) { return 0; } return $res->rowCount(); } // RETURN: array rows or single value if ($return === DB_RETURN_ROW || $return === DB_RETURN_ROWS || $return === DB_RETURN_VALUE) { // Keyfields are only valid for DB_RETURN_ROWS. if ($return !== DB_RETURN_ROWS) { $keyfield = NULL; } $rows = array(); if ($res) { while ($row = $res->fetch(PDO::FETCH_NUM)) { if ($keyfield === NULL) { $rows[] = $row; } else { $rows[$row[$keyfield]] = $row; } } } // Return all rows. if ($return === DB_RETURN_ROWS) { return $rows; } // Return a single row. if ($return === DB_RETURN_ROW) { if (count($rows) == 0) { return NULL; } else { return $rows[0]; } } // Return a single value. if (count($rows) == 0) { return NULL; } else { return $rows[0][0]; } } // RETURN: associative array rows if ($return === DB_RETURN_ASSOC || $return === DB_RETURN_ASSOCS) { // Keyfields are only valid for DB_RETURN_ASSOCS. if ($return !== DB_RETURN_ASSOCS) { $keyfield = NULL; } $rows = array(); if ($res) { while ($row = $res->fetch(PDO::FETCH_ASSOC)) { if ($keyfield === NULL) { $rows[] = $row; } else { $rows[$row[$keyfield]] = $row; } } } // Return all rows. if ($return === DB_RETURN_ASSOCS) { return $rows; } // Return a single row. if ($return === DB_RETURN_ASSOC) { if (count($rows) == 0) { return NULL; } else { return $rows[0]; } } } // RETURN: new id after inserting a new record if ($return === DB_RETURN_NEWID) { return $conn->lastInsertId(); } trigger_error(__METHOD__ . ': Internal error: ' . 'illegal return type specified!', E_USER_ERROR); }
/** * This function is the central function for handling database interaction. * The function can be used for setting up a database connection, for running * a SQL query and for returning query rows. Which of these actions the * function will handle and what the function return data will be, is * determined by the $return function parameter. * * @param $return - What to return. Options are the following constants: * DB_RETURN_CONN a db connection handle * DB_RETURN_QUOTED a quoted parameter * DB_RETURN_RES result resource handle * DB_RETURN_ROW single row as array * DB_RETURN_ROWS all rows as arrays * DB_RETURN_ASSOC single row as associative array * DB_RETURN_ASSOCS all rows as associative arrays * DB_RETURN_VALUE single row, single column * DB_RETURN_ROWCOUNT number of selected rows * DB_RETURN_NEWID new row id for insert query * DB_RETURN_ERROR an error message if the query * failed or NULL if there was no error * DB_CLOSE_CONN close the connection, no return data * * @param $sql - The SQL query to run or the parameter to quote if * DB_RETURN_QUOTED is used. * * @param $keyfield - When returning an array of rows, the indexes are * numerical by default (0, 1, 2, etc.). However, if * the $keyfield parameter is set, then from each * row the $keyfield index is taken as the key for the * return array. This way, you can create a direct * mapping between some id field and its row in the * return data. Mind that there is no error checking * at all, so you have to make sure that you provide * a valid $keyfield here! * * @param $flags - Special flags for modifying the function's behavior. * These flags can be OR'ed if multiple flags are needed. * DB_NOCONNECTOK Failure to connect is not fatal but * lets the call return FALSE (useful * in combination with DB_RETURN_CONN). * DB_MISSINGTABLEOK Missing table errors not fatal. * DB_DUPFIELDNAMEOK Duplicate field errors not fatal. * DB_DUPKEYNAMEOK Duplicate key name errors not fatal. * DB_DUPKEYOK Duplicate key errors not fatal. * * @return $res - The result of the query, based on the $return parameter. */ function phorum_db_interact($return, $sql = NULL, $keyfield = NULL, $flags = 0) { static $conn; // Close the database connection. if ($return == DB_CLOSE_CONN) { if (!empty($conn)) { mysql_close($conn); $conn = null; } return; } // Setup a database connection if no database connection is available yet. if (empty($conn)) { $PHORUM = $GLOBALS['PHORUM']; $conn = mysql_connect($PHORUM['DBCONFIG']['server'], $PHORUM['DBCONFIG']['user'], $PHORUM['DBCONFIG']['password'], TRUE); if ($conn === FALSE) { if ($flags & DB_NOCONNECTOK) { return FALSE; } phorum_database_error('Failed to connect to the database.'); exit; } if (mysql_select_db($PHORUM['DBCONFIG']['name'], $conn) === FALSE) { if ($flags & DB_NOCONNECTOK) { return FALSE; } phorum_database_error('Failed to select the database.'); exit; } if (!empty($PHORUM['DBCONFIG']['charset'])) { mysql_query("SET NAMES '{$PHORUM['DBCONFIG']['charset']}'", $conn); } } // RETURN: database connection handle if ($return === DB_RETURN_CONN) { return $conn; } // Return a quoted parameter. if ($return === DB_RETURN_QUOTED) { return mysql_real_escape_string($sql, $conn); } // By now, we really need a SQL query. if ($sql === NULL) { trigger_error('Internal error: phorum_db_interact(): ' . 'missing sql query statement!', E_USER_ERROR); } // Execute the SQL query. $tries = 0; $res = false; while ($res === FALSE) { // For queries where we are going to retrieve multiple rows, we // use an unuffered query result. $res = $return === DB_RETURN_ASSOCS || $return === DB_RETURN_ROWS ? mysql_unbuffered_query($sql, $conn) : mysql_query($sql, $conn); if ($res === FALSE) { $errno = mysql_errno($conn); // if we have an error due to a transactional storage engine, // retry the query for those errors up to 2 more times if ($tries < 3 && ($errno == 1422 || $errno == 1213 || $errno == 1205)) { // 1205 Lock wait timeout $tries++; } else { // See if the $flags tell us to ignore the error. $ignore_error = FALSE; switch ($errno) { // Table does not exist. case 1146: if ($flags & DB_MISSINGTABLEOK) { $ignore_error = TRUE; } break; // Table already exists. // Table already exists. case 1050: if ($flags & DB_TABLEEXISTSOK) { $ignore_error = TRUE; } break; // Duplicate column name. // Duplicate column name. case 1060: if ($flags & DB_DUPFIELDNAMEOK) { $ignore_error = TRUE; } break; // Duplicate key name. // Duplicate key name. case 1061: if ($flags & DB_DUPKEYNAMEOK) { $ignore_error = TRUE; } break; // Duplicate entry for key. // Duplicate entry for key. case 1062: // For MySQL server versions 5.1.15 up to 5.1.20. // See bug #28842 (http://bugs.mysql.com/bug.php?id=28842) // For MySQL server versions 5.1.15 up to 5.1.20. // See bug #28842 (http://bugs.mysql.com/bug.php?id=28842) case 1582: if ($flags & DB_DUPKEYOK) { $ignore_error = TRUE; } break; } // Handle this error if it's not to be ignored. if (!$ignore_error) { $err = mysql_error($conn); // RETURN: error message or NULL if ($return === DB_RETURN_ERROR) { return $err; } // Trigger an error. phorum_database_error("{$err} ({$errno}): {$sql}"); exit; } // break while break; } } } if ($res === FALSE) { } // RETURN: error message or NULL if ($return === DB_RETURN_ERROR) { return NULL; } // RETURN: query resource handle if ($return === DB_RETURN_RES) { return $res; } elseif ($return === DB_RETURN_ROWCOUNT) { return $res ? mysql_num_rows($res) : 0; } elseif ($return === DB_RETURN_ROW || $return === DB_RETURN_ROWS || $return === DB_RETURN_VALUE) { // Keyfields are only valid for DB_RETURN_ROWS. if ($return !== DB_RETURN_ROWS) { $keyfield = NULL; } $rows = array(); if ($res) { while ($row = mysql_fetch_row($res)) { if ($keyfield === NULL) { $rows[] = $row; } else { $rows[$row[$keyfield]] = $row; } } } // Return all rows. if ($return === DB_RETURN_ROWS) { return $rows; } // Return a single row. if ($return === DB_RETURN_ROW) { if (count($rows) == 0) { return NULL; } else { return $rows[0]; } } // Return a single value. if (count($rows) == 0) { return NULL; } else { return $rows[0][0]; } } elseif ($return === DB_RETURN_ASSOC || $return === DB_RETURN_ASSOCS) { // Keyfields are only valid for DB_RETURN_ASSOCS. if ($return !== DB_RETURN_ASSOCS) { $keyfield = NULL; } $rows = array(); if ($res) { while ($row = mysql_fetch_assoc($res)) { if ($keyfield === NULL) { $rows[] = $row; } else { $rows[$row[$keyfield]] = $row; } } } // Return all rows. if ($return === DB_RETURN_ASSOCS) { return $rows; } // Return a single row. if ($return === DB_RETURN_ASSOC) { if (count($rows) == 0) { return NULL; } else { return $rows[0]; } } } elseif ($return === DB_RETURN_NEWID) { return mysql_insert_id($conn); } trigger_error('Internal error: phorum_db_interact(): ' . 'illegal return type specified!', E_USER_ERROR); }