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

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