Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 05/07/2023 in all areas

  1. They will input however they can. That may be via POST data, GET parameters, the URL path, HTTP headers, Cookies, etc. Anywhere that your program accepts external input has potential for bad data. If that external input is then used in some way in your SQL query, you have the potential for SQL Injection. They don't need to make their own form on their own host, they can just manipulate your form using a browser's Development tools or submit requests with a tool like cURL. What you're describing regarding using another server to host a fake form an entirely different security issue known as Cross-site request forgery and the solution to that is unique tokens as part of your form data. You're conflating things here. Hard-coding a value means you're just inputting a string or number or whatever directly where it needs to be. This can make maintainence or configuration changes harder as you need to change every place that value is needed. Defining values as a variable or constant means you can put the values in one place, then just re-use that variable/constant where needed. Using those variables/constants doesn't suddenly mean you are vulnerable to SQL injection. SQL injection is caused by using end-user having control over the value of variables used in your queries. Using variables that have a hard-coded value is fine. Using variables whose value comes from outside your control is a problem. You seem to have some idea about this being the case. Yes, if you have a specific set of safe values, and require your variable to be one of those values before it's used in a query, then that is ok. Your code doest at least make an attempt to validate that $table is an expected value via the check: if(!in_array($tables[$table],$tables)) { die('Invalid Table!'); } That check may work, but is not ideal. An invalid table value would give you E_NOTICE errors about an undefined index. Your $headings and $columns values would also be invalid since the invalid table doesn't exist. You should checking with isset or array_key_exists instead. You should also be checking this condition before you try and use the value for other things, not after. For example: $table = !empty($_POST['tbl']) ? $_POST['tbl'] : (!empty($_GET['tbl']) ? $_GET['tbl'] : 'spidered_web_index'); if (!isset($tables[$table])){ die('Invalid table'); } $headings = array_values($tables[$table]); $columns = array_keys($tables[$table]); Fundamentally, the difference between what is commonly called "procedural" vs "OOP" styles has to do with how data is handled, not code flow. Either way, code runs top to bottom within a block, and will jump randomly between blocks as you run functions, conditionals, etc. What's different is that with OOP, your classes hold both the context data they need and the functions to operate on that context. With procedural programming, the context gets passed around from function to function. In OOP, since the object owns it's context, it can control whether other parts of code are allowed to manipulate that context or not and the programmer cannot accidentally pass in the wrong context or just omit it entirely. With procedural, the program has to be sure to always pass along the context and make sure they pass along the correct context. For the mysqli API, you might have noticed that when you compare the function prototypes in the manual between the two styles, the procedural version usually has an extra parameter. eg: //OOP public mysqli_stmt::prepare(string $query): bool //Procedural mysqli_stmt_prepare(mysqli_stmt $statement, string $query): bool That extra $statement parameter is the context that you end up having to pass around from function to function when you code procedural style. If you pass in the wrong value, things break. In the OOP version of the API, that context is part of the object itself so there's no need to pass it between the functions. The functions can just grab it from the object they are being called on (the $this value in a class method). As a novice that's just using pre-made classes, there's little difference from your point of view, other than you end up typing $someObject->someMethod() instead of someMethod($someObject). When you start getting into writing libraries for others (or just yourself) to use in various projects, then you start seeing more of the benefits of OOP. Studying small libraries written in an OOP style may help to understand things more.
    1 point
  2. Both of those use some third party API which you'd likely have to sign up for. Since I've never looked into either of them, I don't know how they operate and can't really judge the code. If your goal is to avoid third-parties and having to pay for access, then neither solution is great. AI isn't magic, if you don't really know what to ask for or ask for something too generic then you won't get good results. Knowing what to ask and how to ask for it means you need some working knowledge of the topic. Part of the issue with your prompts is that Bitcoin doesn't have some official gateway api, so you're getting solutions using third-party APIs. The way to interact with the bitcoin network yourself is by running a local node and using it's built-in RPC server. Once you know that, by studying how bitcoin works, you can develop a proper prompt that will get you some reasonable starting code. Prompt: Write a function in PHP that confirms a bitcoin transaction using a local node RPC server. /** * This function confirms a Bitcoin transaction using a local node RPC server. * * @param string $txid The transaction ID to confirm * @param string $rpc_user The RPC server username * @param string $rpc_password The RPC server password * @param string $rpc_host The RPC server host * @param int $rpc_port The RPC server port * * @return bool True if the transaction is confirmed, false otherwise */ function confirm_bitcoin_transaction($txid, $rpc_user, $rpc_password, $rpc_host, $rpc_port) { try { // Create a new RPC client instance $client = new \Nbobtc\Bitcoind\RpcClient($rpc_user, $rpc_password, $rpc_host, $rpc_port); // Get the transaction details $transaction = $client->getTransaction($txid); // Check if the transaction is confirmed if ($transaction['confirmations'] > 0) { return true; } else { return false; } } catch (\Exception $e) { // Log the error error_log("Error confirming Bitcoin transaction: " . $e->getMessage()); return false; } } This code is using some library to interface with the RPC server, you'll need to either find that library or write your own code to interact with the server. Yes, finding an AI forum (for ChatGPT or otherwise) would be ideal. I do not know of any. As far as crypto forums, the only one I know of is Bitcoin Talk. I'm sure your favorite search engine could help you find more for any subject.
    1 point
  3. <?php //TEMPLATE. //FULLY WORKING! //COMPLETE! //mysqli_stmt_store_result(). //mysqli_stmt_free_result(). //$rows_count = mysqli_stmt_num_rows($stmt). //mysqli_stmt_get_result(). //http_build_query(). //Report Error. ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL); //Valid $_GET Items. //$tables = array('spidered_web_index','$submitted_web_index','$items_listings','visiting_history','following_history'); $spidered_web_index = ['id', 'date_and_time', 'domain', 'url', 'title', 'header', 'meta_keyword', 'meta_description', 'keyword', 'keyphrase']; $submitted_web_index = ['id', 'date_and_time', 'domain', 'url', 'title', 'description', 'country', 'keyword', 'keyphrase']; $items_listings = ['id', 'date_and_time', 'item', 'brand', 'manufacturer', 'model', 'heading', 'year', 'description', 'price', 'country', 'keyword', 'keyphrase']; $visiting_history = ['id', 'date_and_time', 'searcher', 'domain', 'url', 'title', 'header', 'description', 'country', 'meta_keyword', 'meta_description', 'keyword', 'keyphrase']; $following_history = ['id', 'date_and_time', 'searcher', 'follower', 'domain', 'url', 'title', 'header', 'description', 'country', 'meta_keyword', 'meta_description', 'keyword', 'keyphrase']; $tables = [ 'spidered_web_index' => [ 'id' => 'ID', 'date_and_time' => 'Date & Time', 'domain' => 'Domain', 'domain_point' => 'Domain Point', 'url' => 'Url', 'url' => 'Url Point', 'title' => 'Title', 'title' => 'Title Point', 'heading_1' => 'Heading 1', 'heading_1_point' => 'Heading 1 Point', 'heading_2' => 'Heading 2', 'heading_2_point' => 'Heading 2 Point', 'heading_3' => 'Heading 3', 'heading_3_point' => 'Heading 3 Point', 'heading_4' => 'Heading 4', 'heading_4_point' => 'Heading 4 Point', 'heading_5' => 'Heading 5', 'heading_5_point' => 'Heading 5 Point', 'heading_6' => 'Heading 6', 'heading_6_point' => 'Heading 6 Point', 'keyword_superscript' => 'Keyword Superscript', 'keyword_superscript' => 'Keyword superscript', 'keyword_strong' => 'Keyword Strong', 'keyword_strong' => 'Keyword Strong', 'keyword_emphasised' => 'Keyword Emphasised', 'keyword_emphasised' => 'Keyword Emphasised', 'keyword_bold' => 'Keyword Bold', 'keyword_bold' => 'Keyword Bold', 'keyword_italic' => 'Keyword Italic', 'keyword_italic' => 'Keyword Italic', 'keyword_marked' => 'Keyword Marked', 'keyword_marked' => 'Keyword Marked', 'keyword_inserted' => 'Keyword Inserted', 'keyword_inserted' => 'Keyword Inserted', 'keyword_deleted' => 'Keyword Deleted', 'keyword_deleted' => 'Keyword Deleted', 'keyword_small' => 'Keyword Small', 'keyword_small' => 'Keyword Small', 'keyword_subscript' => 'Keyword Subscript', 'keyword_subscript' => 'Keyword Subscript', ], 'submitted_web_index' => [ 'id' => 'ID', 'date_and_time' => 'Date & Time', 'domain' => 'Domain', 'domain_point' => 'Domain Point', 'url' => 'Url', 'url' => 'Url Point', 'title' => 'Title', 'title' => 'Title Point', 'heading_1' => 'Heading 1', 'heading_1_point' => 'Heading 1 Point', 'heading_2' => 'Heading 2', 'heading_2_point' => 'Heading 2 Point', 'heading_3' => 'Heading 3', 'heading_3_point' => 'Heading 3 Point', 'heading_4' => 'Heading 4', 'heading_4_point' => 'Heading 4 Point', 'heading_5' => 'Heading 5', 'heading_5_point' => 'Heading 5 Point', 'heading_6' => 'Heading 6', 'heading_6_point' => 'Heading 6 Point', 'keyword_superscript' => 'Keyword Superscript', 'keyword_superscript' => 'Keyword superscript', 'keyword_strong' => 'Keyword Strong', 'keyword_strong' => 'Keyword Strong', 'keyword_emphasised' => 'Keyword Emphasised', 'keyword_emphasised' => 'Keyword Emphasised', 'keyword_bold' => 'Keyword Bold', 'keyword_bold' => 'Keyword Bold', 'keyword_italic' => 'Keyword Italic', 'keyword_italic' => 'Keyword Italic', 'keyword_marked' => 'Keyword Marked', 'keyword_marked' => 'Keyword Marked', 'keyword_inserted' => 'Keyword Inserted', 'keyword_inserted' => 'Keyword Inserted', 'keyword_deleted' => 'Keyword Deleted', 'keyword_deleted' => 'Keyword Deleted', 'keyword_small' => 'Keyword Small', 'keyword_small' => 'Keyword Small', 'keyword_subscript' => 'Keyword Subscript', 'keyword_subscript' => 'Keyword Subscript', ], 'links_crawls_drummin' => [ 'id' => "ID", 'date_and_time' => "Date and Time", 'domain' => "Domain", 'domain_point' => "Domain Point", 'url' => "URL", 'url_point' => "Url Point", 'title' => "Title", 'title_point' => "Title Point", 'header' => "Header", 'header_point' => "Header Point", 'kw_1' => "Keyword 1", 'kw_1_point' => "Keyword 1 Point", 'kw_2' => "Keyword 2", 'kw_2_point' => "Keyword 2 Point", 'kw_3' => "Keyword 3", 'kw_3_point' => "Keyword 3 Point", 'kw_4' => "Keyword 4", 'kw_4_point' => "Keyword 4 Point", 'description' => "Description", 'description_point' => "Description Point", ], 'links_submits_drummin' => [ 'id' => "ID", 'date_and_time' => "Date and Time", 'domain' => "Domain", 'domain_point' => "Domain Point", 'url' => "URL", 'url_point' => "Url Point", 'title' => "Title", 'title_point' => "Title Point", 'header' => "Header", 'header_point' => "Header Point", 'kw_1' => "Keyword 1", 'kw_1_point' => "Keyword 1 Point", 'kw_2' => "Keyword 2", 'kw_2_point' => "Keyword 2 Point", 'kw_3' => "Keyword 3", 'kw_3_point' => "Keyword 3 Point", 'kw_4' => "Keyword 4", 'kw_4_point' => "Keyword 4 Point", 'description' => "Description", 'description_point' => "Description Point", ], ]; //Extract $_GETs. $table = !empty($_POST['tbl']) ? $_POST['tbl'] : (!empty($_GET['tbl']) ? $_GET['tbl'] : 'spidered_web_index'); $column = !empty($_POST['col']) ? $_POST['col'] : (!empty($_GET['col']) ? $_GET['col'] : 'id'); $limit = !empty($_POST['lmt']) ? $_POST['lmt'] : (!empty($_GET['lmt']) ? $_GET['lmt'] : 1); $match = !empty($_POST['mtch']) ? $_POST['mtch'] : (!empty($_GET['mtch']) ? $_GET['mtch'] : 'fuzzy'); $search = !empty($_POST['srch']) ? $_POST['srch'] : (!empty($_GET['srch']) ? $_GET['srch'] : 'mobile'); $page = !empty($_GET['pg']) ? intval($_GET['pg']) : 1; $offset = $page * $limit - $limit; $headings = array_values($tables[$table]); $columns = array_keys($tables[$table]); echo $columns_count = count($columns); if (!in_array($column, $columns)) { die('Invalid Column!'); } if (!in_array($tables[$table], $tables)) { die('Invalid Table!'); } $search = !empty($search) && $match === 'fuzzy' ? str_replace('*', '%', $search) : $search; $char_types = str_repeat('s', $columns_count); $search_values = array_fill(0, $columns_count, $search); $comparator = $match === 'exact' ? '=' : 'LIKE'; $sql = "SELECT * FROM $table WHERE " . implode(" $comparator ? OR ", $columns) . " $comparator ? "; $sql .= "ORDER BY id DESC LIMIT $limit OFFSET $offset"; //Query DB. mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); $conn = mysqli_connect("localhost", "root", "", "buzz"); //mysqli_connect("server","user","password","db"); mysqli_set_charset($conn, 'utf8mb4'); if (mysqli_connect_errno()) { printf("Mysqli Connection Error: %s", mysqli_connect_error()); } $stmt = mysqli_stmt_init($conn); if (!mysqli_stmt_prepare($stmt, $sql)) { //Fetch Rows based on Row Limit per page. echo 'Mysqli Error: ' . mysqli_stmt_error($stmt); echo '<br>'; echo 'Mysqli Error No: ' . mysqli_stmt_errno($stmt); } else { mysqli_stmt_bind_param($stmt, $char_types, ...$search_values); mysqli_stmt_execute($stmt); mysqli_stmt_store_result($stmt); //Necessary to use with mysqli_stmt_num_rows() when SQL query is SELECT. echo '<br><br>'; echo '<br><br>'; echo '<br><br>'; echo '<br><br>'; //Fetch Matching Rows Count. //mysqli_stmt_num_rows() has to come after mysqli_stmt_store_result(). echo 'Total Result: ' . ($rows_count = mysqli_stmt_num_rows($stmt)); echo '<br><br>'; mysqli_stmt_free_result($stmt); //Is this really necessary ? if (!mysqli_stmt_prepare($stmt, $sql)) { //Fetch Rows based on Row Limit per page. echo 'Mysqli Error: ' . mysqli_stmt_error($stmt); echo '<br>'; echo 'Mysqli Error No: ' . mysqli_stmt_errno($stmt); } else { mysqli_stmt_bind_param($stmt, $char_types, ...$search_values); mysqli_stmt_execute($stmt); $result = mysqli_stmt_get_result($stmt); mysqli_stmt_free_result($stmt); //Is this really necessary ? while ($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) { for ($i = 0; $i < $columns_count; $i++) { echo '<b>' . $headings[$i] . ': </b>' . $row[$columns[$i]]; echo '<br>'; } } } } mysqli_stmt_close($stmt); mysqli_close($conn); echo 'Total Pages: ' . ($total_pages = ceil($rows_count / $limit)); echo '<br><br>'; $i = 0; while ($i < $total_pages) { $i++; $pagination_section_array = ["tbl" => "$table", "mtch" => "$match", "lmt" => "$limit", "srch" => "$search", "pg" => intval($i)]; $serps_url = $_SERVER['PHP_SELF'] . '?' . http_build_query($pagination_section_array, '', '&amp;'); //Did convert '&' to '&amp' and so NO need to add htmlspecialchars() when echoing link. if ($i == $page) { echo '<a href="' . $serps_url . '">' . "<b>$i</b>" . '</a>'; //No need to add htmlspecialchars(), to convert '&' to '&amp;', when echoing link here. } else { echo '<a href="' . $serps_url . '">' . "$i" . '</a>'; //No need to add htmlspecialchars(), to convert '&' to '&amp;', when echoing link here. } } echo '<br>'; ?> To improve this script, the first thing I would do is cut out the large arrays. So I would create a new directory called config and create a new file tables.php to hold the table configuration, like this: search-engine-project/ ├─ config/ │ ├─ tables.php Then in tables.php I would paste the large array: <?php return [ 'spidered_web_index' => [ 'id' => 'ID', 'date_and_time' => 'Date & Time', 'domain' => 'Domain', 'domain_point' => 'Domain Point', 'url' => 'Url', 'url' => 'Url Point', 'title' => 'Title', 'title' => 'Title Point', 'heading_1' => 'Heading 1', 'heading_1_point' => 'Heading 1 Point', 'heading_2' => 'Heading 2', 'heading_2_point' => 'Heading 2 Point', 'heading_3' => 'Heading 3', 'heading_3_point' => 'Heading 3 Point', 'heading_4' => 'Heading 4', 'heading_4_point' => 'Heading 4 Point', 'heading_5' => 'Heading 5', 'heading_5_point' => 'Heading 5 Point', 'heading_6' => 'Heading 6', 'heading_6_point' => 'Heading 6 Point', 'keyword_superscript' => 'Keyword Superscript', 'keyword_superscript' => 'Keyword superscript', 'keyword_strong' => 'Keyword Strong', 'keyword_strong' => 'Keyword Strong', 'keyword_emphasised' => 'Keyword Emphasised', 'keyword_emphasised' => 'Keyword Emphasised', 'keyword_bold' => 'Keyword Bold', 'keyword_bold' => 'Keyword Bold', 'keyword_italic' => 'Keyword Italic', 'keyword_italic' => 'Keyword Italic', 'keyword_marked' => 'Keyword Marked', 'keyword_marked' => 'Keyword Marked', 'keyword_inserted' => 'Keyword Inserted', 'keyword_inserted' => 'Keyword Inserted', 'keyword_deleted' => 'Keyword Deleted', 'keyword_deleted' => 'Keyword Deleted', 'keyword_small' => 'Keyword Small', 'keyword_small' => 'Keyword Small', 'keyword_subscript' => 'Keyword Subscript', 'keyword_subscript' => 'Keyword Subscript', ], 'submitted_web_index' => [ 'id' => 'ID', 'date_and_time' => 'Date & Time', 'domain' => 'Domain', 'domain_point' => 'Domain Point', 'url' => 'Url', 'url' => 'Url Point', 'title' => 'Title', 'title' => 'Title Point', 'heading_1' => 'Heading 1', 'heading_1_point' => 'Heading 1 Point', 'heading_2' => 'Heading 2', 'heading_2_point' => 'Heading 2 Point', 'heading_3' => 'Heading 3', 'heading_3_point' => 'Heading 3 Point', 'heading_4' => 'Heading 4', 'heading_4_point' => 'Heading 4 Point', 'heading_5' => 'Heading 5', 'heading_5_point' => 'Heading 5 Point', 'heading_6' => 'Heading 6', 'heading_6_point' => 'Heading 6 Point', 'keyword_superscript' => 'Keyword Superscript', 'keyword_superscript' => 'Keyword superscript', 'keyword_strong' => 'Keyword Strong', 'keyword_strong' => 'Keyword Strong', 'keyword_emphasised' => 'Keyword Emphasised', 'keyword_emphasised' => 'Keyword Emphasised', 'keyword_bold' => 'Keyword Bold', 'keyword_bold' => 'Keyword Bold', 'keyword_italic' => 'Keyword Italic', 'keyword_italic' => 'Keyword Italic', 'keyword_marked' => 'Keyword Marked', 'keyword_marked' => 'Keyword Marked', 'keyword_inserted' => 'Keyword Inserted', 'keyword_inserted' => 'Keyword Inserted', 'keyword_deleted' => 'Keyword Deleted', 'keyword_deleted' => 'Keyword Deleted', 'keyword_small' => 'Keyword Small', 'keyword_small' => 'Keyword Small', 'keyword_subscript' => 'Keyword Subscript', 'keyword_subscript' => 'Keyword Subscript', ], 'links_crawls_drummin' => [ 'id' => "ID", 'date_and_time' => "Date and Time", 'domain' => "Domain", 'domain_point' => "Domain Point", 'url' => "URL", 'url_point' => "Url Point", 'title' => "Title", 'title_point' => "Title Point", 'header' => "Header", 'header_point' => "Header Point", 'kw_1' => "Keyword 1", 'kw_1_point' => "Keyword 1 Point", 'kw_2' => "Keyword 2", 'kw_2_point' => "Keyword 2 Point", 'kw_3' => "Keyword 3", 'kw_3_point' => "Keyword 3 Point", 'kw_4' => "Keyword 4", 'kw_4_point' => "Keyword 4 Point", 'description' => "Description", 'description_point' => "Description Point", ], 'links_submits_drummin' => [ 'id' => "ID", 'date_and_time' => "Date and Time", 'domain' => "Domain", 'domain_point' => "Domain Point", 'url' => "URL", 'url_point' => "Url Point", 'title' => "Title", 'title_point' => "Title Point", 'header' => "Header", 'header_point' => "Header Point", 'kw_1' => "Keyword 1", 'kw_1_point' => "Keyword 1 Point", 'kw_2' => "Keyword 2", 'kw_2_point' => "Keyword 2 Point", 'kw_3' => "Keyword 3", 'kw_3_point' => "Keyword 3 Point", 'kw_4' => "Keyword 4", 'kw_4_point' => "Keyword 4 Point", 'description' => "Description", 'description_point' => "Description Point", ], ]; Then back to our main script I would then include the configuration like this: <?php ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL); $items_listings = ['id', 'date_and_time', 'item', 'brand', 'manufacturer', 'model', 'heading', 'year', 'description', 'price', 'country', 'keyword', 'keyphrase']; $visiting_history = ['id', 'date_and_time', 'searcher', 'domain', 'url', 'title', 'header', 'description', 'country', 'meta_keyword', 'meta_description', 'keyword', 'keyphrase']; $following_history = ['id', 'date_and_time', 'searcher', 'follower', 'domain', 'url', 'title', 'header', 'description', 'country', 'meta_keyword', 'meta_description', 'keyword', 'keyphrase']; // refactored part $tables = require 'config/tables.php'; $spidered_web_index = array_keys($tables['spidered_web_index']); $submitted_web_index = array_keys($tables['submitted_web_index']); // end refactored part //Extract $_GETs. $table = !empty($_POST['tbl']) ? $_POST['tbl'] : (!empty($_GET['tbl']) ? $_GET['tbl'] : 'spidered_web_index'); $column = !empty($_POST['col']) ? $_POST['col'] : (!empty($_GET['col']) ? $_GET['col'] : 'id'); $limit = !empty($_POST['lmt']) ? $_POST['lmt'] : (!empty($_GET['lmt']) ? $_GET['lmt'] : 1); $match = !empty($_POST['mtch']) ? $_POST['mtch'] : (!empty($_GET['mtch']) ? $_GET['mtch'] : 'fuzzy'); $search = !empty($_POST['srch']) ? $_POST['srch'] : (!empty($_GET['srch']) ? $_GET['srch'] : 'mobile'); $page = !empty($_GET['pg']) ? intval($_GET['pg']) : 1; $offset = $page * $limit - $limit; $headings = array_values($tables[$table]); $columns = array_keys($tables[$table]); echo $columns_count = count($columns); if (!in_array($column, $columns)) { die('Invalid Column!'); } if (!in_array($tables[$table], $tables)) { die('Invalid Table!'); } $search = !empty($search) && $match === 'fuzzy' ? str_replace('*', '%', $search) : $search; $char_types = str_repeat('s', $columns_count); $search_values = array_fill(0, $columns_count, $search); $comparator = $match === 'exact' ? '=' : 'LIKE'; $sql = "SELECT * FROM $table WHERE " . implode(" $comparator ? OR ", $columns) . " $comparator ? "; $sql .= "ORDER BY id DESC LIMIT $limit OFFSET $offset"; //Query DB. mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); $conn = mysqli_connect("localhost", "root", "", "buzz"); //mysqli_connect("server","user","password","db"); mysqli_set_charset($conn, 'utf8mb4'); if (mysqli_connect_errno()) { printf("Mysqli Connection Error: %s", mysqli_connect_error()); } $stmt = mysqli_stmt_init($conn); if (!mysqli_stmt_prepare($stmt, $sql)) { //Fetch Rows based on Row Limit per page. echo 'Mysqli Error: ' . mysqli_stmt_error($stmt); echo '<br>'; echo 'Mysqli Error No: ' . mysqli_stmt_errno($stmt); } else { mysqli_stmt_bind_param($stmt, $char_types, ...$search_values); mysqli_stmt_execute($stmt); mysqli_stmt_store_result($stmt); //Necessary to use with mysqli_stmt_num_rows() when SQL query is SELECT. echo '<br><br>'; echo '<br><br>'; echo '<br><br>'; echo '<br><br>'; //Fetch Matching Rows Count. //mysqli_stmt_num_rows() has to come after mysqli_stmt_store_result(). echo 'Total Result: ' . ($rows_count = mysqli_stmt_num_rows($stmt)); echo '<br><br>'; mysqli_stmt_free_result($stmt); //Is this really necessary ? if (!mysqli_stmt_prepare($stmt, $sql)) { //Fetch Rows based on Row Limit per page. echo 'Mysqli Error: ' . mysqli_stmt_error($stmt); echo '<br>'; echo 'Mysqli Error No: ' . mysqli_stmt_errno($stmt); } else { mysqli_stmt_bind_param($stmt, $char_types, ...$search_values); mysqli_stmt_execute($stmt); $result = mysqli_stmt_get_result($stmt); mysqli_stmt_free_result($stmt); //Is this really necessary ? while ($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) { for ($i = 0; $i < $columns_count; $i++) { echo '<b>' . $headings[$i] . ': </b>' . $row[$columns[$i]]; echo '<br>'; } } } } mysqli_stmt_close($stmt); mysqli_close($conn); echo 'Total Pages: ' . ($total_pages = ceil($rows_count / $limit)); echo '<br><br>'; $i = 0; while ($i < $total_pages) { $i++; $pagination_section_array = ["tbl" => "$table", "mtch" => "$match", "lmt" => "$limit", "srch" => "$search", "pg" => intval($i)]; $serps_url = $_SERVER['PHP_SELF'] . '?' . http_build_query($pagination_section_array, '', '&amp;'); //Did convert '&' to '&amp' and so NO need to add htmlspecialchars() when echoing link. if ($i == $page) { echo '<a href="' . $serps_url . '">' . "<b>$i</b>" . '</a>'; //No need to add htmlspecialchars(), to convert '&' to '&amp;', when echoing link here. } else { echo '<a href="' . $serps_url . '">' . "$i" . '</a>'; //No need to add htmlspecialchars(), to convert '&' to '&amp;', when echoing link here. } } echo '<br>'; ?> Then as the second step I would cut out the pagination HTML into a separate directory (html) and file (pagination.php), like this: search-engine-project/ ├─ config/ │ ├─ tables.php ├─ html/ │ ├─ pagination.php In our pagination.php file: <?php for ($i = 0; $i < $total_pages; $i++): ?> <a href="?<?= http_build_query(array_merge($pagination_section_array, ['pg' => $i]), '', '&amp;') ?>"> <?php if ($i == $page): ?> <b> <?php endif ?> <?= $i ?> <?php if ($i == $page): ?> </b> <?php endif ?> </a> <?php endfor ?> <br> Then back to our original script (scroll to the end): <?php ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL); $items_listings = ['id', 'date_and_time', 'item', 'brand', 'manufacturer', 'model', 'heading', 'year', 'description', 'price', 'country', 'keyword', 'keyphrase']; $visiting_history = ['id', 'date_and_time', 'searcher', 'domain', 'url', 'title', 'header', 'description', 'country', 'meta_keyword', 'meta_description', 'keyword', 'keyphrase']; $following_history = ['id', 'date_and_time', 'searcher', 'follower', 'domain', 'url', 'title', 'header', 'description', 'country', 'meta_keyword', 'meta_description', 'keyword', 'keyphrase']; $tables = require 'config/tables.php'; $spidered_web_index = array_keys($tables['spidered_web_index']); $submitted_web_index = array_keys($tables['submitted_web_index']); //Extract $_GETs. $table = !empty($_POST['tbl']) ? $_POST['tbl'] : (!empty($_GET['tbl']) ? $_GET['tbl'] : 'spidered_web_index'); $column = !empty($_POST['col']) ? $_POST['col'] : (!empty($_GET['col']) ? $_GET['col'] : 'id'); $limit = !empty($_POST['lmt']) ? $_POST['lmt'] : (!empty($_GET['lmt']) ? $_GET['lmt'] : 1); $match = !empty($_POST['mtch']) ? $_POST['mtch'] : (!empty($_GET['mtch']) ? $_GET['mtch'] : 'fuzzy'); $search = !empty($_POST['srch']) ? $_POST['srch'] : (!empty($_GET['srch']) ? $_GET['srch'] : 'mobile'); $page = !empty($_GET['pg']) ? intval($_GET['pg']) : 1; $offset = $page * $limit - $limit; $headings = array_values($tables[$table]); $columns = array_keys($tables[$table]); echo $columns_count = count($columns); if (!in_array($column, $columns)) { die('Invalid Column!'); } if (!in_array($tables[$table], $tables)) { die('Invalid Table!'); } $search = !empty($search) && $match === 'fuzzy' ? str_replace('*', '%', $search) : $search; $char_types = str_repeat('s', $columns_count); $search_values = array_fill(0, $columns_count, $search); $comparator = $match === 'exact' ? '=' : 'LIKE'; $sql = "SELECT * FROM $table WHERE " . implode(" $comparator ? OR ", $columns) . " $comparator ? "; $sql .= "ORDER BY id DESC LIMIT $limit OFFSET $offset"; //Query DB. mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); $conn = mysqli_connect("localhost", "root", "", "buzz"); //mysqli_connect("server","user","password","db"); mysqli_set_charset($conn, 'utf8mb4'); if (mysqli_connect_errno()) { printf("Mysqli Connection Error: %s", mysqli_connect_error()); } $stmt = mysqli_stmt_init($conn); if (!mysqli_stmt_prepare($stmt, $sql)) { //Fetch Rows based on Row Limit per page. echo 'Mysqli Error: ' . mysqli_stmt_error($stmt); echo '<br>'; echo 'Mysqli Error No: ' . mysqli_stmt_errno($stmt); } else { mysqli_stmt_bind_param($stmt, $char_types, ...$search_values); mysqli_stmt_execute($stmt); mysqli_stmt_store_result($stmt); //Necessary to use with mysqli_stmt_num_rows() when SQL query is SELECT. echo '<br><br>'; echo '<br><br>'; echo '<br><br>'; echo '<br><br>'; //Fetch Matching Rows Count. //mysqli_stmt_num_rows() has to come after mysqli_stmt_store_result(). echo 'Total Result: ' . ($rows_count = mysqli_stmt_num_rows($stmt)); echo '<br><br>'; mysqli_stmt_free_result($stmt); //Is this really necessary ? if (!mysqli_stmt_prepare($stmt, $sql)) { //Fetch Rows based on Row Limit per page. echo 'Mysqli Error: ' . mysqli_stmt_error($stmt); echo '<br>'; echo 'Mysqli Error No: ' . mysqli_stmt_errno($stmt); } else { mysqli_stmt_bind_param($stmt, $char_types, ...$search_values); mysqli_stmt_execute($stmt); $result = mysqli_stmt_get_result($stmt); mysqli_stmt_free_result($stmt); //Is this really necessary ? while ($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) { for ($i = 0; $i < $columns_count; $i++) { echo '<b>' . $headings[$i] . ': </b>' . $row[$columns[$i]]; echo '<br>'; } } } } mysqli_stmt_close($stmt); mysqli_close($conn); echo 'Total Pages: ' . ($total_pages = ceil($rows_count / $limit)); echo '<br><br>'; $pagination_section_array = ["tbl" => "$table", "mtch" => "$match", "lmt" => "$limit", "srch" => "$search"]; // refactored part require 'html/pagination.php'; // end refactored part ?> This way bit by bit, the code gets smaller, and easier to maintain.
    1 point
  4. Q1. yes, it needs a stored result to count the rows. Q2. yes, it clears the stored result from the internal buffer freeing memory. It's good practice to always clean up after yourself. Q3. either use mysqli_* or PDO, most people use PDO for its simple API. PDO has no pdo_* functions, only it's Object Oriented interface. Q4. bad, but not in the way of ugly or "newbie" but because it can be exploited by hackers; it will be hard to maintain (lots of duplicate code, weird indents, no separation between HTML and PHP, ..); using die() in a script is not good UX, the user can't get back to the homepage or try another search;
    1 point
  5. You avoid SQL injection when you use prepared statements assuming you write the full SQL and don't inject foreign SQL using variables. So while this is safe: mysqli_stmt_prepare($stmt, 'SELECT * FROM users WHERE username = ?'); This is not: mysqli_stmt_prepare($stmt, "SELECT * FROM $tbl WHERE $col_1 = ?"); Because now a hacker can control what the prepared statement is. So this could end up being: mysqli_stmt_prepare($stmt, "SELECT * FROM users; DELETE FROM users WHERE 1 = ?"); Which is not what you intended. -- I assume nobody told you, because I don't think anyone read over your code like I did. Walls of text do that to people. Which is why, as a programmer, we divide the program into little pieces like lego blocks. Building or re-using blocks to build a car or a house. We even have "rules" defining how small things should be: https://refactoring.guru/refactoring/smells/bloaters -- I assumed it was either a search engine or an SEO kinda tool. You might want to read up on cursor based pagination: https://medium.com/swlh/how-to-implement-cursor-pagination-like-a-pro-513140b65f32 as LIMIT OFFSET is not ideal for pagination (performance wise).
    1 point
This leaderboard is set to New York/GMT-05:00
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.