From e85c7fd57887124dd64be1d125f8b393fc6e096d Mon Sep 17 00:00:00 2001 From: Daniel Messer Date: Wed, 8 Oct 2025 15:40:14 -0500 Subject: [PATCH] Security and functional improvements to results.php --- archive/results-old.php | 381 +++++++++++++++++++++++++++++++++++ results.php | 437 ++++++++++++++++++++-------------------- 2 files changed, 602 insertions(+), 216 deletions(-) create mode 100644 archive/results-old.php diff --git a/archive/results-old.php b/archive/results-old.php new file mode 100644 index 0000000..af793c9 --- /dev/null +++ b/archive/results-old.php @@ -0,0 +1,381 @@ +query("SELECT +DISTINCT books.id AS id, +books.title AS title, +SUBSTR(comments.text,0,120) AS excerpt +FROM books +INNER JOIN +comments ON comments.book = books.id +INNER JOIN +books_tags_link ON books_tags_link.book = books.id +INNER JOIN +tags ON tags.id = books_tags_link.tag +WHERE books.title LIKE '%$keywordsearch%' +OR books.author_sort LIKE '%$keywordsearch%' +OR comments.text LIKE '%$keywordsearch%' +OR tags.name LIKE '%$keywordsearch%' +ORDER BY books.title ASC"); + +$authorquery = $db->query("SELECT +DISTINCT books.id AS id, +books.title AS title, +SUBSTR(comments.text,0,120) AS excerpt +FROM books +INNER JOIN +comments ON comments.book = books.id +INNER JOIN +books_tags_link ON books_tags_link.book = books.id +WHERE books.author_sort LIKE '%$authorsearch%' +ORDER BY books.title ASC"); + +$typequery = $db->query("SELECT +DISTINCT books.id AS id, +books.title AS title, +SUBSTR(comments.text,0,120) AS excerpt +FROM books +INNER JOIN +comments ON comments.book = books.id +INNER JOIN +books_custom_column_1_link ON books_custom_column_1_link.book = books.id +INNER JOIN +custom_column_1 ON custom_column_1.id = books_custom_column_1_link.value +WHERE +custom_column_1.value = '$typesearch' +ORDER BY books.title ASC"); + +$subtypequery = $db->query("SELECT +DISTINCT books.id AS id, +books.title AS title, +SUBSTR(comments.text,0,120) AS excerpt +FROM books +INNER JOIN +comments ON comments.book = books.id +INNER JOIN +books_custom_column_3_link ON books_custom_column_3_link.book = books.id +INNER JOIN +custom_column_3 ON custom_column_3.id = books_custom_column_3_link.value +WHERE +custom_column_3.value = '$subtypesearch' +ORDER BY books.title ASC"); + +$seriesquery = $db->query("SELECT +DISTINCT books.id AS id, +books.title AS title, +SUBSTR(comments.text,0,120) AS excerpt +FROM books +INNER JOIN +comments ON comments.book = books.id +INNER JOIN +books_series_link ON books_series_link.book = books.id +INNER JOIN +series ON series.id = books_series_link.series +WHERE series.name = '$seriessearch' +ORDER BY books.series_index ASC"); + +$subjectquery = $db->query("SELECT +DISTINCT books.id AS id, +books.title AS title, +SUBSTR(comments.text,0,120) AS excerpt +FROM books +INNER JOIN +comments ON comments.book = books.id +INNER JOIN +books_tags_link on books_tags_link.book = books.id +INNER JOIN +tags on tags.id = books_tags_link.tag +WHERE tags.name = '$subjectsearch' +ORDER BY books.title ASC"); + +$types = $db->query("SELECT +value +FROM custom_column_1 +ORDER BY value ASC"); + +$subtypes = $db->query("SELECT +value +FROM custom_column_3 +ORDER BY value ASC"); + +?> + + + + + + + + + + + Infopump - Search results - <?php echo $searchtopic; ?> + + + + + + + + + ';?> + + ';?> + + '; + echo ''; + } elseif (!empty($authorsearch)) { + echo ''; + echo ''; + } elseif (!empty($typesearch)) { + echo ''; + echo ''; + } elseif (!empty($seriessearch)) { + echo ''; + echo ''; + } elseif (!empty($subjectsearch)) { + echo ''; + echo ''; + } else { + echo ''; + echo ''; + } + ?> + + ';?> + + ';?> + + ';?> + + ';?> + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Close +
+
+ Infopump Avatar +
+

About the Project

+

Infopump

+

A bibliographic management and display system.

+
+

A free, open source project from:
+ The L0WL1F3 Podcast
+ Neon Dystopia
+ Cyberpunk Librarian +

