<?php

/*
  $Id: database.php 1739 2007-12-20 00:52:16Z hpdl $

  osCommerce, Open Source E-Commerce Solutions
  http://www.oscommerce.com

  Copyright (c) 2007 osCommerce

  Released under the GNU General Public License


  mailbeez.com: modified for compatibility in zencart - just in case someone already did include these functions
 */


///////////////////////////////////////////////////////////////////////////////
///																																					 //
///                 MailBeez Core file - do not edit                         //
///                                                                          //
///////////////////////////////////////////////////////////////////////////////
///
global $db;
global $mh_db;

if (!isset($mh_db)) {
    $mh_db = new stdClass();
}

if (isset($db) && is_object($db) && get_class($db) === 'queryFactory') {
    mh_define('MH_DBTYPE', 'MYSQLI');
} else {
    if (isset($db) && is_object($db)) {
        $mh_db = $db;
    }

    if (isset($mh_db->link)) {
        $mh_db_link = $mh_db->link;

        // detect type of db connection
        if (is_resource($mh_db_link) && get_resource_type($mh_db_link) === 'mysql link') {
            mh_define('MH_DBTYPE', 'MYSQL');
        } elseif (is_object($mh_db_link) && $mh_db_link instanceof mysqli) {
            mh_define('MH_DBTYPE', 'MYSQLI');
        }
    }
}

// Fallback to MYSQLI if not detected and extension exists
if (!defined('MH_DBTYPE')) {
    if (function_exists('mysqli_connect')) {
        mh_define('MH_DBTYPE', 'MYSQLI');
    } else {
        mh_define('MH_DBTYPE', 'MYSQL');
    }
}


// issue: on zencart the dblink is not of type mysqli


if (!function_exists('tep_db_connect')) {

    function tep_db_connect($server = DB_SERVER, $username = DB_SERVER_USERNAME, $password = DB_SERVER_PASSWORD, $database = DB_DATABASE, $link = 'db_link')
    {
        global $mh_db;


        switch (MH_DBTYPE) {
            case 'MYSQL':
                if (USE_PCONNECT == 'true') {
                    $mh_db->link = mysql_pconnect($server, $username, $password);
                } else {
                    $mh_db->link = mysql_connect($server, $username, $password);
                }

                if ($mh_db->link)
                    mysql_select_db($database);

                return $mh_db->link;

                break;
            case 'MYSQLI':
                if (USE_PCONNECT == 'true') {
                    $server = 'p:' . $server;
                }

                $mh_db->link = mysqli_connect($server, $username, $password, $database);
                return $mh_db->link;
                break;
            default:
//                echo 'DB Type not supported';
        }
    }

}


if (!function_exists('tep_db_close')) {

    function tep_db_close($link = 'db_link')
    {
        global $mh_db;

        switch (MH_DBTYPE) {
            case 'MYSQL':
                return mysql_close($mh_db->link);
                break;
            case 'MYSQLI':
                return mysqli_close($mh_db->link);
                break;
            default:
//                echo 'DB Type not supported';
        }
    }
}

if (!function_exists('tep_db_error')) {

    function tep_db_error($query, $errno, $error)
    {
        $debug = debug_backtrace(PHP_VERSION_ID >= 50306 ? DEBUG_BACKTRACE_IGNORE_ARGS : 0, 5);

        $error_message = "Database Error: " . $errno . " - " . $error . "\n";
        $error_message .= "Query: " . $query . "\n";

        error_log($error_message);

        $output = '<div style="font-family:sans-serif; border:1px solid #cc0000; padding:15px; background:#fff5f5; color:#000;">';
        $output .= '<h2 style="color:#cc0000; margin-top:0;">Database Error</h2>';
        $output .= '<strong>Error Code:</strong> ' . htmlspecialchars($errno) . '<br>';
        $output .= '<strong>Error Message:</strong> ' . htmlspecialchars($error) . '<br><br>';
        $output .= '<strong>Query:</strong><pre style="white-space:pre-wrap; background:#eee; padding:10px; border:1px solid #ccc;">' . htmlspecialchars($query) . '</pre><br>';
        $output .= '<strong>Backtrace:</strong><pre style="white-space:pre-wrap; background:#eee; padding:10px; border:1px solid #ccc; font-size:11px;">' . htmlspecialchars(print_r($debug, true)) . '</pre>';
        $output .= '<small style="color:#ff0000; font-weight:bold;">[TEP STOP]</small>';
        $output .= '</div>';

        die($output);
    }

}

