BioTorrents.de’s version of Gazelle
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

advancedsearch.php 42KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174
  1. <?php
  2. #declare(strict_types = 1);
  3. if (!empty($_GET['search'])) {
  4. if (preg_match('/^'.IP_REGEX.'$/', $_GET['search'])) {
  5. $_GET['ip'] = $_GET['search'];
  6. } elseif (preg_match('/^'.EMAIL_REGEX.'$/i', $_GET['search'])) {
  7. $_GET['email'] = $_GET['search'];
  8. } elseif (preg_match(USERNAME_REGEX, $_GET['search'])) {
  9. $DB->query("
  10. SELECT ID
  11. FROM users_main
  12. WHERE Username = '".db_string($_GET['search'])."'");
  13. if (list($ID) = $DB->next_record()) {
  14. header("Location: user.php?id=$ID");
  15. error();
  16. }
  17. $_GET['username'] = $_GET['search'];
  18. } else {
  19. $_GET['comment'] = $_GET['search'];
  20. }
  21. }
  22. define('USERS_PER_PAGE', 30);
  23. function wrap($String, $ForceMatch = '', $IPSearch = false)
  24. {
  25. if (!$ForceMatch) {
  26. global $Match;
  27. } else {
  28. $Match = $ForceMatch;
  29. }
  30. if ($Match == ' REGEXP ') {
  31. if (strpos($String, '\'') !== false || preg_match('/^.*\\\\$/i', $String)) {
  32. error('Regex contains illegal characters.');
  33. }
  34. } else {
  35. $String = db_string($String);
  36. }
  37. if ($Match == ' LIKE ') {
  38. // Fuzzy search
  39. // Stick in wildcards at beginning and end of string unless string starts or ends with |
  40. if (($String[0] != '|') && !$IPSearch) {
  41. $String = "%$String";
  42. } elseif ($String[0] == '|') {
  43. $String = substr($String, 1, strlen($String));
  44. }
  45. if (substr($String, -1, 1) != '|') {
  46. $String = "$String%";
  47. } else {
  48. $String = substr($String, 0, -1);
  49. }
  50. }
  51. $String = "'$String'";
  52. return $String;
  53. }
  54. function date_compare($Field, $Operand, $Date1, $Date2 = '')
  55. {
  56. $Date1 = db_string($Date1);
  57. $Date2 = db_string($Date2);
  58. $Return = [];
  59. switch ($Operand) {
  60. case 'on':
  61. $Return [] = " $Field >= '$Date1 00:00:00' ";
  62. $Return [] = " $Field <= '$Date1 23:59:59' ";
  63. break;
  64. case 'before':
  65. $Return [] = " $Field < '$Date1 00:00:00' ";
  66. break;
  67. case 'after':
  68. $Return [] = " $Field > '$Date1 23:59:59' ";
  69. break;
  70. case 'between':
  71. $Return [] = " $Field >= '$Date1 00:00:00' ";
  72. $Return [] = " $Field <= '$Date2 00:00:00' ";
  73. break;
  74. }
  75. return $Return;
  76. }
  77. function num_compare($Field, $Operand, $Num1, $Num2 = '')
  78. {
  79. if ($Num1 != 0) {
  80. $Num1 = db_string($Num1);
  81. }
  82. if ($Num2 != 0) {
  83. $Num2 = db_string($Num2);
  84. }
  85. $Return = [];
  86. switch ($Operand) {
  87. case 'equal':
  88. $Return [] = " $Field = '$Num1' ";
  89. break;
  90. case 'above':
  91. $Return [] = " $Field > '$Num1' ";
  92. break;
  93. case 'below':
  94. $Return [] = " $Field < '$Num1' ";
  95. break;
  96. case 'between':
  97. $Return [] = " $Field > '$Num1' ";
  98. $Return [] = " $Field < '$Num2' ";
  99. break;
  100. default:
  101. print_r($Return);
  102. error();
  103. }
  104. return $Return;
  105. }
  106. // Arrays, regexes, and all that fun stuff we can use for validation, form generation, etc
  107. $DateChoices = array('inarray'=>array('on', 'before', 'after', 'between'));
  108. $SingleDateChoices = array('inarray'=>array('on', 'before', 'after'));
  109. $NumberChoices = array('inarray'=>array('equal', 'above', 'below', 'between', 'buffer'));
  110. $YesNo = array('inarray'=>array('any', 'yes', 'no'));
  111. $OrderVals = array('inarray'=>array('Username', 'Ratio', 'IP', 'Email', 'Joined', 'Last Seen', 'Uploaded', 'Downloaded', 'Invites', 'Snatches'));
  112. $WayVals = array('inarray'=>array('Ascending', 'Descending'));
  113. if (count($_GET)) {
  114. $DateRegex = array('regex' => '/\d{4}-\d{2}-\d{2}/');
  115. $ClassIDs = [];
  116. $SecClassIDs = [];
  117. foreach ($Classes as $ClassID => $Value) {
  118. if ($Value['Secondary']) {
  119. $SecClassIDs[] = $ClassID;
  120. } else {
  121. $ClassIDs[] = $ClassID;
  122. }
  123. }
  124. $Val->SetFields('comment', '0', 'string', 'Comment is too long.', array('maxlength' => 512));
  125. $Val->SetFields('disabled_invites', '0', 'inarray', 'Invalid disabled_invites field', $YesNo);
  126. $Val->SetFields('joined', '0', 'inarray', 'Invalid joined field', $DateChoices);
  127. $Val->SetFields('join1', '0', 'regex', 'Invalid join1 field', $DateRegex);
  128. $Val->SetFields('join2', '0', 'regex', 'Invalid join2 field', $DateRegex);
  129. $Val->SetFields('lastactive', '0', 'inarray', 'Invalid lastactive field', $DateChoices);
  130. $Val->SetFields('lastactive1', '0', 'regex', 'Invalid lastactive1 field', $DateRegex);
  131. $Val->SetFields('lastactive2', '0', 'regex', 'Invalid lastactive2 field', $DateRegex);
  132. $Val->SetFields('ratio', '0', 'inarray', 'Invalid ratio field', $NumberChoices);
  133. $Val->SetFields('uploaded', '0', 'inarray', 'Invalid uploaded field', $NumberChoices);
  134. $Val->SetFields('downloaded', '0', 'inarray', 'Invalid downloaded field', $NumberChoices);
  135. //$Val->SetFields('snatched', '0', 'inarray', 'Invalid snatched field', $NumberChoices);
  136. $Val->SetFields('matchtype', '0', 'inarray', 'Invalid matchtype field', array('inarray' => array('strict', 'fuzzy', 'regex')));
  137. $Val->SetFields('lockedaccount', '0', 'inarray', 'Invalid locked account field', array('inarray' => array('any', 'locked', 'unlocked')));
  138. $Val->SetFields('enabled', '0', 'inarray', 'Invalid enabled field', array('inarray' => array('', 0, 1, 2)));
  139. $Val->SetFields('class', '0', 'inarray', 'Invalid class', array('inarray' => $ClassIDs));
  140. $Val->SetFields('secclass', '0', 'inarray', 'Invalid class', array('inarray' => $SecClassIDs));
  141. $Val->SetFields('donor', '0', 'inarray', 'Invalid donor field', $YesNo);
  142. $Val->SetFields('warned', '0', 'inarray', 'Invalid warned field', $YesNo);
  143. $Val->SetFields('disabled_uploads', '0', 'inarray', 'Invalid disabled_uploads field', $YesNo);
  144. $Val->SetFields('order', '0', 'inarray', 'Invalid ordering', $OrderVals);
  145. $Val->SetFields('way', '0', 'inarray', 'Invalid way', $WayVals);
  146. $Val->SetFields('passkey', '0', 'string', 'Invalid passkey', array('maxlength' => 32));
  147. $Val->SetFields('avatar', '0', 'string', 'Avatar URL too long', array('maxlength' => 512));
  148. $Val->SetFields('stylesheet', '0', 'inarray', 'Invalid stylesheet', array_unique(array_keys($Stylesheets)));
  149. $Val->SetFields('cc', '0', 'inarray', 'Invalid Country Code', array('maxlength' => 2));
  150. $Err = $Val->ValidateForm($_GET);
  151. if (!$Err) {
  152. // Passed validation. Let's rock.
  153. $RunQuery = false; // if we should run the search
  154. if (isset($_GET['matchtype']) && $_GET['matchtype'] == 'strict') {
  155. $Match = ' = ';
  156. } elseif (isset($_GET['matchtype']) && $_GET['matchtype'] == 'regex') {
  157. $Match = ' REGEXP ';
  158. } else {
  159. $Match = ' LIKE ';
  160. }
  161. $OrderTable = array(
  162. 'Username' => 'um1.Username',
  163. 'Joined' => 'ui1.JoinDate',
  164. 'Email' => 'um1.Email',
  165. 'IP' => 'um1.IP',
  166. 'Last Seen' => 'um1.LastAccess',
  167. 'Uploaded' => 'um1.Uploaded',
  168. 'Downloaded' => 'um1.Downloaded',
  169. 'Ratio' => '(um1.Uploaded / um1.Downloaded)',
  170. 'Invites' => 'um1.Invites',
  171. 'Snatches' => 'Snatches');
  172. $WayTable = array('Ascending'=>'ASC', 'Descending'=>'DESC');
  173. $Where = [];
  174. $Having = [];
  175. $Join = [];
  176. $Group = [];
  177. $Distinct = '';
  178. $Order = '';
  179. $SQL = '
  180. SQL_CALC_FOUND_ROWS
  181. um1.ID,
  182. um1.Username,
  183. um1.Uploaded,
  184. um1.Downloaded,';
  185. if ($_GET['snatched'] == 'off') {
  186. $SQL .= "'X' AS Snatches,";
  187. } else {
  188. $SQL .= "
  189. (
  190. SELECT COUNT(xs.uid)
  191. FROM xbt_snatched AS xs
  192. WHERE xs.uid = um1.ID
  193. ) AS Snatches,";
  194. }
  195. if ($_GET['invitees'] == 'off') {
  196. $SQL .= "'X' AS Invitees,";
  197. } else {
  198. $SQL .= "
  199. (
  200. SELECT COUNT(ui2.UserID)
  201. FROM users_info AS ui2
  202. WHERE um1.ID = ui2.Inviter
  203. ) AS Invitees,";
  204. }
  205. $SQL .= '
  206. um1.PermissionID,
  207. um1.Email,
  208. um1.Enabled,
  209. um1.IP,
  210. um1.Invites,
  211. ui1.DisableInvites,
  212. ui1.Warned,
  213. ui1.Donor,
  214. ui1.JoinDate,
  215. um1.LastAccess
  216. FROM users_main AS um1
  217. JOIN users_info AS ui1 ON ui1.UserID = um1.ID ';
  218. if (!empty($_GET['username'])) {
  219. $Where[] = 'um1.Username'.$Match.wrap($_GET['username']);
  220. }
  221. if (!empty($_GET['email'])) {
  222. if (isset($_GET['email_history'])) {
  223. $Distinct = 'DISTINCT ';
  224. }
  225. $Join['the'] = ' JOIN users_emails_decrypted AS he ON he.ID = um1.ID ';
  226. $Where[] = ' he.Email '.$Match.wrap($_GET['email']);
  227. }
  228. if (!empty($_GET['email_cnt']) && is_number($_GET['email_cnt'])) {
  229. $Query = "
  230. SELECT UserID
  231. FROM users_history_emails
  232. GROUP BY UserID
  233. HAVING COUNT(DISTINCT Email) ";
  234. if ($_GET['emails_opt'] === 'equal') {
  235. $operator = '=';
  236. }
  237. if ($_GET['emails_opt'] === 'above') {
  238. $operator = '>';
  239. }
  240. if ($_GET['emails_opt'] === 'below') {
  241. $operator = '<';
  242. }
  243. $Query .= $operator.' '.$_GET['email_cnt'];
  244. $DB->query($Query);
  245. $Users = implode(',', $DB->collect('UserID'));
  246. if (!empty($Users)) {
  247. $Where[] = "um1.ID IN ($Users)";
  248. }
  249. }
  250. if (!empty($_GET['ip'])) {
  251. if (isset($_GET['ip_history'])) {
  252. $Distinct = 'DISTINCT ';
  253. }
  254. $Join['tip'] = ' JOIN users_ips_decrypted AS tip ON tip.ID = um1.ID ';
  255. $Where[] = ' tip.IP '.$Match.wrap($_GET['ip'], '', true);
  256. }
  257. if ($_GET['lockedaccount'] != '' && $_GET['lockedaccount'] != 'any') {
  258. $Join['la'] = '';
  259. if ($_GET['lockedaccount'] == 'unlocked') {
  260. $Join['la'] .= ' LEFT';
  261. $Where[] = ' la.UserID IS NULL';
  262. }
  263. $Join['la'] .= ' JOIN locked_accounts AS la ON la.UserID = um1.ID ';
  264. }
  265. if (!empty($_GET['cc'])) {
  266. if ($_GET['cc_op'] == 'equal') {
  267. $Where[] = "um1.ipcc = '".db_string($_GET['cc'])."'";
  268. } else {
  269. $Where[] = "um1.ipcc != '".db_string($_GET['cc'])."'";
  270. }
  271. }
  272. if (!empty($_GET['tracker_ip'])) {
  273. $Distinct = 'DISTINCT ';
  274. $Join['xfu'] = ' JOIN xbt_files_users AS xfu ON um1.ID = xfu.uid ';
  275. $Where[] = ' xfu.ip '.$Match.wrap($_GET['tracker_ip'], '', true);
  276. }
  277. // if (!empty($_GET['tracker_ip'])) {
  278. // $Distinct = 'DISTINCT ';
  279. // $Join['xs'] = ' JOIN xbt_snatched AS xs ON um1.ID = xs.uid ';
  280. // $Where[] = ' xs.IP '.$Match.wrap($_GET['ip']);
  281. // }
  282. if (!empty($_GET['comment'])) {
  283. $Where[] = 'ui1.AdminComment'.$Match.wrap($_GET['comment']);
  284. }
  285. if (strlen($_GET['invites1'])) {
  286. $Invites1 = round($_GET['invites1']);
  287. $Invites2 = round($_GET['invites2']);
  288. $Where[] = implode(' AND ', num_compare('Invites', $_GET['invites'], $Invites1, $Invites2));
  289. }
  290. if (strlen($_GET['invitees1']) && $_GET['invitees'] != 'off') {
  291. $Invitees1 = round($_GET['invitees1']);
  292. $Invitees2 = round($_GET['invitees2']);
  293. $Having[] = implode(' AND ', num_compare('Invitees', $_GET['invitees'], $Invitees1, $Invitees2));
  294. }
  295. if ($_GET['disabled_invites'] == 'yes') {
  296. $Where[] = 'ui1.DisableInvites = \'1\'';
  297. } elseif ($_GET['disabled_invites'] == 'no') {
  298. $Where[] = 'ui1.DisableInvites = \'0\'';
  299. }
  300. if ($_GET['disabled_uploads'] == 'yes') {
  301. $Where[] = 'ui1.DisableUpload = \'1\'';
  302. } elseif ($_GET['disabled_uploads'] == 'no') {
  303. $Where[] = 'ui1.DisableUpload = \'0\'';
  304. }
  305. if ($_GET['join1']) {
  306. $Where[] = implode(' AND ', date_compare('ui1.JoinDate', $_GET['joined'], $_GET['join1'], $_GET['join2']));
  307. }
  308. if ($_GET['lastactive1']) {
  309. $Where[] = implode(' AND ', date_compare('um1.LastAccess', $_GET['lastactive'], $_GET['lastactive1'], $_GET['lastactive2']));
  310. }
  311. if ($_GET['ratio1']) {
  312. $Decimals = strlen(array_pop(explode('.', $_GET['ratio1'])));
  313. if (!$Decimals) {
  314. $Decimals = 0;
  315. }
  316. $Where[] = implode(' AND ', num_compare("ROUND(Uploaded/Downloaded,$Decimals)", $_GET['ratio'], $_GET['ratio1'], $_GET['ratio2']));
  317. }
  318. if (strlen($_GET['uploaded1'])) {
  319. $Upload1 = round($_GET['uploaded1']);
  320. $Upload2 = round($_GET['uploaded2']);
  321. if ($_GET['uploaded'] != 'buffer') {
  322. $Where[] = implode(' AND ', num_compare('ROUND(Uploaded / 1024 / 1024 / 1024)', $_GET['uploaded'], $Upload1, $Upload2));
  323. } else {
  324. $Where[] = implode(' AND ', num_compare('ROUND((Uploaded / 1024 / 1024 / 1024) - (Downloaded / 1024 / 1024 / 1023))', 'between', $Upload1 * 0.9, $Upload1 * 1.1));
  325. }
  326. }
  327. if (strlen($_GET['downloaded1'])) {
  328. $Download1 = round($_GET['downloaded1']);
  329. $Download2 = round($_GET['downloaded2']);
  330. $Where[] = implode(' AND ', num_compare('ROUND(Downloaded / 1024 / 1024 / 1024)', $_GET['downloaded'], $Download1, $Download2));
  331. }
  332. if (strlen($_GET['snatched1'])) {
  333. $Snatched1 = round($_GET['snatched1']);
  334. $Snatched2 = round($_GET['snatched2']);
  335. $Having[] = implode(' AND ', num_compare('Snatches', $_GET['snatched'], $Snatched1, $Snatched2));
  336. }
  337. if ($_GET['enabled'] != '') {
  338. $Where[] = 'um1.Enabled = '.wrap($_GET['enabled'], '=');
  339. }
  340. if ($_GET['class'] != '') {
  341. $Where[] = 'um1.PermissionID = '.wrap($_GET['class'], '=');
  342. }
  343. if ($_GET['secclass'] != '') {
  344. $Join['ul'] = ' JOIN users_levels AS ul ON um1.ID = ul.UserID ';
  345. $Where[] = 'ul.PermissionID = '.wrap($_GET['secclass'], '=');
  346. }
  347. if ($_GET['donor'] == 'yes') {
  348. $Where[] = 'ui1.Donor = \'1\'';
  349. } elseif ($_GET['donor'] == 'no') {
  350. $Where[] = 'ui1.Donor = \'0\'';
  351. }
  352. if ($_GET['warned'] == 'yes') {
  353. $Where[] = 'ui1.Warned IS NOT NULL';
  354. } elseif ($_GET['warned'] == 'no') {
  355. $Where[] = 'ui1.Warned IS NULL';
  356. }
  357. if ($_GET['disabled_ip']) {
  358. $Distinct = 'DISTINCT ';
  359. if ($_GET['ip_history']) {
  360. if (!isset($Join['tip'])) {
  361. $Join['tip'] = ' JOIN users_ips_decrypted AS tip ON tip.ID = um1.ID ';
  362. }
  363. $Join['tip2'] = ' JOIN users_ips_decrypted2 AS tip2 ON tip2.IP = tip.IP ';
  364. $Join['um2'] = ' JOIN users_main AS um2 ON um2.ID = tip2.ID AND um2.Enabled = \'2\' ';
  365. } else {
  366. $Join['um2'] = ' JOIN users_main AS um2 ON um2.IP = um1.IP AND um2.Enabled = \'2\' ';
  367. }
  368. }
  369. if (!empty($_GET['passkey'])) {
  370. $Where[] = 'um1.torrent_pass'.$Match.wrap($_GET['passkey']);
  371. }
  372. if (!empty($_GET['avatar'])) {
  373. $Where[] = 'ui1.Avatar'.$Match.wrap($_GET['avatar']);
  374. }
  375. if ($_GET['stylesheet'] != '') {
  376. $Where[] = 'ui1.StyleID = '.wrap($_GET['stylesheet'], '=');
  377. }
  378. if ($OrderTable[$_GET['order']] && $WayTable[$_GET['way']]) {
  379. $Order = ' ORDER BY '.$OrderTable[$_GET['order']].' '.$WayTable[$_GET['way']].' ';
  380. }
  381. //---------- Finish generating the search string
  382. $SQL = 'SELECT '.$Distinct.$SQL;
  383. $SQL .= implode(' ', $Join);
  384. if (count($Where)) {
  385. $SQL .= ' WHERE '.implode(' AND ', $Where);
  386. }
  387. if (count($Group)) {
  388. $SQL .= " GROUP BY " . implode(' ,', $Group);
  389. }
  390. if (count($Having)) {
  391. $SQL .= ' HAVING '.implode(' AND ', $Having);
  392. }
  393. $SQL .= $Order;
  394. if (count($Where) > 0 || count($Join) > 0 || count($Having) > 0) {
  395. $RunQuery = true;
  396. }
  397. list($Page, $Limit) = Format::page_limit(USERS_PER_PAGE);
  398. $SQL .= " LIMIT $Limit";
  399. } else {
  400. error($Err);
  401. }
  402. }
  403. View::show_header('User search');
  404. ?>
  405. <div>
  406. <form class="search_form" name="users" action="user.php" method="get">
  407. <input type="hidden" name="action" value="search" />
  408. <table class="layout">
  409. <tr>
  410. <td class="label nobr">Username:</td>
  411. <td width="24%">
  412. <input type="text" name="username" size="20"
  413. value="<?=display_str($_GET['username'])?>" />
  414. </td>
  415. <td class="label nobr">Joined:</td>
  416. <td width="24%">
  417. <select name="joined">
  418. <option value="on" <?php if ($_GET['joined'] === 'on') {
  419. echo ' selected="selected"';
  420. } ?>>On
  421. </option>
  422. <option value="before" <?php if ($_GET['joined'] === 'before') {
  423. echo ' selected="selected"';
  424. } ?>>Before
  425. </option>
  426. <option value="after" <?php if ($_GET['joined'] === 'after') {
  427. echo ' selected="selected"';
  428. } ?>>After
  429. </option>
  430. <option value="between" <?php if ($_GET['joined']==='between') {
  431. echo ' selected="selected"' ;
  432. } ?>>Between
  433. </option>
  434. </select>
  435. <input type="text" name="join1" size="10"
  436. value="<?=display_str($_GET['join1'])?>"
  437. placeholder="YYYY-MM-DD" />
  438. <input type="text" name="join2" size="10"
  439. value="<?=display_str($_GET['join2'])?>"
  440. placeholder="YYYY-MM-DD" />
  441. </td>
  442. <td class="label nobr">Enabled:</td>
  443. <td>
  444. <select name="enabled">
  445. <option value="" <?php if ($_GET['enabled'] === '') {
  446. echo ' selected="selected"';
  447. } ?>>Any
  448. </option>
  449. <option value="0" <?php if ($_GET['enabled']==='0') {
  450. echo ' selected="selected"' ;
  451. } ?>>Unconfirmed
  452. </option>
  453. <option value="1" <?php if ($_GET['enabled']==='1') {
  454. echo ' selected="selected"' ;
  455. } ?>>Enabled
  456. </option>
  457. <option value="2" <?php if ($_GET['enabled']==='2') {
  458. echo ' selected="selected"' ;
  459. } ?>>Disabled
  460. </option>
  461. </select>
  462. </td>
  463. </tr>
  464. <tr>
  465. <td class="label nobr">Email address:</td>
  466. <td>
  467. <input type="text" name="email" size="20"
  468. value="<?=display_str($_GET['email'])?>" />
  469. </td>
  470. <td class="label nobr">Last active:</td>
  471. <td width="30%">
  472. <select name="lastactive">
  473. <option value="on" <?php if ($_GET['lastactive'] === 'on') {
  474. echo ' selected="selected"';
  475. } ?>>On
  476. </option>
  477. <option value="before" <?php if ($_GET['lastactive'] === 'before') {
  478. echo ' selected="selected"';
  479. } ?>>Before
  480. </option>
  481. <option value="after" <?php if ($_GET['lastactive'] === 'after') {
  482. echo ' selected="selected"';
  483. } ?>>After
  484. </option>
  485. <option value="between" <?php if ($_GET['lastactive']==='between') {
  486. echo ' selected="selected"' ;
  487. } ?>
  488. >Between
  489. </option>
  490. </select>
  491. <input type="text" name="lastactive1" size="10"
  492. value="<?=display_str($_GET['lastactive1'])?>"
  493. placeholder="YYYY-MM-DD" />
  494. <input type="text" name="lastactive2" size="10"
  495. value="<?=display_str($_GET['lastactive2'])?>"
  496. placeholder="YYYY-MM-DD" />
  497. </td>
  498. <td class="label nobr">Primary class:</td>
  499. <td>
  500. <select name="class">
  501. <option value="" <?php if ($_GET['class']==='') {
  502. echo ' selected="selected"' ;
  503. } ?>>Any
  504. </option>
  505. <?php foreach ($ClassLevels as $Class) {
  506. if ($Class['Secondary']) {
  507. continue;
  508. } ?>
  509. <option value="<?=$Class['ID'] ?>"
  510. <?php
  511. if ($_GET['class']===$Class['ID']) {
  512. echo ' selected="selected"' ;
  513. } ?>><?=Format::cut_string($Class['Name'], 10, 1, 1).' ('.$Class['Level'].')'?>
  514. </option>
  515. <?php
  516. } ?>
  517. </select>
  518. </td>
  519. </tr>
  520. <tr>
  521. <td class="label tooltip nobr"
  522. title="To fuzzy search (default) for a block of addresses (e.g. 55.66.77.*), enter &quot;55.66.77.&quot; without the quotes">
  523. IP address:</td>
  524. <td>
  525. <input type="text" name="ip" size="20"
  526. value="<?=display_str($_GET['ip'])?>" />
  527. </td>
  528. <td class="label nobr">Locked Account:</td>
  529. <td>
  530. <select name="lockedaccount">
  531. <option value="any" <?php if ($_GET['lockedaccount']=='any') {
  532. echo ' selected="selected"' ;
  533. } ?>>Any
  534. </option>
  535. <option value="locked" <?php if ($_GET['lockedaccount']=='locked') {
  536. echo ' selected="selected"' ;
  537. } ?>>Locked
  538. </option>
  539. <option value="unlocked" <?php if ($_GET['lockedaccount']=='unlocked') {
  540. echo ' selected="selected"' ;
  541. } ?>
  542. >Unlocked
  543. </option>
  544. </select>
  545. </td>
  546. <td class="label nobr">Secondary class:</td>
  547. <td>
  548. <select name="secclass">
  549. <option value="" <?php if ($_GET['secclass']==='') {
  550. echo ' selected="selected"' ;
  551. } ?>>Any
  552. </option>
  553. <?php $Secondaries = [];
  554. // Neither level nor ID is particularly useful when searching secondary classes, so let's do some
  555. // kung-fu to sort them alphabetically.
  556. $fnc = function ($Class1, $Class2) {
  557. return strcmp($Class1['Name'], $Class2['Name']);
  558. };
  559. foreach ($ClassLevels as $Class) {
  560. if (!$Class['Secondary']) {
  561. continue;
  562. }
  563. $Secondaries[] = $Class;
  564. }
  565. usort($Secondaries, $fnc);
  566. foreach ($Secondaries as $Class) {
  567. ?>
  568. <option value="<?=$Class['ID'] ?>"
  569. <?php
  570. if ($_GET['secclass']===$Class['ID']) {
  571. echo ' selected="selected"' ;
  572. } ?>><?=Format::cut_string($Class['Name'], 20, 1, 1)?>
  573. </option>
  574. <?php
  575. } ?>
  576. </select>
  577. </td>
  578. </tr>
  579. <tr>
  580. <td class="label nobr">Extra:</td>
  581. <td>
  582. <ul class="options_list nobullet">
  583. <li>
  584. <input type="checkbox" name="ip_history" id="ip_history" <?php if ($_GET['ip_history']) {
  585. echo ' checked="checked"' ;
  586. } ?> />
  587. <label for="ip_history">IP history</label>
  588. </li>
  589. <li>
  590. <input type="checkbox" name="email_history" id="email_history" <?php if ($_GET['email_history']) {
  591. echo ' checked="checked"' ;
  592. } ?> />
  593. <label for="email_history">Email history</label>
  594. </li>
  595. </ul>
  596. </td>
  597. <td class="label nobr">Ratio:</td>
  598. <td width="30%">
  599. <select name="ratio">
  600. <option value="equal" <?php if ($_GET['ratio'] === 'equal') {
  601. echo ' selected="selected"';
  602. } ?>>Equal
  603. </option>
  604. <option value="above" <?php if ($_GET['ratio'] === 'above') {
  605. echo ' selected="selected"';
  606. } ?>>Above
  607. </option>
  608. <option value="below" <?php if ($_GET['ratio'] === 'below') {
  609. echo ' selected="selected"';
  610. } ?>>Below
  611. </option>
  612. <option value="between" <?php if ($_GET['ratio']==='between') {
  613. echo ' selected="selected"' ;
  614. } ?>>Between
  615. </option>
  616. </select>
  617. <input type="text" name="ratio1" size="6"
  618. value="<?=display_str($_GET['ratio1'])?>" />
  619. <input type="text" name="ratio2" size="6"
  620. value="<?=display_str($_GET['ratio2'])?>" />
  621. </td>
  622. <td class="label nobr">Donor:</td>
  623. <td>
  624. <select name="donor">
  625. <option value="" <?php if ($_GET['donor'] === '') {
  626. echo ' selected="selected"';
  627. } ?>>Any
  628. </option>
  629. <option value="yes" <?php if ($_GET['donor']==='yes') {
  630. echo ' selected="selected"' ;
  631. } ?>>Yes
  632. </option>
  633. <option value="no" <?php if ($_GET['donor'] === 'no') {
  634. echo ' selected="selected"';
  635. } ?>>No
  636. </option>
  637. </select>
  638. </td>
  639. </tr>
  640. <tr>
  641. <?php if (check_perms('users_mod')) { ?>
  642. <td class="label nobr">Staff notes:</td>
  643. <td>
  644. <input type="text" name="comment" size="20"
  645. value="<?=display_str($_GET['comment'])?>" />
  646. </td>
  647. <?php } else { ?>
  648. <td class="label nobr"></td>
  649. <td>
  650. </td>
  651. <?php } ?>
  652. <td class="label tooltip nobr" title="Units are in gibibytes (the base 2 sibling of gigabytes)">Uploaded:</td>
  653. <td width="30%">
  654. <select name="uploaded">
  655. <option value="equal" <?php if ($_GET['uploaded'] === 'equal') {
  656. echo ' selected="selected"';
  657. } ?>>Equal
  658. </option>
  659. <option value="above" <?php if ($_GET['uploaded'] === 'above') {
  660. echo ' selected="selected"';
  661. } ?>>Above
  662. </option>
  663. <option value="below" <?php if ($_GET['uploaded'] === 'below') {
  664. echo ' selected="selected"';
  665. } ?>>Below
  666. </option>
  667. <option value="between" <?php if ($_GET['uploaded']==='between') {
  668. echo ' selected="selected"' ;
  669. } ?>>Between
  670. </option>
  671. <option value="buffer" <?php if ($_GET['uploaded'] === 'buffer') {
  672. echo ' selected="selected"';
  673. } ?>>Buffer
  674. </option>
  675. </select>
  676. <input type="text" name="uploaded1" size="6"
  677. value="<?=display_str($_GET['uploaded1'])?>" />
  678. <input type="text" name="uploaded2" size="6"
  679. value="<?=display_str($_GET['uploaded2'])?>" />
  680. </td>
  681. <td class="label nobr">Warned:</td>
  682. <td>
  683. <select name="warned">
  684. <option value="" <?php if ($_GET['warned'] === '') {
  685. echo ' selected="selected"';
  686. } ?>>Any
  687. </option>
  688. <option value="yes" <?php if ($_GET['warned']==='yes') {
  689. echo ' selected="selected"' ;
  690. } ?>>Yes
  691. </option>
  692. <option value="no" <?php if ($_GET['warned'] === 'no') {
  693. echo ' selected="selected"';
  694. } ?>>No
  695. </option>
  696. </select>
  697. </td>
  698. </tr>
  699. <tr>
  700. <td class="label nobr"># of invites:</td>
  701. <td>
  702. <select name="invites">
  703. <option value="equal" <?php if ($_GET['invites'] === 'equal') {
  704. echo ' selected="selected"';
  705. } ?>>Equal
  706. </option>
  707. <option value="above" <?php if ($_GET['invites'] === 'above') {
  708. echo ' selected="selected"';
  709. } ?>>Above
  710. </option>
  711. <option value="below" <?php if ($_GET['invites'] === 'below') {
  712. echo ' selected="selected"';
  713. } ?>>Below
  714. </option>
  715. <option value="between" <?php if ($_GET['invites']==='between') {
  716. echo ' selected="selected"' ;
  717. } ?>>Between
  718. </option>
  719. </select>
  720. <input type="text" name="invites1" size="6"
  721. value="<?=display_str($_GET['invites1'])?>" />
  722. <input type="text" name="invites2" size="6"
  723. value="<?=display_str($_GET['invites2'])?>" />
  724. </td>
  725. <td class="label tooltip nobr" title="Units are in gibibytes (the base 2 sibling of gigabytes)">Downloaded:</td>
  726. <td width="30%">
  727. <select name="downloaded">
  728. <option value="equal" <?php if ($_GET['downloaded'] === 'equal') {
  729. echo ' selected="selected"';
  730. } ?>>Equal
  731. </option>
  732. <option value="above" <?php if ($_GET['downloaded'] === 'above') {
  733. echo ' selected="selected"';
  734. } ?>>Above
  735. </option>
  736. <option value="below" <?php if ($_GET['downloaded'] === 'below') {
  737. echo ' selected="selected"';
  738. } ?>>Below
  739. </option>
  740. <option value="between" <?php if ($_GET['downloaded']==='between') {
  741. echo ' selected="selected"' ;
  742. } ?>
  743. >Between
  744. </option>
  745. </select>
  746. <input type="text" name="downloaded1" size="6"
  747. value="<?=display_str($_GET['downloaded1'])?>" />
  748. <input type="text" name="downloaded2" size="6"
  749. value="<?=display_str($_GET['downloaded2'])?>" />
  750. </td>
  751. <td class="label tooltip nobr" title="Only display users that have a disabled account linked by IP address">
  752. <label for="disabled_ip">Disabled accounts<br />linked by IP:</label>
  753. </td>
  754. <td>
  755. <input type="checkbox" name="disabled_ip" id="disabled_ip" <?php if ($_GET['disabled_ip']) {
  756. echo ' checked="checked"' ;
  757. } ?> />
  758. </td>
  759. </tr>
  760. <tr>
  761. <td class="label nobr">Disabled invites:</td>
  762. <td>
  763. <select name="disabled_invites">
  764. <option value="" <?php if ($_GET['disabled_invites'] === '') {
  765. echo ' selected="selected"';
  766. } ?>>Any
  767. </option>
  768. <option value="yes" <?php if ($_GET['disabled_invites']==='yes') {
  769. echo ' selected="selected"' ;
  770. } ?>>Yes
  771. </option>
  772. <option value="no" <?php if ($_GET['disabled_invites'] === 'no') {
  773. echo ' selected="selected"';
  774. } ?>>No
  775. </option>
  776. </select>
  777. </td>
  778. <td class="label nobr">Snatched:</td>
  779. <td width="30%">
  780. <select name="snatched">
  781. <option value="equal" <?php if (isset($_GET['snatched']) && $_GET['snatched'] === 'equal') {
  782. echo ' selected="selected"';
  783. } ?>>Equal
  784. </option>
  785. <option value="above" <?php if (isset($_GET['snatched']) && $_GET['snatched'] === 'above') {
  786. echo ' selected="selected"';
  787. } ?>>Above
  788. </option>
  789. <option value="below" <?php if (isset($_GET['snatched']) && $_GET['snatched'] === 'below') {
  790. echo ' selected="selected"';
  791. } ?>>Below
  792. </option>
  793. <option value="between" <?php if (isset($_GET['snatched']) && $_GET['snatched']==='between') {
  794. echo ' selected="selected"' ;
  795. } ?>>Between
  796. </option>
  797. <option value="off" <?php if (!isset($_GET['snatched']) || $_GET['snatched'] === 'off') {
  798. echo ' selected="selected"';
  799. } ?>>Off
  800. </option>
  801. </select>
  802. <input type="text" name="snatched1" size="6"
  803. value="<?=display_str($_GET['snatched1'])?>" />
  804. <input type="text" name="snatched2" size="6"
  805. value="<?=display_str($_GET['snatched2'])?>" />
  806. </td>
  807. <td class="label nobr">Disabled uploads:</td>
  808. <td>
  809. <select name="disabled_uploads">
  810. <option value="" <?php if (isset($_GET['disabled_uploads']) && $_GET['disabled_uploads'] === '') {
  811. echo ' selected="selected"';
  812. } ?>>Any
  813. </option>
  814. <option value="yes" <?php if (isset($_GET['disabled_uploads']) && $_GET['disabled_uploads']==='yes') {
  815. echo ' selected="selected"' ;
  816. } ?>>Yes
  817. </option>
  818. <option value="no" <?php if (isset($_GET['disabled_uploads']) && $_GET['disabled_uploads'] === 'no') {
  819. echo ' selected="selected"';
  820. } ?>>No
  821. </option>
  822. </select>
  823. </td>
  824. </tr>
  825. <tr>
  826. <td width="30%" class="label nobr"># of invitees:</td>
  827. <td>
  828. <select name="invitees">
  829. <option value="equal" <?=isset($_GET['invitees']) && $_GET['invitees'] == 'equal' ? 'selected' : ''?>>Equal
  830. </option>
  831. <option value="above" <?=isset($_GET['invitees']) && $_GET['invitees'] == 'above' ? 'selected' : ''?>>Above
  832. </option>
  833. <option value="below" <?=isset($_GET['invitees']) && $_GET['invitees'] == 'below' ? 'selected' : ''?>>Below
  834. </option>
  835. <option value="between" <?=isset($_GET['invitees']) && $_GET['invitees'] == 'between' ? 'selected' : ''?>>Between
  836. </option>
  837. <option value="off" <?=!isset($_GET['invitees']) || $_GET['invitees'] == 'off' ? 'selected' : ''?>>Off
  838. </option>
  839. </select>
  840. <input type="text" name="invitees1" size="6"
  841. value="<?=display_str($_GET['invitees1'])?>" />
  842. <input type="text" name="invitees2" size="6"
  843. value="<?=display_str($_GET['invitees2'])?>" />
  844. </td>
  845. <td class="label nobr">Passkey:</td>
  846. <td>
  847. <input type="text" name="passkey" size="20"
  848. value="<?=display_str($_GET['passkey'])?>" />
  849. </td>
  850. <td class="label nobr">Tracker IP:</td>
  851. <td>
  852. <input type="text" name="tracker_ip" size="20"
  853. value="<?=display_str($_GET['tracker_ip'])?>" />
  854. </td>
  855. </tr>
  856. <tr>
  857. <td class="label tooltip nobr"
  858. title="Supports partial URL matching, e.g. entering &quot;&#124;https://whatimg.com&quot; will search for avatars hosted on https://whatimg.com">
  859. Avatar URL:</td>
  860. <td>
  861. <input type="text" name="avatar" size="20"
  862. value="<?=display_str($_GET['avatar'])?>" />
  863. </td>
  864. <td class="label nobr">Stylesheet:</td>
  865. <td>
  866. <select name="stylesheet" id="stylesheet">
  867. <option value="">Any</option>
  868. <?php foreach ($Stylesheets as $Style) { ?>
  869. <option value="<?=$Style['ID']?>"
  870. <?Format::selected('stylesheet', $Style['ID'])?>><?=$Style['ProperName']?>
  871. </option>
  872. <?php } ?>
  873. </select>
  874. </td>
  875. <td class="label tooltip nobr" title="Two-letter codes as defined in ISO 3166-1 alpha-2">Country code:</td>
  876. <td width="30%">
  877. <select name="cc_op">
  878. <option value="equal" <?php if ($_GET['cc_op'] === 'equal') {
  879. echo ' selected="selected"';
  880. } ?>>Equals
  881. </option>
  882. <option value="not_equal" <?php if ($_GET['cc_op']==='not_equal') {
  883. echo ' selected="selected"' ;
  884. } ?>>Not
  885. equal
  886. </option>
  887. </select>
  888. <input type="text" name="cc" size="2"
  889. value="<?=display_str($_GET['cc'])?>" />
  890. </td>
  891. </tr>
  892. <tr>
  893. <td class="label nobr">Search type:</td>
  894. <td>
  895. <ul class="options_list nobullet">
  896. <li>
  897. <input type="radio" name="matchtype" id="strict_match_type" value="strict" <?php if ($_GET['matchtype']=='strict' || !$_GET['matchtype']) {
  898. echo ' checked="checked"' ;
  899. } ?> />
  900. <label class="tooltip"
  901. title="A &quot;strict&quot; search uses no wildcards in search fields, and it is analogous to &#96;grep -E &quot;&circ;SEARCHTERM&#36;&quot;&#96;"
  902. for="strict_match_type">Strict</label>
  903. </li>
  904. <li>
  905. <input type="radio" name="matchtype" id="fuzzy_match_type" value="fuzzy" <?php if ($_GET['matchtype']=='fuzzy' || !$_GET['matchtype']) {
  906. echo ' checked="checked"' ;
  907. } ?> />
  908. <label class="tooltip"
  909. title="A &quot;fuzzy&quot; search automatically prepends and appends wildcards to search strings, except for IP address searches, unless the search string begins or ends with a &quot;&#124;&quot; (pipe). It is analogous to a vanilla grep search (except for the pipe stuff)."
  910. for="fuzzy_match_type">Fuzzy</label>
  911. </li>
  912. <li>
  913. <input type="radio" name="matchtype" id="regex_match_type" value="regex" <?php if ($_GET['matchtype']=='regex') {
  914. echo ' checked="checked"' ;
  915. } ?> />
  916. <label class="tooltip" title="A &quot;regex&quot; search uses MySQL's regular expression syntax."
  917. for="regex_match_type">Regex</label>
  918. </li>
  919. </ul>
  920. </td>
  921. <td class="label nobr">Order:</td>
  922. <td class="nobr">
  923. <select name="order">
  924. <?php
  925. foreach (array_shift($OrderVals) as $Cur) { ?>
  926. <option value="<?=$Cur?>" <?php if (isset($_GET['order']) &&
  927. $_GET['order']==$Cur || (!isset($_GET['order']) && $Cur=='Joined')) {
  928. echo ' selected="selected"' ;
  929. } ?>
  930. ><?=$Cur?>
  931. </option>
  932. <?php } ?>
  933. </select>
  934. <select name="way">
  935. <?php foreach (array_shift($WayVals) as $Cur) { ?>
  936. <option value="<?=$Cur?>" <?php if (isset($_GET['way']) &&
  937. $_GET['way']==$Cur || (!isset($_GET['way']) && $Cur=='Descending')) {
  938. echo ' selected="selected"' ;
  939. } ?>
  940. ><?=$Cur?>
  941. </option>
  942. <?php } ?>
  943. </select>
  944. </td>
  945. <td class="label nobr"># of emails:</td>
  946. <td>
  947. <select name="emails_opt">
  948. <option value="equal" <?php if ($_GET['emails_opt']==='equal') {
  949. echo ' selected="selected"' ;
  950. } ?>>Equal
  951. </option>
  952. <option value="above" <?php if ($_GET['emails_opt']==='above') {
  953. echo ' selected="selected"' ;
  954. } ?>>Above
  955. </option>
  956. <option value="below" <?php if ($_GET['emails_opt']==='below') {
  957. echo ' selected="selected"' ;
  958. } ?>>Below
  959. </option>
  960. </select>
  961. <input type="text" name="email_cnt" size="6"
  962. value="<?=display_str($_GET['email_cnt'])?>" />
  963. </td>
  964. </tr>
  965. <tr>
  966. <td colspan="6" class="center">
  967. <input type="submit" value="Search users" />
  968. </td>
  969. </tr>
  970. </table>
  971. </form>
  972. </div>
  973. <?php
  974. if ($RunQuery) {
  975. if (!empty($_GET['ip'])) {
  976. if (isset($_GET['ip_history'])) {
  977. $DB->query("SELECT UserID, IP FROM users_history_ips");
  978. } else {
  979. $DB->query("SELECT ID, IP FROM users_main");
  980. }
  981. while (list($ID, $EncIP) = $DB->next_record()) {
  982. $IPs[] = $ID.", '".Crypto::decrypt($EncIP)."'";
  983. }
  984. $DB->query("CREATE TEMPORARY TABLE users_ips_decrypted (ID INT(10) UNSIGNED NOT NULL, IP VARCHAR(45) NOT NULL, PRIMARY KEY (ID,IP)) ENGINE=MEMORY");
  985. $DB->query("INSERT IGNORE INTO users_ips_decrypted (ID, IP) VALUES(".implode("),(", $IPs).")");
  986. if ($_GET['disabled_ip'] && $_GET['ip_history']) {
  987. $DB->query("CREATE TEMPORARY TABLE users_ips_decrypted2 SELECT * FROM users_ips_decrypted");
  988. }
  989. }
  990. if (!empty($_GET['email'])) {
  991. if (isset($_GET['email_history'])) {
  992. $DB->query("SELECT UserID, Email FROM users_history_emails");
  993. } else {
  994. $DB->query("SELECT ID, Email FROM users_main");
  995. }
  996. while (list($ID, $EncEmail) = $DB->next_record()) {
  997. $Emails[] = $ID.", '".Crypto::decrypt($EncEmail)."'";
  998. }
  999. $DB->query("CREATE TEMPORARY TABLE users_emails_decrypted (ID INT(10) UNSIGNED NOT NULL, Email VARCHAR(255) NOT NULL, PRIMARY KEY (ID,Email)) ENGINE=MEMORY");
  1000. $DB->query("INSERT IGNORE INTO users_emails_decrypted (ID, Email) VALUES(".implode("),(", $Emails).")");
  1001. }
  1002. $Results = $DB->query($SQL);
  1003. $DB->query('SELECT FOUND_ROWS()');
  1004. list($NumResults) = $DB->next_record();
  1005. if (!empty($_GET['ip'])) {
  1006. $DB->query("DROP TABLE users_ips_decrypted");
  1007. }
  1008. if (!empty($_GET['email'])) {
  1009. $DB->query("DROP TABLE users_emails_decrypted");
  1010. }
  1011. $DB->set_query_id($Results);
  1012. } else {
  1013. $DB->query('SET @nothing = 0');
  1014. $NumResults = 0;
  1015. }
  1016. ?>
  1017. <div class="linkbox">
  1018. <?php
  1019. $Pages = Format::get_pages($Page, $NumResults, USERS_PER_PAGE, 11);
  1020. echo $Pages;
  1021. ?>
  1022. </div>
  1023. <div class="box pad center">
  1024. <h2><?=number_format($NumResults)?> results</h2>
  1025. <table width="100%">
  1026. <tr class="colhead">
  1027. <td>Username</td>
  1028. <td>Ratio</td>
  1029. <td>IP address</td>
  1030. <td>Email</td>
  1031. <td>Joined</td>
  1032. <td>Last seen</td>
  1033. <td>Upload</td>
  1034. <td>Download</td>
  1035. <td>Downloads</td>
  1036. <td>Snatched</td>
  1037. <td>Invites</td>
  1038. <?php if (isset($_GET['invitees']) && $_GET['invitees'] != 'off') { ?>
  1039. <td>Invitees</td>
  1040. <?php } ?>
  1041. </tr>
  1042. <?php
  1043. while (list($UserID, $Username, $Uploaded, $Downloaded, $Snatched, $Invitees, $Class, $Email, $Enabled, $IP, $Invites, $DisableInvites, $Warned, $Donor, $JoinDate, $LastAccess) = $DB->next_record()) {
  1044. $IP = apcu_exists('DBKEY') ? Crypto::decrypt($IP) : '[Encrypted]';
  1045. $Email = apcu_exists('DBKEY') ? Crypto::decrypt($Email) : '[Encrypted]'; ?>
  1046. <tr>
  1047. <td><?=Users::format_username($UserID, true, true, true, true)?>
  1048. </td>
  1049. <td><?=Format::get_ratio_html($Uploaded, $Downloaded)?>
  1050. </td>
  1051. <td style="word-break: break-all;"><?=display_str($IP)?>
  1052. (<?=Tools::get_country_code_by_ajax($IP)?>)</td>
  1053. <td><?=display_str($Email)?>
  1054. </td>
  1055. <td><?=time_diff($JoinDate)?>
  1056. </td>
  1057. <td><?=time_diff($LastAccess)?>
  1058. </td>
  1059. <td><?=Format::get_size($Uploaded)?>
  1060. </td>
  1061. <td><?=Format::get_size($Downloaded)?>
  1062. </td>
  1063. <?php $DB->query("
  1064. SELECT COUNT(ud.UserID)
  1065. FROM users_downloads AS ud
  1066. JOIN torrents AS t ON t.ID = ud.TorrentID
  1067. WHERE ud.UserID = $UserID");
  1068. list($Downloads) = $DB->next_record();
  1069. $DB->set_query_id($Results); ?>
  1070. <td><?=number_format((int)$Downloads)?>
  1071. </td>
  1072. <td><?=(is_numeric($Snatched) ? number_format($Snatched) : display_str($Snatched))?>
  1073. </td>
  1074. <td>
  1075. <?php if ($DisableInvites) {
  1076. echo 'X';
  1077. } else {
  1078. echo number_format($Invites);
  1079. } ?>
  1080. </td>
  1081. <?php if (isset($_GET['invitees']) && $_GET['invitees'] != 'off') { ?>
  1082. <td><?=number_format($Invitees)?>
  1083. </td>
  1084. <?php } ?>
  1085. </tr>
  1086. <?php
  1087. }
  1088. ?>
  1089. </table>
  1090. </div>
  1091. <div class="linkbox">
  1092. <?=$Pages?>
  1093. </div>
  1094. <?php View::show_footer();