+
    + + +
+
+ +
+
+

Recent Additions

+
    + fetchArray()) { + $row_value = $row['value']; + $row_titlecase = mb_convert_case($row_value, MB_CASE_TITLE, "UTF-8"); + echo '
  • '.$row_titlecase.'
  • '; + //echo '
  • '.$row_value.'
  • '; + + } + ?> +
+
+
+

Search

+
+
+ +
+
+
+
+
+ + +
+ +
+ +
+ + + + +
+ +
+ +
+ +
+
+
+
+
+
+ fetchArray()) { + $row_id = $row['id']; + $row_title = $row['title']; + $row_excerpt = $row['excerpt']; + + echo '

'.$row_title.' : '.strip_tags($row_excerpt).'...

'; + } + } elseif ($typesearch != '') { + while ($row = $typequery->fetchArray()) { + $row_id = $row['id']; + $row_title = $row['title']; + $row_excerpt = $row['excerpt']; + + echo '

'.$row_title.' : '.strip_tags($row_excerpt).'...

'; + } + } elseif ($authorsearch != '') { + while ($row = $authorquery->fetchArray()) { + $row_id = $row['id']; + $row_title = $row['title']; + $row_excerpt = $row['excerpt']; + + echo '

'.$row_title.' : '.strip_tags($row_excerpt).'...

'; + } + } elseif ($seriessearch != '') { + while ($row = $seriesquery->fetchArray()) { + $row_id = $row['id']; + $row_title = $row['title']; + $row_excerpt = $row['excerpt']; + + echo '

'.$row_title.' : '.strip_tags($row_excerpt).'...

'; + } + } elseif ($subjectsearch != '') { + while ($row = $subjectquery->fetchArray()) { + $row_id = $row['id']; + $row_title = $row['title']; + $row_excerpt = $row['excerpt']; + + echo '

'.$row_title.' : '.strip_tags($row_excerpt).'...

'; + } + } else { + while ($row = $subtypequery->fetchArray()) { + $row_id = $row['id']; + $row_title = $row['title']; + $row_excerpt = $row['excerpt']; + + echo '

'.$row_title.' : '.strip_tags($row_excerpt).'...

'; + } + } + ?> +
+
+ +
+
+
+
+ + + + + + + + + + + + + + + + + diff --git a/results.php b/results.php index af793c9..162c5ab 100644 --- a/results.php +++ b/results.php @@ -2,140 +2,200 @@ include_once "settings.php"; -// Get and use a basic title search for pulling records. -$keywordsearch = htmlspecialchars($_GET["kw"]); -$authorsearch = htmlspecialchars($_GET["au"]); -$typesearch = htmlspecialchars($_GET["ty"]); -$subtypesearch = htmlspecialchars($_GET["st"]); -$seriessearch = htmlspecialchars($_GET["se"]); -$subjectsearch = htmlspecialchars($_GET["su"]); +// Initialize variables +$keywordsearch = ''; +$authorsearch = ''; +$typesearch = ''; +$subtypesearch = ''; +$seriessearch = ''; +$subjectsearch = ''; +$searchtopic = ''; +$searchtype = ''; -$socialkw = mb_convert_case($keywordsearch, MB_CASE_TITLE, "UTF-8"); -$socialau = mb_convert_case($authorsearch, MB_CASE_TITLE, "UTF-8"); -$socialty = mb_convert_case($typesearch, MB_CASE_TITLE, "UTF-8"); -$socialst = mb_convert_case($subtypesearch, MB_CASE_TITLE, "UTF-8"); -$socialse = mb_convert_case($seriessearch, MB_CASE_TITLE, "UTF-8"); -$socialsu = mb_convert_case($subjectsearch, MB_CASE_TITLE, "UTF-8"); +// Sanitize and validate input +if (!empty($_GET["kw"])) { + $keywordsearch = trim($_GET["kw"]); + $searchtopic = 'Keyword: ' . htmlspecialchars($keywordsearch, ENT_QUOTES, 'UTF-8'); + $searchtype = 'keyword'; +} elseif (!empty($_GET["au"])) { + $authorsearch = trim($_GET["au"]); + $searchtopic = 'Author: ' . htmlspecialchars($authorsearch, ENT_QUOTES, 'UTF-8'); + $searchtype = 'author'; +} elseif (!empty($_GET["ty"])) { + $typesearch = trim($_GET["ty"]); + $searchtopic = 'Type: ' . htmlspecialchars(mb_convert_case($typesearch, MB_CASE_TITLE, "UTF-8"), ENT_QUOTES, 'UTF-8'); + $searchtype = 'type'; +} elseif (!empty($_GET["st"])) { + $subtypesearch = trim($_GET["st"]); + $searchtopic = 'Subtype: ' . htmlspecialchars(mb_convert_case($subtypesearch, MB_CASE_TITLE, "UTF-8"), ENT_QUOTES, 'UTF-8'); + $searchtype = 'subtype'; +} elseif (!empty($_GET["se"])) { + $seriessearch = trim($_GET["se"]); + $searchtopic = 'Series: ' . htmlspecialchars($seriessearch, ENT_QUOTES, 'UTF-8'); + $searchtype = 'series'; +} elseif (!empty($_GET["su"])) { + $subjectsearch = trim($_GET["su"]); + $searchtopic = 'Subject: ' . htmlspecialchars($subjectsearch, ENT_QUOTES, 'UTF-8'); + $searchtype = 'subject'; +} -if (!empty($keywordsearch)) { - $searchtopic = 'Keyword: '.$socialkw; -} elseif (!empty($authorsearch)) { - $searchtopic = 'Author: '.$socialau; -} elseif (!empty($typesearch)) { - $searchtopic = 'Type: '.$socialty; -} elseif (!empty($seriessearch)) { - $searchtopic = 'Series: '.$socialse; -} elseif (!empty($subjectsearch)) { - $searchtopic = 'Subject: '.$socialsu; -} else { - $searchtopic = 'Subtype: '.$socialst; +// If no valid search parameter, redirect to index +if (empty($searchtype)) { + header('Location: index.php'); + exit; } // -------------------- BEGIN DATABASE QUERIES -------------------- -// Establish atabase connection -$db = new SQLite3('metadata.sqlite'); +// Establish database connection +try { + $db = new SQLite3('metadata.sqlite'); + $db->enableExceptions(true); +} catch (Exception $e) { + error_log("Database connection error: " . $e->getMessage()); + die("Database connection failed"); +} -$keywordquery = $db->query("SELECT -DISTINCT books.id AS id, -books.title AS title, -SUBSTR(comments.text,0,120) AS excerpt -FROM books -INNER JOIN -comments ON comments.book = books.id -INNER JOIN -books_tags_link ON books_tags_link.book = books.id -INNER JOIN -tags ON tags.id = books_tags_link.tag -WHERE books.title LIKE '%$keywordsearch%' -OR books.author_sort LIKE '%$keywordsearch%' -OR comments.text LIKE '%$keywordsearch%' -OR tags.name LIKE '%$keywordsearch%' -ORDER BY books.title ASC"); +// Prepare the appropriate query based on search type +$results = null; -$authorquery = $db->query("SELECT -DISTINCT books.id AS id, -books.title AS title, -SUBSTR(comments.text,0,120) AS excerpt -FROM books -INNER JOIN -comments ON comments.book = books.id -INNER JOIN -books_tags_link ON books_tags_link.book = books.id -WHERE books.author_sort LIKE '%$authorsearch%' -ORDER BY books.title ASC"); +switch ($searchtype) { + case 'keyword': + $searchPattern = '%' . $keywordsearch . '%'; + $stmt = $db->prepare("SELECT + DISTINCT books.id AS id, + books.title AS title, + SUBSTR(comments.text, 0, 120) AS excerpt + FROM books + INNER JOIN comments ON comments.book = books.id + INNER JOIN books_tags_link ON books_tags_link.book = books.id + INNER JOIN tags ON tags.id = books_tags_link.tag + WHERE books.title LIKE :search + OR books.author_sort LIKE :search + OR comments.text LIKE :search + OR tags.name LIKE :search + ORDER BY books.title ASC + LIMIT 100"); + $stmt->bindValue(':search', $searchPattern, SQLITE3_TEXT); + break; + + case 'author': + $searchPattern = '%' . $authorsearch . '%'; + $stmt = $db->prepare("SELECT + DISTINCT books.id AS id, + books.title AS title, + SUBSTR(comments.text, 0, 120) AS excerpt + FROM books + INNER JOIN comments ON comments.book = books.id + INNER JOIN books_tags_link ON books_tags_link.book = books.id + WHERE books.author_sort LIKE :search + ORDER BY books.title ASC + LIMIT 100"); + $stmt->bindValue(':search', $searchPattern, SQLITE3_TEXT); + break; + + case 'type': + $stmt = $db->prepare("SELECT + DISTINCT books.id AS id, + books.title AS title, + SUBSTR(comments.text, 0, 120) AS excerpt + FROM books + INNER JOIN comments ON comments.book = books.id + INNER JOIN books_custom_column_1_link ON books_custom_column_1_link.book = books.id + INNER JOIN custom_column_1 ON custom_column_1.id = books_custom_column_1_link.value + WHERE custom_column_1.value = :search + ORDER BY books.title ASC + LIMIT 100"); + $stmt->bindValue(':search', $typesearch, SQLITE3_TEXT); + break; + + case 'subtype': + $stmt = $db->prepare("SELECT + DISTINCT books.id AS id, + books.title AS title, + SUBSTR(comments.text, 0, 120) AS excerpt + FROM books + INNER JOIN comments ON comments.book = books.id + INNER JOIN books_custom_column_3_link ON books_custom_column_3_link.book = books.id + INNER JOIN custom_column_3 ON custom_column_3.id = books_custom_column_3_link.value + WHERE custom_column_3.value = :search + ORDER BY books.title ASC + LIMIT 100"); + $stmt->bindValue(':search', $subtypesearch, SQLITE3_TEXT); + break; + + case 'series': + $stmt = $db->prepare("SELECT + DISTINCT books.id AS id, + books.title AS title, + SUBSTR(comments.text, 0, 120) AS excerpt + FROM books + INNER JOIN comments ON comments.book = books.id + INNER JOIN books_series_link ON books_series_link.book = books.id + INNER JOIN series ON series.id = books_series_link.series + WHERE series.name = :search + ORDER BY books.series_index ASC + LIMIT 100"); + $stmt->bindValue(':search', $seriessearch, SQLITE3_TEXT); + break; + + case 'subject': + $stmt = $db->prepare("SELECT + DISTINCT books.id AS id, + books.title AS title, + SUBSTR(comments.text, 0, 120) AS excerpt + FROM books + INNER JOIN comments ON comments.book = books.id + INNER JOIN books_tags_link ON books_tags_link.book = books.id + INNER JOIN tags ON tags.id = books_tags_link.tag + WHERE tags.name = :search + ORDER BY books.title ASC + LIMIT 100"); + $stmt->bindValue(':search', $subjectsearch, SQLITE3_TEXT); + break; +} -$typequery = $db->query("SELECT -DISTINCT books.id AS id, -books.title AS title, -SUBSTR(comments.text,0,120) AS excerpt -FROM books -INNER JOIN -comments ON comments.book = books.id -INNER JOIN -books_custom_column_1_link ON books_custom_column_1_link.book = books.id -INNER JOIN -custom_column_1 ON custom_column_1.id = books_custom_column_1_link.value -WHERE -custom_column_1.value = '$typesearch' -ORDER BY books.title ASC"); +// Execute query and handle errors +try { + $results = $stmt->execute(); +} catch (Exception $e) { + error_log("Query execution error: " . $e->getMessage()); + $results = null; +} -$subtypequery = $db->query("SELECT -DISTINCT books.id AS id, -books.title AS title, -SUBSTR(comments.text,0,120) AS excerpt -FROM books -INNER JOIN -comments ON comments.book = books.id -INNER JOIN -books_custom_column_3_link ON books_custom_column_3_link.book = books.id -INNER JOIN -custom_column_3 ON custom_column_3.id = books_custom_column_3_link.value -WHERE -custom_column_3.value = '$subtypesearch' -ORDER BY books.title ASC"); +// Get types for menu +try { + $types = $db->query("SELECT value FROM custom_column_1 ORDER BY value ASC"); +} catch (Exception $e) { + error_log("Types query error: " . $e->getMessage()); + $types = null; +} -$seriesquery = $db->query("SELECT -DISTINCT books.id AS id, -books.title AS title, -SUBSTR(comments.text,0,120) AS excerpt -FROM books -INNER JOIN -comments ON comments.book = books.id -INNER JOIN -books_series_link ON books_series_link.book = books.id -INNER JOIN -series ON series.id = books_series_link.series -WHERE series.name = '$seriessearch' -ORDER BY books.series_index ASC"); - -$subjectquery = $db->query("SELECT -DISTINCT books.id AS id, -books.title AS title, -SUBSTR(comments.text,0,120) AS excerpt -FROM books -INNER JOIN -comments ON comments.book = books.id -INNER JOIN -books_tags_link on books_tags_link.book = books.id -INNER JOIN -tags on tags.id = books_tags_link.tag -WHERE tags.name = '$subjectsearch' -ORDER BY books.title ASC"); - -$types = $db->query("SELECT -value -FROM custom_column_1 -ORDER BY value ASC"); - -$subtypes = $db->query("SELECT -value -FROM custom_column_3 -ORDER BY value ASC"); +// Build social media URLs safely +$socialUrl = ''; +switch ($searchtype) { + case 'keyword': + $socialUrl = $SiteURL . '/results.php?kw=' . urlencode($keywordsearch); + break; + case 'author': + $socialUrl = $SiteURL . '/results.php?au=' . urlencode($authorsearch); + break; + case 'type': + $socialUrl = $SiteURL . '/results.php?ty=' . urlencode($typesearch); + break; + case 'subtype': + $socialUrl = $SiteURL . '/results.php?st=' . urlencode($subtypesearch); + break; + case 'series': + $socialUrl = $SiteURL . '/results.php?se=' . urlencode($seriessearch); + break; + case 'subject': + $socialUrl = $SiteURL . '/results.php?su=' . urlencode($subjectsearch); + break; +} ?> - @@ -144,9 +204,9 @@ ORDER BY value ASC"); - Infopump - Search results - <?php echo $searchtopic; ?> + Infopump - Search results - <?php echo htmlspecialchars($searchtopic, ENT_QUOTES, 'UTF-8'); ?> - + @@ -165,42 +225,14 @@ ORDER BY value ASC"); --> - ';?> - - ';?> - - '; - echo ''; - } elseif (!empty($authorsearch)) { - echo ''; - echo ''; - } elseif (!empty($typesearch)) { - echo ''; - echo ''; - } elseif (!empty($seriessearch)) { - echo ''; - echo ''; - } elseif (!empty($subjectsearch)) { - echo ''; - echo ''; - } else { - echo ''; - echo ''; - } - ?> - - ';?> - - ';?> - - ';?> - - ';?> - - - + + + + + + + + @@ -213,10 +245,8 @@ ORDER BY value ASC"); - - @@ -253,12 +283,12 @@ ORDER BY value ASC");

Recent Additions

@@ -267,7 +297,7 @@ ORDER BY value ASC");

Search

- +
@@ -287,7 +317,7 @@ ORDER BY value ASC");
  • -->
    -

    Search Results

    +

    Search Results

    @@ -303,55 +333,26 @@ ORDER BY value ASC");
    fetchArray()) { - $row_id = $row['id']; - $row_title = $row['title']; - $row_excerpt = $row['excerpt']; - - echo '

    '.$row_title.' : '.strip_tags($row_excerpt).'...

    '; + if ($results) { + $hasResults = false; + while ($row = $results->fetchArray(SQLITE3_ASSOC)) { + $hasResults = true; + $row_id = (int)$row['id']; + $row_title = htmlspecialchars($row['title'], ENT_QUOTES, 'UTF-8'); + $row_excerpt = htmlspecialchars(strip_tags($row['excerpt']), ENT_QUOTES, 'UTF-8'); + + echo '

    '; + echo '' . $row_title . ''; + echo '' . $row_title . ' : '; + echo $row_excerpt . '...

    '; + } + + if (!$hasResults) { + echo '

    No results found for your search.

    '; + } + } else { + echo '

    An error occurred while searching. Please try again.

    '; } - } elseif ($typesearch != '') { - while ($row = $typequery->fetchArray()) { - $row_id = $row['id']; - $row_title = $row['title']; - $row_excerpt = $row['excerpt']; - - echo '

    '.$row_title.' : '.strip_tags($row_excerpt).'...

    '; - } - } elseif ($authorsearch != '') { - while ($row = $authorquery->fetchArray()) { - $row_id = $row['id']; - $row_title = $row['title']; - $row_excerpt = $row['excerpt']; - - echo '

    '.$row_title.' : '.strip_tags($row_excerpt).'...

    '; - } - } elseif ($seriessearch != '') { - while ($row = $seriesquery->fetchArray()) { - $row_id = $row['id']; - $row_title = $row['title']; - $row_excerpt = $row['excerpt']; - - echo '

    '.$row_title.' : '.strip_tags($row_excerpt).'...

    '; - } - } elseif ($subjectsearch != '') { - while ($row = $subjectquery->fetchArray()) { - $row_id = $row['id']; - $row_title = $row['title']; - $row_excerpt = $row['excerpt']; - - echo '

    '.$row_title.' : '.strip_tags($row_excerpt).'...

    '; - } - } else { - while ($row = $subtypequery->fetchArray()) { - $row_id = $row['id']; - $row_title = $row['title']; - $row_excerpt = $row['excerpt']; - - echo '

    '.$row_title.' : '.strip_tags($row_excerpt).'...

    '; - } - } ?>
    @@ -379,3 +380,7 @@ ORDER BY value ASC"); +close(); +?> \ No newline at end of file