<?php
/**
* Administrative User Search Interface
* Secure and optimized version for PHP/MySQL
*/
// Start output buffering and include required files
ob_start();
require_once "include/bittorrent.php";
// Configuration
define('DEBUG_MODE', 0); // 0 - No debug; 1 - Show and run SQL query; 2 - Show SQL query only
define('RECORDS_PER_PAGE', 30);
define('GB_UNIT', 1073741824); // 1GB in bytes
// Security checks
dbconn();
loggedinorreturn();
if (get_user_class() < UC_SUPERMOD) {
stderr("Error", "Access denied. Only accessible by SUPERMODERATORS.");
}
// Initialize CSRF protection
if (!isset($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
stdhead("Administrative User Search");
/**
* Utility Functions
*/
class UserSearchValidator {
public static function sanitizeInput($input) {
return trim(htmlspecialchars($input, ENT_QUOTES, 'UTF-8'));
}
public static function validateDate($date) {
if (empty($date)) return false;
$separators = ['-', '/'];
$parts = null;
foreach ($separators as $sep) {
if (strpos($date, $sep) !== false) {
$parts = explode($sep, $date);
break;
}
}
if (!$parts || count($parts) !== 3) return false;
foreach ($parts as $part) {
if (!is_numeric($part)) return false;
}
if (checkdate($parts[1], $parts[2], $parts[0])) {
return date("Y-m-d", mktime(0, 0, 0, $parts[1], $parts[2], $parts[0]));
}
return false;
}
public static function validateIP($ip) {
return filter_var($ip, FILTER_VALIDATE_IP) !== false;
}
public static function validateEmail($email) {
return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}
public static function hasWildcard($text) {
return (strpos($text, '*') !== false || strpos($text, '?') !== false ||
strpos($text, '%') !== false || strpos($text, '_') !== false);
}
public static function validateNumeric($value, $min = 0) {
return is_numeric($value) && $value >= $min;
}
}
class UserSearchQuery {
private $where_conditions = [];
private $join_conditions = "";
private $query_params = [];
private $distinct = "";
public function addWhereCondition($condition) {
if (!empty($condition)) {
$this->where_conditions[] = $condition;
}
}
public function addJoinCondition($join) {
$this->join_conditions .= " " . $join;
}
public function setDistinct($distinct = true) {
$this->distinct = $distinct ? "DISTINCT " : "";
}
public function addQueryParam($param) {
$this->query_params[] = $param;
}
public function buildSearchCondition($field, $values, $exact_match = false, $use_like_wildcard = false) {
if (empty($values) || $values[0] === "") return "";
$includes = [];
$excludes = [];
foreach ($values as $value) {
if (substr($value, 0, 1) === '~') {
if ($value === '~') continue;
$excludes[] = substr($value, 1);
} else {
$includes[] = $value;
}
}
$conditions = [];
// Handle includes
if (!empty($includes)) {
$include_conditions = [];
foreach ($includes as $value) {
if ($use_like_wildcard) {
$include_conditions[] = "$field LIKE " . sqlesc("%$value%");
} elseif ($exact_match || !UserSearchValidator::hasWildcard($value)) {
$include_conditions[] = "$field = " . sqlesc($value);
} else {
$value = str_replace(['?', '*'], ['_', '%'], $value);
$include_conditions[] = "$field LIKE " . sqlesc($value);
}
}
if (!empty($include_conditions)) {
$conditions[] = "(" . implode(" OR ", $include_conditions) . ")";
}
}
// Handle excludes
if (!empty($excludes)) {
$exclude_conditions = [];
foreach ($excludes as $value) {
if ($use_like_wildcard) {
$exclude_conditions[] = "$field LIKE " . sqlesc("%$value%");
} elseif ($exact_match || !UserSearchValidator::hasWildcard($value)) {
$exclude_conditions[] = "$field = " . sqlesc($value);
} else {
$value = str_replace(['?', '*'], ['_', '%'], $value);
$exclude_conditions[] = "$field LIKE " . sqlesc($value);
}
}
if (!empty($exclude_conditions)) {
$conditions[] = "NOT (" . implode(" OR ", $exclude_conditions) . ")";
}
}
return implode(" AND ", $conditions);
}
public function getWhereClause() {
return empty($this->where_conditions) ? "" : "WHERE " . implode(" AND ", $this->where_conditions);
}
public function getJoinClause() {
return $this->join_conditions;
}
public function getDistinct() {
return $this->distinct;
}
public function getQueryString() {
return empty($this->query_params) ? "" : implode("&", $this->query_params);
}
}
function displayRatio($up, $down, $use_color = true) {
if ($down > 0) {
$ratio = number_format($up / $down, 2);
if ($use_color && function_exists('get_ratio_color')) {
$ratio = "<span style='color: " . get_ratio_color($ratio) . "'>$ratio</span>";
}
return $ratio;
} else {
return ($up > 0) ? "Inf." : "---";
}
}
function getUserIcons($user, $big = false) {
$icons = '';
if ($user["donor"] === "yes") {
$icon = $big ? "starbig.gif" : "star.gif";
$icons .= "<img src='pic/$icon' alt='Donor' style='margin-left: 2px; border: 0;'>";
}
if ($user["enabled"] === "yes") {
if ($user["warned"] === "yes") {
$icon = $big ? "warnedbig.gif" : "warned.gif";
$icons .= "<img src='pic/$icon' alt='Warned' style='border: 0;'>";
}
} else {
$icon = $big ? "disabledbig.gif" : "disabled.gif";
$icons .= "<img src='pic/$icon' alt='Disabled' style='margin-left: 2px; border: 0;'>";
}
return $icons;
}
function renderSelectOptions($options, $selected_value = 0) {
$html = '';
for ($i = 0; $i < count($options); $i++) {
$selected = ($selected_value == $i) ? "selected" : "";
$html .= "<option value='$i' $selected>" . htmlspecialchars($options[$i]) . "</option>\
";
}
return $html;
}
?>
<h1>Administrative User Search</h1>
<?php
// Display help instructions
if (isset($_GET['h']) && $_GET['h']) {
echo "<div class='info-box' style='width: 65%; margin: 0 auto; padding: 15px; background-color: #F5F4EA; border: 1px solid #ccc; margin-bottom: 20px;'>
<h3>Search Instructions:</h3>
<ul style='text-align: left;'>
<li>Fields left blank will be ignored</li>
<li>Wildcards * and ? may be used in Name, Email and Comments</li>
<li>Multiple values can be separated by spaces (e.g. 'user1 user2*')</li>
<li>Use '~' for negation (e.g. '~blocked' excludes users with 'blocked' in comments)</li>
<li>Ratio field accepts 'Inf' and '---' besides numeric values</li>
<li>Subnet mask may be entered in dotted decimal or CIDR notation</li>
<li>Upload/Download amounts should be entered in GB</li>
<li>'Active only' restricts search to users currently leeching or seeding</li>
<li>'Disabled IPs' shows users whose IPs also appear in disabled accounts</li>
</ul>
</div>";
} else {
echo "<p style='text-align: center;'>
(<a href='" . htmlspecialchars($_SERVER["PHP_SELF"]) . "?h=1'>Instructions</a>)
-
(<a href='" . htmlspecialchars($_SERVER["PHP_SELF"]) . "'>Reset</a>)
</p>";
}
$highlight = "style='background-color: #BBAF9B;'";
?>
<form method="get" action="<?= htmlspecialchars($_SERVER["PHP_SELF"]) ?>">
<input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>">
<table border="1" cellspacing="0" cellpadding="5" style="width: 100%; max-width: 1000px; margin: 0 auto;">
<tr>
<td class="rowhead">Name:</td>
<td <?= (!empty($_GET['n'])) ? $highlight : "" ?>>
<input name="n" type="text" value="<?= UserSearchValidator::sanitizeInput($_GET['n'] ?? '') ?>" size="25" maxlength="50">
</td>
<td class="rowhead">Ratio:</td>
<td <?= (!empty($_GET['r'])) ? $highlight : "" ?>>
<select name="rt">
<?= renderSelectOptions(["equal", "above", "below", "between"], $_GET['rt'] ?? 0) ?>
</select>
<input name="r" type="text" value="<?= UserSearchValidator::sanitizeInput($_GET['r'] ?? '') ?>" size="5" maxlength="6">
<input name="r2" type="text" value="<?= UserSearchValidator::sanitizeInput($_GET['r2'] ?? '') ?>" size="5" maxlength="6">
</td>
<td class="rowhead">Member Status:</td>
<td <?= (!empty($_GET['st'])) ? $highlight : "" ?>>
<select name="st">
<?= renderSelectOptions(["(any)", "confirmed", "pending"], $_GET['st'] ?? 0) ?>
</select>
</td>
</tr>
<tr>
<td class="rowhead">Email:</td>
<td <?= (!empty($_GET['em'])) ? $highlight : "" ?>>
<input name="em" type="text" value="<?= UserSearchValidator::sanitizeInput($_GET['em'] ?? '') ?>" size="25" maxlength="100">
</td>
<td class="rowhead">IP Address:</td>
<td <?= (!empty($_GET['ip'])) ? $highlight : "" ?>>
<input name="ip" type="text" value="<?= UserSearchValidator::sanitizeInput($_GET['ip'] ?? '') ?>" size="15" maxlength="15">
</td>
<td class="rowhead">Account Status:</td>
<td <?= (!empty($_GET['as'])) ? $highlight : "" ?>>
<select name="as">
<?= renderSelectOptions(["(any)", "enabled", "disabled"], $_GET['as'] ?? 0) ?>
</select>
</td>
</tr>
<tr>
<td class="rowhead">Comments:</td>
<td <?= (!empty($_GET['co'])) ? $highlight : "" ?>>
<input name="co" type="text" value="<?= UserSearchValidator::sanitizeInput($_GET['co'] ?? '') ?>" size="25" maxlength="100">
</td>
<td class="rowhead">Subnet Mask:</td>
<td <?= (!empty($_GET['ma'])) ? $highlight : "" ?>>
<input name="ma" type="text" value="<?= UserSearchValidator::sanitizeInput($_GET['ma'] ?? '') ?>" size="15" maxlength="18" placeholder="255.255.255.0 or /24">
</td>
<td class="rowhead">User Class:</td>
<td <?= (!empty($_GET['c']) && $_GET['c'] != 1) ? $highlight : "" ?>>
<select name="c">
<option value="1">(any)</option>
<?php
$selected_class = intval($_GET['c'] ?? 1);
for ($i = 2; $i <= 20; $i++) { // Reasonable limit
$class_name = get_user_class_name($i - 2);
if ($class_name) {
$selected = ($selected_class === $i) ? " selected" : "";
echo "<option value='$i'$selected>" . htmlspecialchars($class_name) . "</option>\
";
} else {
break;
}
}
?>
</select>
</td>
</tr>
<tr>
<td class="rowhead">Date Joined:</td>
<td <?= (!empty($_GET['d'])) ? $highlight : "" ?>>
<select name="dt">
<?= renderSelectOptions(["on", "before", "after", "between"], $_GET['dt'] ?? 0) ?>
</select>
<input name="d" type="date" value="<?= UserSearchValidator::sanitizeInput($_GET['d'] ?? '') ?>" size="12">
<input name="d2" type="date" value="<?= UserSearchValidator::sanitizeInput($_GET['d2'] ?? '') ?>" size="12">
</td>
<td class="rowhead">Uploaded (GB):</td>
<td <?= (!empty($_GET['ul'])) ? $highlight : "" ?>>
<select name="ult">
<?= renderSelectOptions(["equal", "above", "below", "between"], $_GET['ult'] ?? 0) ?>
</select>
<input name="ul" type="number" step="0.01" min="0" value="<?= UserSearchValidator::sanitizeInput($_GET['ul'] ?? '') ?>" size="8">
<input name="ul2" type="number" step="0.01" min="0" value="<?= UserSearchValidator::sanitizeInput($_GET['ul2'] ?? '') ?>" size="8">
</td>
<td class="rowhead">Donor:</td>
<td <?= (!empty($_GET['do'])) ? $highlight : "" ?>>
<select name="do">
<?= renderSelectOptions(["(any)", "Yes", "No"], $_GET['do'] ?? 0) ?>
</select>
</td>
</tr>
<tr>
<td class="rowhead">Last Seen:</td>
<td <?= (!empty($_GET['ls'])) ? $highlight : "" ?>>
<select name="lst">
<?= renderSelectOptions(["on", "before", "after", "between"], $_GET['lst'] ?? 0) ?>
</select>
<input name="ls" type="date" value="<?= UserSearchValidator::sanitizeInput($_GET['ls'] ?? '') ?>" size="12">
<input name="ls2" type="date" value="<?= UserSearchValidator::sanitizeInput($_GET['ls2'] ?? '') ?>" size="12">
</td>
<td class="rowhead">Downloaded (GB):</td>
<td <?= (!empty($_GET['dl'])) ? $highlight : "" ?>>
<select name="dlt">
<?= renderSelectOptions(["equal", "above", "below", "between"], $_GET['dlt'] ?? 0) ?>
</select>
<input name="dl" type="number" step="0.01" min="0" value="<?= UserSearchValidator::sanitizeInput($_GET['dl'] ?? '') ?>" size="8">
<input name="dl2" type="number" step="0.01" min="0" value="<?= UserSearchValidator::sanitizeInput($_GET['dl2'] ?? '') ?>" size="8">
</td>
<td class="rowhead">Warned:</td>
<td <?= (!empty($_GET['w'])) ? $highlight : "" ?>>
<select name="w">
<?= renderSelectOptions(["(any)", "Yes", "No"], $_GET['w'] ?? 0) ?>
</select>
</td>
</tr>
<tr>
<td class="rowhead">Active Only:</td>
<td <?= (!empty($_GET['ac'])) ? $highlight : "" ?>>
<input name="ac" type="checkbox" value="1" <?= (!empty($_GET['ac'])) ? "checked" : "" ?>>
</td>
<td class="rowhead">Disabled IP:</td>
<td <?= (!empty($_GET['dip'])) ? $highlight : "" ?>>
<input name="dip" type="checkbox" value="1" <?= (!empty($_GET['dip'])) ? "checked" : "" ?>>
</td>
<td class="rowhead">Country:</td>
<td <?= (!empty($_GET['country'])) ? $highlight : "" ?>>
<select name="country">
<option value="0">---- None selected ----</option>
<?php
$country_query = "SELECT id, name FROM countries ORDER BY name";
$country_result = mysql_query($country_query);
if ($country_result) {
$selected_country = intval($_GET['country'] ?? 0);
while ($country = mysql_fetch_assoc($country_result)) {
$selected = ($selected_country === intval($country['id'])) ? " selected" : "";
echo "<option value='" . intval($country['id']) . "'$selected>" .
htmlspecialchars($country['name']) . "</option>\
";
}
}
?>
</select>
</td>
</tr>
<tr>
<td class="rowhead">Download Rights:</td>
<td <?= (!empty($_GET['dp'])) ? $highlight : "" ?>>
<select name="dp">
<?= renderSelectOptions(["(any)", "Yes", "No"], $_GET['dp'] ?? 0) ?>
</select>
</td>
<td class="rowhead">Parked:</td>
<td <?= (!empty($_GET['pk'])) ? $highlight : "" ?>>
<select name="pk">
<?= renderSelectOptions(["(any)", "Yes", "No"], $_GET['pk'] ?? 0) ?>
</select>
</td>
<td class="rowhead">Forum Access:</td>
<td <?= (!empty($_GET['fp'])) ? $highlight : "" ?>>
<select name="fp">
<?= renderSelectOptions(["(any)", "Yes", "No"], $_GET['fp'] ?? 0) ?>
</select>
</td>
</tr>
<tr>
<td class="rowhead">Upload Rights:</td>
<td <?= (!empty($_GET['up'])) ? $highlight : "" ?>>
<select name="up">
<?= renderSelectOptions(["(any)", "Yes", "No"], $_GET['up'] ?? 0) ?>
</select>
</td>
<td class="rowhead">Passkey:</td>
<td <?= (!empty($_GET['pas'])) ? $highlight : "" ?>>
<input name="pas" type="text" value="<?= UserSearchValidator::sanitizeInput($_GET['pas'] ?? '') ?>" size="25" maxlength="32">
</td>
<td colspan="2"></td>
</tr>
<tr>
<td colspan="6" style="text-align: center; padding: 10px;">
<input name="submit" type="submit" class="btn" value="Search Users" style="padding: 8px 20px; font-size: 14px;">
</td>
</tr>
</table>
</form>
<br><br>
<?php
// Process search if form submitted
if (!empty($_GET) && !isset($_GET['h']) && isset($_GET['submit'])) {
// CSRF protection
if (!hash_equals($_SESSION['csrf_token'], $_GET['csrf_token'] ?? '')) {
stdmsg("Error", "Invalid request token. Please try again.");
stdfoot();
exit;
}
$searchQuery = new UserSearchQuery();
try {
// Name search
if (!empty($_GET['n'])) {
$names = array_filter(explode(' ', trim($_GET['n'])));
if (!empty($names)) {
$name_condition = $searchQuery->buildSearchCondition('u.username', $names);
$searchQuery->addWhereCondition($name_condition);
$searchQuery->addQueryParam("n=" . urlencode(trim($_GET['n'])));
}
}
// Passkey search
if (!empty($_GET['pas'])) {
$passkeys = array_filter(explode(' ', trim($_GET['pas'])));
if (!empty($passkeys)) {
$passkey_condition = $searchQuery->buildSearchCondition('u.passkey', $passkeys, true);
$searchQuery->addWhereCondition($passkey_condition);
$searchQuery->addQueryParam("pas=" . urlencode(trim($_GET['pas'])));
}
}
// Email search
if (!empty($_GET['em'])) {
$emails = array_filter(explode(' ', trim($_GET['em'])));
foreach ($emails as $email) {
if (!UserSearchValidator::hasWildcard($email) && !UserSearchValidator::validateEmail($email)) {
throw new Exception("Invalid email format: " . htmlspecialchars($email));
}
}
$email_condition = $searchQuery->buildSearchCondition('u.email', $emails);
$searchQuery->addWhereCondition($email_condition);
$searchQuery->addQueryParam("em=" . urlencode(trim($_GET['em'])));
}
// Class search
if (!empty($_GET['c']) && $_GET['c'] != 1) {
$class = intval($_GET['c']) - 2;
if ($class >= 0 && $class < 20) { // Reasonable bounds check
$searchQuery->addWhereCondition("u.class = " . intval($class));
$searchQuery->addQueryParam("c=" . intval($_GET['c']));
}
}
// IP search with subnet support
if (!empty($_GET['ip'])) {
$ip = trim($_GET['ip']);
if (!UserSearchValidator::validateIP($ip)) {
throw new Exception("Invalid IP address format.");
}
$mask = trim($_GET['ma'] ?? '');
if (empty($mask) || $mask === "255.255.255.255") {
$searchQuery->addWhereCondition("u.ip = " . sqlesc($ip));
} else {
if (substr($mask, 0, 1) === "/") {
$cidr = intval(substr($mask, 1));
if ($cidr < 0 || $cidr > 32) {
throw new Exception("Invalid CIDR notation. Must be between /0 and /32.");
}
$mask = long2ip((0xFFFFFFFF << (32 - $cidr)) & 0xFFFFFFFF);
} elseif (!UserSearchValidator::validateIP($mask)) {
throw new Exception("Invalid subnet mask format.");
}
$searchQuery->addWhereCondition(
"INET_ATON(u.ip) & INET_ATON(" . sqlesc($mask) . ") = " .
"INET_ATON(" . sqlesc($ip) . ") & INET_ATON(" . sqlesc($mask) . ")"
);
$searchQuery->addQueryParam("ma=" . urlencode($mask));
}
$searchQuery->addQueryParam("ip=" . urlencode($ip));
}
// Ratio search
if (!empty($_GET['r'])) {
$ratio = trim($_GET['r']);
if ($ratio === '---') {
$searchQuery->addWhereCondition("u.uploaded = 0 AND u.downloaded = 0");
} elseif (strtolower(substr($ratio, 0, 3)) === 'inf') {
$searchQuery->addWhereCondition("u.uploaded > 0 AND u.downloaded = 0");
} else {
if (!UserSearchValidator::validateNumeric($ratio)) {
throw new Exception("Invalid ratio value. Must be a positive number.");
}
$ratiotype = intval($_GET['rt'] ?? 0);
$ratio_field = "(CASE WHEN u.downloaded = 0 THEN 999999 ELSE u.uploaded/u.downloaded END)";
switch ($ratiotype) {
case 3: // between
$ratio2 = trim($_GET['r2'] ?? '');
if (!UserSearchValidator::validateNumeric($ratio2) || $ratio2 < $ratio) {
throw new Exception("Invalid second ratio value for range search.");
}
$searchQuery->addWhereCondition("$ratio_field BETWEEN " . floatval($ratio) . " AND " . floatval($ratio2));
$searchQuery->addQueryParam("r2=" . urlencode($ratio2));
break;
case 2: // below
$searchQuery->addWhereCondition("$ratio_field < " . floatval($ratio));
break;
case 1: // above
$searchQuery->addWhereCondition("$ratio_field > " . floatval($ratio));
break;
default: // equal (with tolerance)
$tolerance = 0.01;
$searchQuery->addWhereCondition(
"$ratio_field BETWEEN " . (floatval($ratio) - $tolerance) .
" AND " . (floatval($ratio) + $tolerance)
);
break;
}
$searchQuery->addQueryParam("rt=" . intval($ratiotype));
}
$searchQuery->addQueryParam("r=" . urlencode($ratio));
}
// Comment search
if (!empty($_GET['co'])) {
$comments = array_filter(explode(' ', trim($_GET['co'])));
if (!empty($comments)) {
$comment_condition = $searchQuery->buildSearchCondition('u.modcomment', $comments, false, true);
$searchQuery->addWhereCondition($comment_condition);
$searchQuery->addQueryParam("co=" . urlencode(trim($_GET['co'])));
}
}
// Upload/Download amount searches
foreach (['ul' => 'uploaded', 'dl' => 'downloaded'] as $param => $field) {
if (!empty($_GET[$param])) {
$amount = trim($_GET[$param]);
if (!UserSearchValidator::validateNumeric($amount)) {
throw new Exception("Invalid $field amount. Must be a positive number.");
}
$type = intval($_GET[$param . 't'] ?? 0);
$amount_bytes = floatval($amount) * GB_UNIT;
switch ($type) {
case 3: // between
$amount2 = trim($_GET[$param . '2'] ?? '');
if (!UserSearchValidator::validateNumeric($amount2) || $amount2 < $amount) {
throw new Exception("Invalid second $field amount for range search.");
}
$amount2_bytes = floatval($amount2) * GB_UNIT;
$searchQuery->addWhereCondition("u.$field BETWEEN $amount_bytes AND $amount2_bytes");
$searchQuery->addQueryParam($param . "2=" . urlencode($amount2));
break;
case 2: // below
$searchQuery->addWhereCondition("u.$field < $amount_bytes");
break;
case 1: // above
$searchQuery->addWhereCondition("u.$field > $amount_bytes");
break;
default: // equal (with tolerance)
$tolerance = 0.01 * GB_UNIT;
$searchQuery->addWhereCondition(
"u.$field BETWEEN " . ($amount_bytes - $tolerance) .
" AND " . ($amount_bytes + $tolerance)
);
break;
}
$searchQuery->addQueryParam($param . "t=" . intval($type));
$searchQuery->addQueryParam($param . "=" . urlencode($amount));
}
}
// Date searches
foreach (['d' => 'added', 'ls' => 'last_access'] as $param => $field) {
if (!empty($_GET[$param])) {
$date = UserSearchValidator::validateDate(trim($_GET[$param]));
if (!$date) {
throw new Exception("Invalid date format for " . ($param === 'd' ? 'joined date' : 'last seen date') . ".");
}
$type = intval($_GET[$param . 't'] ?? 0);
switch ($type) {
case 0: // on
$searchQuery->addWhereCondition(
"DATE(u.$field) = " . sqlesc($date)
);
break;
case 3: // between
$date2 = UserSearchValidator::validateDate(trim($_GET[$param . '2'] ?? ''));
if (!$date2) {
throw new Exception("Invalid second date for range search.");
}
$searchQuery->addWhereCondition("u.$field BETWEEN " . sqlesc($date) . " AND " . sqlesc($date2));
$searchQuery->addQueryParam($param . "2=" . urlencode($date2));
break;
case 1: // before
$searchQuery->addWhereCondition("u.$field < " . sqlesc($date));
break;
case 2: // after
$searchQuery->addWhereCondition("u.$field > " . sqlesc($date));
break;
}
$searchQuery->addQueryParam($param . "t=" . intval($type));
$searchQuery->addQueryParam($param . "=" . urlencode($date));
}
}
// Status searches
$status_fields = [
'st' =>