From: Roland Häder Date: Sun, 6 Jul 2025 15:29:22 +0000 (+0200) Subject: Continued: X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=2ca2c2cd82e8e9b8c2fec50d2aeb1adae207feda;p=ctracker.git Continued: - renamed lib_connect.php to lib_database.php - changed last remaining old array() to "new" [] style --- diff --git a/ctracker.php b/ctracker.php index 909681e..f8d7a0a 100644 --- a/ctracker.php +++ b/ctracker.php @@ -35,7 +35,7 @@ // Include files require 'libs/lib_general.php'; require 'libs/lib_detector.php'; -require 'libs/lib_connect.php'; +require 'libs/lib_database.php'; require 'libs/lib_updates.php'; // Init diff --git a/libs/lib_connect.php b/libs/lib_connect.php deleted file mode 100644 index d217437..0000000 --- a/libs/lib_connect.php +++ /dev/null @@ -1,442 +0,0 @@ - - * @version 3.0.0 - * @copyright Copyright (c) 2009 - 2017 Cracker Tracker Team - * @license GNU GPL 3.0 or any newer version - * @link http://www.shipsimu.org - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -// Function to aquire a database link -function aquireCrackerTrackerDatabaseLink (): void { - // Is the link up? - if ((!isCrackerTrackerDatabaseLinkUp()) && (!empty($GLOBALS['ctracker_host'])) && (!empty($GLOBALS['ctracker_dbname'])) && (!empty($GLOBALS['ctracker_user']))) { - // Then connect to the database - $GLOBALS['ctracker_link'] = mysqli_connect($GLOBALS['ctracker_host'], $GLOBALS['ctracker_user'], $GLOBALS['ctracker_password'], $GLOBALS['ctracker_dbname']) or crackerTrackerDatabaseError(__FUNCTION__, __LINE__); - - // Check on connection and config table - if (!isCrackerTrackerDatabaseLinkUp()) { - // Connect didn't work - crackerTrackerDatabaseError(__FUNCTION__, __LINE__); - } elseif (isCrackerTrackerTableCreated('ctracker_config')) { - // Load the config - crackerTrackerLoadConfig(); - } - } else { - // Init fake config - crackerTrackerInitFakeConfig(); - } -} - -// Inits a fake configurtation -function crackerTrackerInitFakeConfig (): void { - // Set the array - $GLOBALS['ctracker_config'] = [ - 'ctracker_alert_user' => 'Y', - ]; -} - -// Checks if the link is up -function isCrackerTrackerDatabaseLinkUp (): bool { - // Is the instance at least set? - if (isset($GLOBALS['ctracker_link'])) { - // Debug message - //* DEBUG: */ error_log('isset='.intval(isset($GLOBALS['ctracker_link'])) . ',is_object=' . intval(is_object($GLOBALS['ctracker_link'])) . ',mysqli_connect_errno=' . mysqli_connect_errno()); - } else { - // Not set! - //* DEBUG: */ error_log('ctracker_link not set.'); - } - - return ((isset($GLOBALS['ctracker_link'])) && (is_object($GLOBALS['ctracker_link'])) && (mysqli_connect_errno() == 0)); -} - -// Database error detected -function crackerTrackerDatabaseError (string $file, int $line): void { - // Should we debug? - if (isCrackerTrackerDebug()) { - // Output error - print 'Function : ' . $file . '
' . PHP_EOL; - print 'Line : ' . $line . '
' . PHP_EOL; - if (isset($GLOBALS['ctracker_link']) && $GLOBALS['ctracker_link'] !== false) { - print 'MySQL error : ' . mysqli_error($GLOBALS['ctracker_link']) . '
' . PHP_EOL; - } else { - print 'No MySQLi available.
' . PHP_EOL; - } - if (isset($GLOBALS['ctracker_last_sql'])) { - print 'Last SQL : '. $GLOBALS['ctracker_last_sql'] . '
' . PHP_EOL; - } else { - print 'No last SQL command available.
' . PHP_EOL; - } - } - - // Currently only die here - crackerTrackerDie(); -} - -// Closes a maybe open database link -function crackerTrackerCloseDatabaseLink (): void { - // The link should be up here - if (!isCrackerTrackerDatabaseLinkUp()) { - // Throw exception - throw new BadFunctionCallException('Link is not up.'); - } - - // Did it work? - if (!mysqli_close($GLOBALS['ctracker_link'])) { - // Attempt has failed - crackerTrackerDatabaseError(__FUNCTION__, __LINE__); - } -} - -// Inserts given array, if IP/check_get combination was not found -function crackerTrackerInsertArray (string $table, array $rowData): void { - // Is it found? - if (!isCrackerTrackerEntryFound($rowData)) { - // Reset insert id - $GLOBALS['ctracker_last_insert_id'] = false; - - // Run it - runCrackerTrackerSql(sprintf("INSERT INTO `%s` (`%s`) VALUES(%s)", - $table, - implode('`,`', array_keys($rowData)), - implode_secure($rowData) - ), __FUNCTION__, __LINE__); - - // Remember the last insert id - $GLOBALS['ctracker_last_insert_id'] = mysqli_insert_id($GLOBALS['ctracker_link']) or crackerTrackerDatabaseError(__FUNCTION__, __LINE__); - } else { - // Only update the entry - updateCrackerTrackerEntry($rowData); - } -} - -// Updates a given entry by just counting it up -function updateCrackerTrackerEntry (array $rowData, string $countColumn = 'count'): void { - // The link should be up here - if (!isCrackerTrackerDatabaseLinkUp()) { - // Throw exception - throw new BadFunctionCallException('Link is not up.'); - } - - // Run the SQL and check if we have one line - runCrackerTrackerSql(sprintf("UPDATE `ctracker_data` SET `%s`=`%s`+1 WHERE (`remote_addr`='%s' AND `proxy_addr`='%s') LIMIT 1", - $countColumn, - $countColumn, - crackerTrackerEscapeString($rowData['remote_addr']), - crackerTrackerEscapeString($rowData['proxy_addr']) - ), __FUNCTION__, __LINE__); -} - -// Checks if an entry with IP/check_get/domain combination is there -function isCrackerTrackerEntryFound (array $rowData): bool { - // The link should be up here - if (!isCrackerTrackerDatabaseLinkUp()) { - // Throw exception - throw new BadFunctionCallException('Link is not up.'); - } - - // Run the SQL and check if we have one line - $result = runCrackerTrackerSql(sprintf("SELECT `id` FROM `ctracker_data` WHERE (`remote_addr`='%s' OR `proxy_addr`='%s') AND `check_get` = '%s' AND `server_name`='%s' LIMIT 1'", - crackerTrackerEscapeString($rowData['remote_addr']), - crackerTrackerEscapeString($rowData['proxy_addr']), - crackerTrackerEscapeString($rowData['check_get']), - crackerTrackerEscapeString($rowData['server_name']) - ), __FUNCTION__, __LINE__); - - // Check count of rows - return (mysqli_num_rows($result) == 1); -} - -// Escapes the string -function crackerTrackerEscapeString (string $string): string { - // Is the link up? - if (!isCrackerTrackerDatabaseLinkUp()) { - // Then we cant use mysqli_real_escape_string! - $string = htmlentities($string, ENT_QUOTES); - } elseif (function_exists('mysqli_real_escape_string')) { - // Use mysqli_real_escape_string() - $string = mysqli_real_escape_string($GLOBALS['ctracker_link'], $string); - } else { - // Use fall-back (bad!) - $string = htmlentities($string, ENT_QUOTES); - } - - // Return the secured string - return $string; -} - -// Runs an SQL query and checks for errors -function runCrackerTrackerSql (string $sqlString, string $function, int $line) { - // Is the link up? - if (!isCrackerTrackerDatabaseLinkUp()) { - // Abort here - crackerTrackerDie(); - } - - // Remember last SQL - $GLOBALS['ctracker_last_sql'] = $sqlString; - - // Run the query - $GLOBALS['ctracker_last_result'] = mysqli_query($GLOBALS['ctracker_link'], $sqlString) or crackerTrackerDatabaseError($function, $line); - - // And return it - return $GLOBALS['ctracker_last_result']; -} - -// Checks wether a table was found -function isCrackerTrackerTableCreated (string $table): bool { - // Default is not found - $found = false; - - // Run the query - $result = runCrackerTrackerSql('SHOW TABLES', __FUNCTION__, __LINE__); - - // Is our table there? - while (list($tab) = mysqli_fetch_row($result)) { - // Debug message - //* NOISY-DEBUG: */ error_log('tab=' . $tab); - - // Is the table there? - if ($tab == $table) { - // Okay, found. So abort - $found = true; - break; - } - } - - // Free result - freeCrackerTrackerResult($result); - - // Return result - return $found; -} - -// Creates the given table with columns -function crackerTrackerCreateTable (string $table, array $columns, array $keys): void { - // Begin the SQL - $sqlString = 'CREATE TABLE IF NOT EXISTS `' . $table . '` ('; - - // Add table name as first column - $sqlString .= '`' . $table . '` BIGINT ( 20 ) UNSIGNED NOT NULL AUTO_INCREMENT, '; - - // Add all columns - foreach ($columns as $column=>$type) { - // Add this entry - $sqlString .= '`' . $column . '` ' . $type . ', '; - } - - // Add table name as primary key - $sqlString .= 'PRIMARY KEY (`' . $table . '`), '; - - // Add keys - foreach ($keys as $key => $type) { - // Add this entry - $sqlString .= '' . $type . ' (`' . $key . '`), '; - } - - // Finish SQL - $sqlString = substr($sqlString, 0, -2) . ') TYPE=InnoDB'; - - // And run it - runCrackerTrackerSql($sqlString); -} - -// Inits a table by inserting -function crackerTrackerInitTable (string $table): void { - // Prepare SQL and run it - runCrackerTrackerSql(sprintf("INSERT INTO `%s` (`%s`) VALUES (NULL)'", - $table, - $table - )); -} - -// Updates the database scheme automatically -function crackerTrackerUpdateDatabaseScheme (): void { - // Is a link there? - if (!isCrackerTrackerDatabaseLinkUp()) { - // Abort here silently - return; - } - - // Is the main config table there? - if (!isCrackerTrackerTableCreated('ctracker_config')) { - // Then do it for us - crackerTrackerCreateTable('ctracker_config', [ - 'ctracker_db_version' => 'BIGINT ( 20 ) UNSIGNED NOT NULL DEFAULT 0', - 'ctracker_min_sleep' => 'SMALLINT ( 5 ) UNSIGNED NOT NULL DEFAULT 10', - 'ctracker_max_sleep' => 'SMALLINT ( 5 ) UNSIGNED NOT NULL DEFAULT 30', - 'ctracker_alert_user' => "ENUM('Y','N') NOT NULL DEFAULT 'Y'", - 'ctracker_language' => "CHAR ( 2) NOT NULL DEFAULT 'en'" - ], [ - ]); - - // Init that table - crackerTrackerInitTable('ctracker_config'); - } - - // Init update array here - crackerTrackerInitUpdates(); - - // Run any SQL updates recursively - while (isset($GLOBALS['ctracker_updates'][getCrackerTrackerConfig('ctracker_db_version')])) { - // Run that updates - runCrackerTrackerUpdates(getCrackerTrackerConfig('ctracker_db_version')); - - // Update config - runCrackerTrackerSql('UPDATE `ctracker_config` SET `ctracker_db_version`=`ctracker_db_version`+1 WHERE `ctracker_config`=1 LIMIT 1', __FUNCTION__, __LINE__); - - // And count it up in the config array - $GLOBALS['ctracker_config']['ctracker_db_version']++; - } -} - -// Load the configuration -function crackerTrackerLoadConfig (): void { - // Construct SQL command and run it - $result = runCrackerTrackerSql('SELECT * FROM `ctracker_config` WHERE `ctracker_config`=1 LIMIT 1', __FUNCTION__, __LINE__); - - // And get it - $GLOBALS['ctracker_config'] = mysqli_fetch_array($result); - - // Free result - freeCrackerTrackerResult($result); -} - -// Getter for config -function getCrackerTrackerConfig (string $entry) { - // Is the config entry there? - if (!isset($GLOBALS['ctracker_config'][$entry])) { - // Then better die here, else we may have an endless loop - if (isCrackerTrackerDebug()) { - // Nicer message in debug mode - die('Configuration entry ' . $entry . ' missing!'); - } else { - // die() on production systems - die(); - } - } - - // Return it - return $GLOBALS['ctracker_config'][$entry]; -} - -// Did the current IP already generated blocked attempts? -function isCrackerTrackerIpSuspicious (): bool { - // Skip this silently if we have not config - if (!isCrackerTrackerDatabaseLinkUp()) { - // Skip this step silently, all is not suspicious - return false; - } - - // Check if an entry is there - $result = runCrackerTrackerSql("SELECT COUNT(`id`) AS `cnt` FROM `ctracker_data` USE INDEX (`remote_proxy_last`) WHERE `remote_addr`='" . determineCrackerTrackerRealRemoteAddress() . "' OR `proxy_addr`='" . getenv('REMOTE_ADDR') . "' LIMIT 1", __FUNCTION__, __LINE__); - - // Get row count - list($rows) = mysqli_fetch_row($result); - - // Is there one entry? - $found = ($rows > 0); - - // And again? - if ($found === true) { - // Yes, one is found, then load it - $result = runCrackerTrackerSql("SELECT SQL_SMALL_RESULT * FROM `ctracker_data` USE INDEX (`remote_proxy_last`) WHERE `remote_addr`='" . determineCrackerTrackerRealRemoteAddress() . "' OR `proxy_addr`='" . getenv('REMOTE_ADDR') . "' ORDER BY `last_attempt` DESC LIMIT 1", __FUNCTION__, __LINE__); - - // Cache the entry - $GLOBALS['ctracker_last_suspicious_entry'] = mysqli_fetch_array($result); - } - - // Free result - freeCrackerTrackerResult($result); - - // Return the result - return $found; -} - -// Does the current IP have a ticket? -function ifCrackerTrackerIpHasTicket (): bool { - // We only give one ticket per IP! - $result = runCrackerTrackerSql("SELECT * FROM `ctracker_ticket` WHERE `ctracker_ticket_remote_addr`='" . determineCrackerTrackerRealRemoteAddress() . "' OR `ctracker_ticket_proxy_addr`='" . getenv('REMOTE_ADDR') . "' LIMIT 1", __FUNCTION__, __LINE__); - - // Do we have a ticket? - $found = (mysqli_num_rows($result) == 1); - - // And again? - if ($found === true) { - // Cache the ticket data - $GLOBALS['ctracker_last_ticket'] = mysqli_fetch_array($result); - } - - // Free result - freeCrackerTrackerResult($result); - - // Return the result - return $found; -} - -// Adds a ticket based on given (mostly $_POST) data -function addCrackerTrackerTicket (array $data): void { - // Prepare the array - $GLOBALS['ctracker_last_ticket'] = [ - 'ctracker_ticket_remote_addr' => determineCrackerTrackerRealRemoteAddress(), - 'ctracker_ticket_proxy_addr' => getenv('REMOTE_ADDR'), - 'ctracker_ticket_user_agent' => crackerTrackerUserAgent(), - 'ctracker_ticket_name' => crackerTrackerSecureString($data['name']), - 'ctracker_ticket_email' => crackerTrackerSecureString($data['email']), - 'ctracker_ticket_comment' => crackerTrackerSecureString($data['comment']) - ]; - - // Insert it - crackerTrackerInsertArray('ctracker_ticket', $GLOBALS['ctracker_last_ticket']); - - // Is there an entry? - if ((isset($GLOBALS['ctracker_last_insert_id'])) && ($GLOBALS['ctracker_last_insert_id'] > 0)) { - // All fine, so prepare the link between ticket<->data - $data = [ - 'ctracker_ticket_id' => $GLOBALS['ctracker_last_insert_id'], - 'ctracker_data_id' => $GLOBALS['ctracker_last_suspicious_entry']['id'] - ]; - - // And insert it as well - crackerTrackerInsertArray('ctracker_ticket_data', $data); - - // Add ticket id again - $GLOBALS['ctracker_ticket'] = $data['ctracker_ticket_id']; - - // Merge all data for emails - $GLOBALS['ctracker_last_ticket'] = array_merge($GLOBALS['ctracker_last_ticket'], $data); - - // Is this also there? - if ((isset($GLOBALS['ctracker_last_insert_id'])) && ($GLOBALS['ctracker_last_insert_id'] > 0)) { - // All fine, so display "thank you page" - crackerTrackerLoadTemplate('add_ticket_thanks'); - } else { - // Did not insert - crackerTrackerDie(); - } - } else { - // Did not insert - crackerTrackerDie(); - } -} - -// Frees given result instance -function freeCrackerTrackerResult (mysqli_result $result): void { - // Free result - $result->free(); -} diff --git a/libs/lib_database.php b/libs/lib_database.php new file mode 100644 index 0000000..d217437 --- /dev/null +++ b/libs/lib_database.php @@ -0,0 +1,442 @@ + + * @version 3.0.0 + * @copyright Copyright (c) 2009 - 2017 Cracker Tracker Team + * @license GNU GPL 3.0 or any newer version + * @link http://www.shipsimu.org + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// Function to aquire a database link +function aquireCrackerTrackerDatabaseLink (): void { + // Is the link up? + if ((!isCrackerTrackerDatabaseLinkUp()) && (!empty($GLOBALS['ctracker_host'])) && (!empty($GLOBALS['ctracker_dbname'])) && (!empty($GLOBALS['ctracker_user']))) { + // Then connect to the database + $GLOBALS['ctracker_link'] = mysqli_connect($GLOBALS['ctracker_host'], $GLOBALS['ctracker_user'], $GLOBALS['ctracker_password'], $GLOBALS['ctracker_dbname']) or crackerTrackerDatabaseError(__FUNCTION__, __LINE__); + + // Check on connection and config table + if (!isCrackerTrackerDatabaseLinkUp()) { + // Connect didn't work + crackerTrackerDatabaseError(__FUNCTION__, __LINE__); + } elseif (isCrackerTrackerTableCreated('ctracker_config')) { + // Load the config + crackerTrackerLoadConfig(); + } + } else { + // Init fake config + crackerTrackerInitFakeConfig(); + } +} + +// Inits a fake configurtation +function crackerTrackerInitFakeConfig (): void { + // Set the array + $GLOBALS['ctracker_config'] = [ + 'ctracker_alert_user' => 'Y', + ]; +} + +// Checks if the link is up +function isCrackerTrackerDatabaseLinkUp (): bool { + // Is the instance at least set? + if (isset($GLOBALS['ctracker_link'])) { + // Debug message + //* DEBUG: */ error_log('isset='.intval(isset($GLOBALS['ctracker_link'])) . ',is_object=' . intval(is_object($GLOBALS['ctracker_link'])) . ',mysqli_connect_errno=' . mysqli_connect_errno()); + } else { + // Not set! + //* DEBUG: */ error_log('ctracker_link not set.'); + } + + return ((isset($GLOBALS['ctracker_link'])) && (is_object($GLOBALS['ctracker_link'])) && (mysqli_connect_errno() == 0)); +} + +// Database error detected +function crackerTrackerDatabaseError (string $file, int $line): void { + // Should we debug? + if (isCrackerTrackerDebug()) { + // Output error + print 'Function : ' . $file . '
' . PHP_EOL; + print 'Line : ' . $line . '
' . PHP_EOL; + if (isset($GLOBALS['ctracker_link']) && $GLOBALS['ctracker_link'] !== false) { + print 'MySQL error : ' . mysqli_error($GLOBALS['ctracker_link']) . '
' . PHP_EOL; + } else { + print 'No MySQLi available.
' . PHP_EOL; + } + if (isset($GLOBALS['ctracker_last_sql'])) { + print 'Last SQL : '. $GLOBALS['ctracker_last_sql'] . '
' . PHP_EOL; + } else { + print 'No last SQL command available.
' . PHP_EOL; + } + } + + // Currently only die here + crackerTrackerDie(); +} + +// Closes a maybe open database link +function crackerTrackerCloseDatabaseLink (): void { + // The link should be up here + if (!isCrackerTrackerDatabaseLinkUp()) { + // Throw exception + throw new BadFunctionCallException('Link is not up.'); + } + + // Did it work? + if (!mysqli_close($GLOBALS['ctracker_link'])) { + // Attempt has failed + crackerTrackerDatabaseError(__FUNCTION__, __LINE__); + } +} + +// Inserts given array, if IP/check_get combination was not found +function crackerTrackerInsertArray (string $table, array $rowData): void { + // Is it found? + if (!isCrackerTrackerEntryFound($rowData)) { + // Reset insert id + $GLOBALS['ctracker_last_insert_id'] = false; + + // Run it + runCrackerTrackerSql(sprintf("INSERT INTO `%s` (`%s`) VALUES(%s)", + $table, + implode('`,`', array_keys($rowData)), + implode_secure($rowData) + ), __FUNCTION__, __LINE__); + + // Remember the last insert id + $GLOBALS['ctracker_last_insert_id'] = mysqli_insert_id($GLOBALS['ctracker_link']) or crackerTrackerDatabaseError(__FUNCTION__, __LINE__); + } else { + // Only update the entry + updateCrackerTrackerEntry($rowData); + } +} + +// Updates a given entry by just counting it up +function updateCrackerTrackerEntry (array $rowData, string $countColumn = 'count'): void { + // The link should be up here + if (!isCrackerTrackerDatabaseLinkUp()) { + // Throw exception + throw new BadFunctionCallException('Link is not up.'); + } + + // Run the SQL and check if we have one line + runCrackerTrackerSql(sprintf("UPDATE `ctracker_data` SET `%s`=`%s`+1 WHERE (`remote_addr`='%s' AND `proxy_addr`='%s') LIMIT 1", + $countColumn, + $countColumn, + crackerTrackerEscapeString($rowData['remote_addr']), + crackerTrackerEscapeString($rowData['proxy_addr']) + ), __FUNCTION__, __LINE__); +} + +// Checks if an entry with IP/check_get/domain combination is there +function isCrackerTrackerEntryFound (array $rowData): bool { + // The link should be up here + if (!isCrackerTrackerDatabaseLinkUp()) { + // Throw exception + throw new BadFunctionCallException('Link is not up.'); + } + + // Run the SQL and check if we have one line + $result = runCrackerTrackerSql(sprintf("SELECT `id` FROM `ctracker_data` WHERE (`remote_addr`='%s' OR `proxy_addr`='%s') AND `check_get` = '%s' AND `server_name`='%s' LIMIT 1'", + crackerTrackerEscapeString($rowData['remote_addr']), + crackerTrackerEscapeString($rowData['proxy_addr']), + crackerTrackerEscapeString($rowData['check_get']), + crackerTrackerEscapeString($rowData['server_name']) + ), __FUNCTION__, __LINE__); + + // Check count of rows + return (mysqli_num_rows($result) == 1); +} + +// Escapes the string +function crackerTrackerEscapeString (string $string): string { + // Is the link up? + if (!isCrackerTrackerDatabaseLinkUp()) { + // Then we cant use mysqli_real_escape_string! + $string = htmlentities($string, ENT_QUOTES); + } elseif (function_exists('mysqli_real_escape_string')) { + // Use mysqli_real_escape_string() + $string = mysqli_real_escape_string($GLOBALS['ctracker_link'], $string); + } else { + // Use fall-back (bad!) + $string = htmlentities($string, ENT_QUOTES); + } + + // Return the secured string + return $string; +} + +// Runs an SQL query and checks for errors +function runCrackerTrackerSql (string $sqlString, string $function, int $line) { + // Is the link up? + if (!isCrackerTrackerDatabaseLinkUp()) { + // Abort here + crackerTrackerDie(); + } + + // Remember last SQL + $GLOBALS['ctracker_last_sql'] = $sqlString; + + // Run the query + $GLOBALS['ctracker_last_result'] = mysqli_query($GLOBALS['ctracker_link'], $sqlString) or crackerTrackerDatabaseError($function, $line); + + // And return it + return $GLOBALS['ctracker_last_result']; +} + +// Checks wether a table was found +function isCrackerTrackerTableCreated (string $table): bool { + // Default is not found + $found = false; + + // Run the query + $result = runCrackerTrackerSql('SHOW TABLES', __FUNCTION__, __LINE__); + + // Is our table there? + while (list($tab) = mysqli_fetch_row($result)) { + // Debug message + //* NOISY-DEBUG: */ error_log('tab=' . $tab); + + // Is the table there? + if ($tab == $table) { + // Okay, found. So abort + $found = true; + break; + } + } + + // Free result + freeCrackerTrackerResult($result); + + // Return result + return $found; +} + +// Creates the given table with columns +function crackerTrackerCreateTable (string $table, array $columns, array $keys): void { + // Begin the SQL + $sqlString = 'CREATE TABLE IF NOT EXISTS `' . $table . '` ('; + + // Add table name as first column + $sqlString .= '`' . $table . '` BIGINT ( 20 ) UNSIGNED NOT NULL AUTO_INCREMENT, '; + + // Add all columns + foreach ($columns as $column=>$type) { + // Add this entry + $sqlString .= '`' . $column . '` ' . $type . ', '; + } + + // Add table name as primary key + $sqlString .= 'PRIMARY KEY (`' . $table . '`), '; + + // Add keys + foreach ($keys as $key => $type) { + // Add this entry + $sqlString .= '' . $type . ' (`' . $key . '`), '; + } + + // Finish SQL + $sqlString = substr($sqlString, 0, -2) . ') TYPE=InnoDB'; + + // And run it + runCrackerTrackerSql($sqlString); +} + +// Inits a table by inserting +function crackerTrackerInitTable (string $table): void { + // Prepare SQL and run it + runCrackerTrackerSql(sprintf("INSERT INTO `%s` (`%s`) VALUES (NULL)'", + $table, + $table + )); +} + +// Updates the database scheme automatically +function crackerTrackerUpdateDatabaseScheme (): void { + // Is a link there? + if (!isCrackerTrackerDatabaseLinkUp()) { + // Abort here silently + return; + } + + // Is the main config table there? + if (!isCrackerTrackerTableCreated('ctracker_config')) { + // Then do it for us + crackerTrackerCreateTable('ctracker_config', [ + 'ctracker_db_version' => 'BIGINT ( 20 ) UNSIGNED NOT NULL DEFAULT 0', + 'ctracker_min_sleep' => 'SMALLINT ( 5 ) UNSIGNED NOT NULL DEFAULT 10', + 'ctracker_max_sleep' => 'SMALLINT ( 5 ) UNSIGNED NOT NULL DEFAULT 30', + 'ctracker_alert_user' => "ENUM('Y','N') NOT NULL DEFAULT 'Y'", + 'ctracker_language' => "CHAR ( 2) NOT NULL DEFAULT 'en'" + ], [ + ]); + + // Init that table + crackerTrackerInitTable('ctracker_config'); + } + + // Init update array here + crackerTrackerInitUpdates(); + + // Run any SQL updates recursively + while (isset($GLOBALS['ctracker_updates'][getCrackerTrackerConfig('ctracker_db_version')])) { + // Run that updates + runCrackerTrackerUpdates(getCrackerTrackerConfig('ctracker_db_version')); + + // Update config + runCrackerTrackerSql('UPDATE `ctracker_config` SET `ctracker_db_version`=`ctracker_db_version`+1 WHERE `ctracker_config`=1 LIMIT 1', __FUNCTION__, __LINE__); + + // And count it up in the config array + $GLOBALS['ctracker_config']['ctracker_db_version']++; + } +} + +// Load the configuration +function crackerTrackerLoadConfig (): void { + // Construct SQL command and run it + $result = runCrackerTrackerSql('SELECT * FROM `ctracker_config` WHERE `ctracker_config`=1 LIMIT 1', __FUNCTION__, __LINE__); + + // And get it + $GLOBALS['ctracker_config'] = mysqli_fetch_array($result); + + // Free result + freeCrackerTrackerResult($result); +} + +// Getter for config +function getCrackerTrackerConfig (string $entry) { + // Is the config entry there? + if (!isset($GLOBALS['ctracker_config'][$entry])) { + // Then better die here, else we may have an endless loop + if (isCrackerTrackerDebug()) { + // Nicer message in debug mode + die('Configuration entry ' . $entry . ' missing!'); + } else { + // die() on production systems + die(); + } + } + + // Return it + return $GLOBALS['ctracker_config'][$entry]; +} + +// Did the current IP already generated blocked attempts? +function isCrackerTrackerIpSuspicious (): bool { + // Skip this silently if we have not config + if (!isCrackerTrackerDatabaseLinkUp()) { + // Skip this step silently, all is not suspicious + return false; + } + + // Check if an entry is there + $result = runCrackerTrackerSql("SELECT COUNT(`id`) AS `cnt` FROM `ctracker_data` USE INDEX (`remote_proxy_last`) WHERE `remote_addr`='" . determineCrackerTrackerRealRemoteAddress() . "' OR `proxy_addr`='" . getenv('REMOTE_ADDR') . "' LIMIT 1", __FUNCTION__, __LINE__); + + // Get row count + list($rows) = mysqli_fetch_row($result); + + // Is there one entry? + $found = ($rows > 0); + + // And again? + if ($found === true) { + // Yes, one is found, then load it + $result = runCrackerTrackerSql("SELECT SQL_SMALL_RESULT * FROM `ctracker_data` USE INDEX (`remote_proxy_last`) WHERE `remote_addr`='" . determineCrackerTrackerRealRemoteAddress() . "' OR `proxy_addr`='" . getenv('REMOTE_ADDR') . "' ORDER BY `last_attempt` DESC LIMIT 1", __FUNCTION__, __LINE__); + + // Cache the entry + $GLOBALS['ctracker_last_suspicious_entry'] = mysqli_fetch_array($result); + } + + // Free result + freeCrackerTrackerResult($result); + + // Return the result + return $found; +} + +// Does the current IP have a ticket? +function ifCrackerTrackerIpHasTicket (): bool { + // We only give one ticket per IP! + $result = runCrackerTrackerSql("SELECT * FROM `ctracker_ticket` WHERE `ctracker_ticket_remote_addr`='" . determineCrackerTrackerRealRemoteAddress() . "' OR `ctracker_ticket_proxy_addr`='" . getenv('REMOTE_ADDR') . "' LIMIT 1", __FUNCTION__, __LINE__); + + // Do we have a ticket? + $found = (mysqli_num_rows($result) == 1); + + // And again? + if ($found === true) { + // Cache the ticket data + $GLOBALS['ctracker_last_ticket'] = mysqli_fetch_array($result); + } + + // Free result + freeCrackerTrackerResult($result); + + // Return the result + return $found; +} + +// Adds a ticket based on given (mostly $_POST) data +function addCrackerTrackerTicket (array $data): void { + // Prepare the array + $GLOBALS['ctracker_last_ticket'] = [ + 'ctracker_ticket_remote_addr' => determineCrackerTrackerRealRemoteAddress(), + 'ctracker_ticket_proxy_addr' => getenv('REMOTE_ADDR'), + 'ctracker_ticket_user_agent' => crackerTrackerUserAgent(), + 'ctracker_ticket_name' => crackerTrackerSecureString($data['name']), + 'ctracker_ticket_email' => crackerTrackerSecureString($data['email']), + 'ctracker_ticket_comment' => crackerTrackerSecureString($data['comment']) + ]; + + // Insert it + crackerTrackerInsertArray('ctracker_ticket', $GLOBALS['ctracker_last_ticket']); + + // Is there an entry? + if ((isset($GLOBALS['ctracker_last_insert_id'])) && ($GLOBALS['ctracker_last_insert_id'] > 0)) { + // All fine, so prepare the link between ticket<->data + $data = [ + 'ctracker_ticket_id' => $GLOBALS['ctracker_last_insert_id'], + 'ctracker_data_id' => $GLOBALS['ctracker_last_suspicious_entry']['id'] + ]; + + // And insert it as well + crackerTrackerInsertArray('ctracker_ticket_data', $data); + + // Add ticket id again + $GLOBALS['ctracker_ticket'] = $data['ctracker_ticket_id']; + + // Merge all data for emails + $GLOBALS['ctracker_last_ticket'] = array_merge($GLOBALS['ctracker_last_ticket'], $data); + + // Is this also there? + if ((isset($GLOBALS['ctracker_last_insert_id'])) && ($GLOBALS['ctracker_last_insert_id'] > 0)) { + // All fine, so display "thank you page" + crackerTrackerLoadTemplate('add_ticket_thanks'); + } else { + // Did not insert + crackerTrackerDie(); + } + } else { + // Did not insert + crackerTrackerDie(); + } +} + +// Frees given result instance +function freeCrackerTrackerResult (mysqli_result $result): void { + // Free result + $result->free(); +} diff --git a/libs/lib_general.php b/libs/lib_general.php index f5c892d..f5aca95 100644 --- a/libs/lib_general.php +++ b/libs/lib_general.php @@ -50,7 +50,7 @@ function implode_secure (array $array) { // Implode all data foreach ($array as $entry) { // Don't escape some - if (in_array($entry, array('NOW()'))) { + if (in_array($entry, ['NOW()'])) { // Add it with non-string glue $return .= $entry . ','; } elseif (empty($entry)) { @@ -578,7 +578,7 @@ function unsetCtrackerData (): void { // Sanitizes string function crackerTrackerSanitize (string $str): string { - return str_replace(array('//', '/./'), array('/', '/'), $str); + return str_replace(['//', '/./'], ['/', '/'], $str); } function crackerTrackerIsConsole (): bool {