if (!function_exists('tep_db_query')) {

    function tep_db_query($query, $link = 'db_link')
    {
        global $mh_db;

        if (empty($query) || !is_string($query)) {
            return false;
        }

        $query = str_replace("\0", "", $query);

        if (defined('STORE_DB_TRANSACTIONS') && (STORE_DB_TRANSACTIONS == 'true')) {
            error_log('QUERY ' . $query . "\n", 3, STORE_PAGE_PARSE_TIME_LOG);
        }

        // Security Hardening: Analysis of query string for unescaped quotes or malformed literals.
        // This helps detect potential SQL injection and developer errors without blindly re-escaping.
        // 1. Identify and remove all well-formed literals and identifiers to see what is left "naked" in the query.
        $well_formed_rx = '/\'(?:[^\'\\\\]|\\\\.)*\'|"(?:[^"\\\\]|\\\\.)*"|`(?:[^`]|``)*`/';
        $test_query = preg_replace($well_formed_rx, '', $query);

        // 2. Remove SQL comments from the remaining part to avoid false positives from quotes in comments
        $RXSQLComments = '@(--[^\r\n]*)|(\#[^\r\n]*)|(/\*[\w\W]*?(?=\*/)\*/)@ms';
        $test_query = preg_replace($RXSQLComments, '', $test_query);

        // 3. If any single or double quotes remain, the query is likely malformed or has unescaped data.
        if (strpos($test_query, "'") !== false || strpos($test_query, '"') !== false) {
            error_log("Security hardening: Potential SQL injection or malformed query detected in tep_db_query: " . $query);
        }


        switch (MH_DBTYPE) {
            case 'MYSQL':
                $result = mysql_query($query, $mh_db->link) or tep_db_error($query, mysql_errno(), mysql_error());

                if (defined('STORE_DB_TRANSACTIONS') && (STORE_DB_TRANSACTIONS == 'true')) {
                    $result_error = mysql_error();
                    error_log('RESULT ' . $result . ' ' . $result_error . "\n", 3, STORE_PAGE_PARSE_TIME_LOG);
                }
                return $result;
                break;
            case 'MYSQLI':
                if (!is_object($mh_db->link)) {
                    // try to reconnect if link is lost
                    tep_db_connect();
                }

                $result = mysqli_query($mh_db->link, $query) or tep_db_error($query, mysqli_errno($mh_db->link), mysqli_error($mh_db->link));

                if (defined('STORE_DB_TRANSACTIONS') && (STORE_DB_TRANSACTIONS == 'true')) {
                    $result_error = mysqli_error($mh_db->link);
                    error_log('RESULT ' . $result . ' ' . $result_error . "\n", 3, STORE_PAGE_PARSE_TIME_LOG);
                }
                return $result;
                break;
            default:
//                echo 'DB Type not supported';
        }

    }

}


if (!function_exists('tep_db_perform')) {

    function tep_db_perform($table, $data, $action = 'insert', $parameters = '', $link = 'db_link')
    {
        if (!is_array($data)) {
            return false;
        }

        reset($data);
        if ($action == 'insert') {
            $query = 'insert into ' . tep_db_input_field($table) . ' (';
            foreach ($data as $columns => $v) {
                $query .= tep_db_input_field($columns) . ', ';
            }
            $query = substr($query, 0, -2) . ') values (';
            reset($data);
            foreach ($data as $i => $value) {

                switch ((string)$value) {
                    case 'now()':
                        $query .= 'now(), ';
                        break;
                    case 'null':
                        $query .= 'null, ';
                        break;
                    default:
                        $query .= '\'' . tep_db_input($value) . '\', ';
                        break;
                }
            }
            $query = substr($query, 0, -2) . ')';
        } elseif ($action == 'update') {
            $query = 'update ' . tep_db_input_field($table) . ' set ';
            foreach ($data as $columns => $value) {

                switch ((string)$value) {
                    case 'now()':
                        $query .= tep_db_input_field($columns) . ' = now(), ';
                        break;
                    case 'null':
                        $query .= tep_db_input_field($columns) . ' = null, ';
                        break;
                    default:
                        $query .= tep_db_input_field($columns) . ' = \'' . tep_db_input($value) . '\', ';
                        break;
                }
            }
            $query = substr($query, 0, -2) . ' where ' . $parameters;
        }

        return tep_db_query($query, $link);
    }

}

if (!function_exists('tep_db_fetch_array')) {

    function tep_db_fetch_array($mh_db_query)
    {
        switch (MH_DBTYPE) {
            case 'MYSQL':
                return mysql_fetch_array($mh_db_query, MYSQL_ASSOC);
                break;
            case 'MYSQLI':
                return mysqli_fetch_array($mh_db_query, MYSQLI_ASSOC);
                break;
            default:
                echo 'DB Type not supported';
        }
    }

}

if (!function_exists('tep_db_num_rows')) {

    function tep_db_num_rows($mh_db_query)
    {
        switch (MH_DBTYPE) {
            case 'MYSQL':
                return mysql_num_rows($mh_db_query);
                break;
            case 'MYSQLI':
                return mysqli_num_rows($mh_db_query);
                break;
            default:
                echo 'DB Type not supported';
        }
    }

}


if (!function_exists('tep_db_data_seek')) {

    function tep_db_data_seek($mh_db_query, $row_number)
    {
        switch (MH_DBTYPE) {
            case 'MYSQL':
                return mysql_data_seek($mh_db_query, $row_number);
                break;
            case 'MYSQLI':
                return mysqli_data_seek($mh_db_query, $row_number);
                break;
            default:
                echo 'DB Type not supported';
        }
    }

}

if (!function_exists('tep_db_insert_id')) {

    function tep_db_insert_id($link = 'db_link')
    {
        global $mh_db;

        switch (MH_DBTYPE) {
            case 'MYSQL':
                return mysql_insert_id($mh_db->link);
                break;
            case 'MYSQLI':
                return mysqli_insert_id($mh_db->link);
                break;
            default:
                echo 'DB Type not supported';
        }
    }

}

if (!function_exists('tep_db_free_result')) {

    function tep_db_free_result($mh_db_query)
    {
        switch (MH_DBTYPE) {
            case 'MYSQL':
                return mysql_free_result($mh_db_query);
                break;
            case 'MYSQLI':
                return mysqli_free_result($mh_db_query);
                break;
            default:
                echo 'DB Type not supported';
        }

    }

}


if (!function_exists('tep_db_fetch_fields')) {

    function tep_db_fetch_fields($mh_db_query)
    {
        switch (MH_DBTYPE) {
            case 'MYSQL':
                return mysql_fetch_field($mh_db_query);
                break;
            case 'MYSQLI':
                return mysqli_fetch_field($mh_db_query);
                break;
            default:
                echo 'DB Type not supported';
        }
    }

}

if (!function_exists('tep_db_output')) {

    function tep_db_output($string)
    {
        return htmlspecialchars($string);
    }

}

if (!function_exists('tep_db_input')) {

    function tep_db_input($string, $link = 'db_link')
    {
        global $mh_db;

        if ($string === null) {
            return '';
        }

        switch (MH_DBTYPE) {
            case 'MYSQL':
                if (function_exists('mysql_real_escape_string')) {
                    return mysql_real_escape_string((string)$string, $mh_db->link);
                } elseif (function_exists('mysql_escape_string')) {
                    return mysql_escape_string((string)$string);
                }
                return addslashes((string)$string);
                break;
            case 'MYSQLI':
                if (isset($mh_db->link) && is_object($mh_db->link) && $mh_db->link instanceof mysqli) {
                    return mysqli_real_escape_string($mh_db->link, (string)$string);
                }
                return addslashes((string)$string);
                break;
            default:
                return addslashes((string)$string);
        }
    }

}

if (!function_exists('tep_db_input_field')) {

    function tep_db_input_field($identifier)
    {
        return '`' . str_replace('`', '``', (string)$identifier) . '`';
    }

}


if (!function_exists('tep_db_prepare_input')) {

    function tep_db_prepare_input($string)
    {
        if (is_string($string)) {
            return trim(stripslashes($string));
        } elseif (is_array($string)) {
            reset($string);
            foreach ($string as $key => $value) {
                $string[$key] = tep_db_prepare_input($value);
            }
            return $string;
        } else {
            return $string;
        }
    }

}


if (!function_exists('mysqli_connect')) {

    define('MYSQLI_ASSOC', MYSQL_ASSOC);

    function mysqli_connect($server, $username, $password, $database)
    {
        $server = (string)$server;
        if (strpos($server, 'p:') === 0) {
            $link = mysql_pconnect(substr($server, 2), $username, $password);
        } else {
            $link = mysql_connect($server, $username, $password);
        }

        if ($link) {
            mysql_select_db($database, $link);
        }

        return $link;
    }

    function mysqli_close($link)
    {
        return mysql_close($link);
    }

    function mysqli_query($link, $query)
    {
        return mysql_query($query, $link);
    }

    function mysqli_errno($link = null)
    {
        return mysql_errno($link);
    }

    function mysqli_error($link = null)
    {
        return mysql_error($link);
    }

    function mysqli_fetch_array($query, $type)
    {
        return mysql_fetch_array($query, $type);
    }

    function mysqli_num_rows($query)
    {
        return mysql_num_rows($query);
    }

    function mysqli_data_seek($query, $offset)
    {
        return mysql_data_seek($query, $offset);
    }

    function mysqli_insert_id($link)
    {
        return mysql_insert_id($link);
    }

    function mysqli_free_result($query)
    {
        return mysql_free_result($query);
    }

    function mysqli_fetch_field($query)
    {
        return mysql_fetch_field($query);
    }

    function mysqli_real_escape_string($link, $string)
    {
        if (function_exists('mysql_real_escape_string')) {
            return mysql_real_escape_string($string, $link);
        } elseif (function_exists('mysql_escape_string')) {
            return mysql_escape_string($string);
        }

        return addslashes($string);
    }

    function mysqli_affected_rows($link)
    {
        return mysql_affected_rows($link);
    }

    function mysqli_get_server_info($link)
    {
        return mysql_get_server_info($link);
    }
}

if (isset($db) && is_object($db) && get_class($db) == 'queryFactory') {
    tep_db_connect();
}
