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.

takemoderate.php 35KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918
  1. <?php
  2. #declare(strict_types=1);
  3. // Are they being tricky blighters?
  4. if (!$_POST['userid'] || !is_number($_POST['userid'])) {
  5. error(404);
  6. } elseif (!check_perms('users_mod')) {
  7. error(403);
  8. }
  9. authorize();
  10. // End checking for moronity
  11. if (!apcu_exists('DBKEY')) {
  12. error('Decrypt database first');
  13. }
  14. $ENV = ENV::go();
  15. $UserID = $_POST['userid'];
  16. $DeleteKeys = false;
  17. // Variables for database input
  18. $Class = (int)$_POST['Class'];
  19. $Username = db_string($_POST['Username']);
  20. $Title = db_string($_POST['Title']);
  21. $AdminComment = db_string($_POST['AdminComment']);
  22. $Donor = isset($_POST['Donor']) ? 1 : 0;
  23. $Artist = isset($_POST['Artist']) ? 1 : 0;
  24. $SecondaryClasses = isset($_POST['secondary_classes']) ? $_POST['secondary_classes'] : [];
  25. foreach ($SecondaryClasses as $i => $Val) {
  26. if (!is_number($Val)) {
  27. unset($SecondaryClasses[$i]);
  28. }
  29. }
  30. $Visible = isset($_POST['Visible']) ? 1 : 0;
  31. $Invites = (int)$_POST['Invites'];
  32. $SupportFor = db_string($_POST['SupportFor']);
  33. $Pass = $_POST['ChangePassword'];
  34. $Warned = isset($_POST['Warned']) ? 1 : 0;
  35. if (isset($_POST['Uploaded']) && isset($_POST['Downloaded'])) {
  36. $Uploaded = ($_POST['Uploaded'] === '' ? 0 : $_POST['Uploaded']);
  37. if ($Arithmetic = strpbrk($Uploaded, '+-')) {
  38. $Uploaded += max(-$Uploaded, Format::get_bytes($Arithmetic));
  39. }
  40. $Downloaded = ($_POST['Downloaded'] === '' ? 0 : $_POST['Downloaded']);
  41. if ($Arithmetic = strpbrk($Downloaded, '+-')) {
  42. $Downloaded += max(-$Downloaded, Format::get_bytes($Arithmetic));
  43. }
  44. if (!is_number($Uploaded) || !is_number($Downloaded)) {
  45. error(0);
  46. }
  47. }
  48. $BonusPoints = isset($_POST['BonusPoints']) ? $_POST['BonusPoints'] : 0;
  49. if (!is_number($BonusPoints)) {
  50. error(0);
  51. }
  52. $FLTokens = isset($_POST['FLTokens']) ? $_POST['FLTokens'] : 0;
  53. if (!is_number($FLTokens)) {
  54. error(0);
  55. }
  56. $Badges = isset($_POST['badges']) ? $_POST['badges'] : [];
  57. $WarnLength = (int)$_POST['WarnLength'];
  58. $ExtendWarning = (int)$_POST['ExtendWarning'];
  59. $ReduceWarning = (int)$_POST['ReduceWarning'];
  60. $WarnReason = $_POST['WarnReason'];
  61. $UserReason = $_POST['UserReason'];
  62. $DisableAvatar = isset($_POST['DisableAvatar']) ? 1 : 0;
  63. $DisableInvites = isset($_POST['DisableInvites']) ? 1 : 0;
  64. $DisablePosting = isset($_POST['DisablePosting']) ? 1 : 0;
  65. $DisableForums = isset($_POST['DisableForums']) ? 1 : 0;
  66. $DisableTagging = isset($_POST['DisableTagging']) ? 1 : 0;
  67. $DisableUpload = isset($_POST['DisableUpload']) ? 1 : 0;
  68. $DisableWiki = isset($_POST['DisableWiki']) ? 1 : 0;
  69. $DisablePM = isset($_POST['DisablePM']) ? 1 : 0;
  70. $DisablePoints = isset($_POST['DisablePoints']) ? 1 : 0;
  71. $DisablePromotion = isset($_POST['DisablePromotion']) ? 1 : 0;
  72. $DisableIRC = isset($_POST['DisableIRC']) ? 1 : 0;
  73. $DisableRequests = isset($_POST['DisableRequests']) ? 1 : 0;
  74. $DisableLeech = isset($_POST['DisableLeech']) ? 0 : 1;
  75. $LockedAccount = isset($_POST['LockAccount']) ? 1 : 0;
  76. $LockType = $_POST['LockReason'];
  77. $RestrictedForums = db_string(trim($_POST['RestrictedForums']));
  78. $PermittedForums = db_string(trim($_POST['PermittedForums']));
  79. $EnableUser = (int) $_POST['UserStatus'];
  80. $ResetRatioWatch = isset($_POST['ResetRatioWatch']) ? 1 : 0;
  81. $ResetPasskey = isset($_POST['ResetPasskey']) ? 1 : 0;
  82. $ResetAuthkey = isset($_POST['ResetAuthkey']) ? 1 : 0;
  83. $SendHackedMail = isset($_POST['SendHackedMail']) ? 1 : 0;
  84. if ($SendHackedMail && !empty($_POST['HackedEmail'])) {
  85. $HackedEmail = $_POST['HackedEmail'];
  86. } else {
  87. $SendHackedMail = false;
  88. }
  89. $MergeStatsFrom = db_string($_POST['MergeStatsFrom']);
  90. $Reason = db_string($_POST['Reason']);
  91. $HeavyUpdates = [];
  92. $LightUpdates = [];
  93. // Get user info from the database
  94. $DB->query("
  95. SELECT
  96. m.Username,
  97. m.IP,
  98. m.Email,
  99. m.PermissionID,
  100. p.Level AS Class,
  101. m.Title,
  102. m.Enabled,
  103. m.Uploaded,
  104. m.Downloaded,
  105. m.Invites,
  106. m.can_leech,
  107. m.Visible,
  108. i.AdminComment,
  109. m.torrent_pass,
  110. i.Donor,
  111. i.Artist,
  112. i.Warned,
  113. i.SupportFor,
  114. i.RestrictedForums,
  115. i.PermittedForums,
  116. DisableAvatar,
  117. DisableInvites,
  118. DisablePosting,
  119. DisableForums,
  120. DisableTagging,
  121. DisableUpload,
  122. DisableWiki,
  123. DisablePM,
  124. DisablePoints,
  125. DisablePromotion,
  126. DisableIRC,
  127. DisableRequests,
  128. m.RequiredRatio,
  129. m.FLTokens,
  130. m.BonusPoints,
  131. i.RatioWatchEnds,
  132. la.Type,
  133. SHA1(i.AdminComment) AS CommentHash,
  134. GROUP_CONCAT(l.PermissionID SEPARATOR ',') AS SecondaryClasses
  135. FROM users_main AS m
  136. JOIN users_info AS i ON i.UserID = m.ID
  137. LEFT JOIN permissions AS p ON p.ID = m.PermissionID
  138. LEFT JOIN users_levels AS l ON l.UserID = m.ID
  139. LEFT JOIN locked_accounts AS la ON la.UserID = m.ID
  140. WHERE m.ID = $UserID
  141. GROUP BY m.ID");
  142. if (!$DB->has_results()) { // If user doesn't exist
  143. header("Location: log.php?search=User+$UserID");
  144. }
  145. $Cur = $DB->next_record(MYSQLI_ASSOC, false);
  146. if ($_POST['comment_hash'] != $Cur['CommentHash']) {
  147. error("Somebody else has moderated this user since you loaded it. Please go back and refresh the page.");
  148. }
  149. // NOW that we know the class of the current user, we can see if one staff member is trying to hax0r us
  150. if (!check_perms('users_mod', $Cur['Class'])) {
  151. // Son of a fucking bitch
  152. error(403);
  153. error();
  154. }
  155. if (!empty($_POST['donor_points_submit']) && !empty($_POST['donation_value']) && is_numeric($_POST['donation_value'])) {
  156. Donations::regular_donate($UserID, $_POST['donation_value'], "Add Points", $_POST['donation_reason'], $_POST['donation_currency']);
  157. } elseif (!empty($_POST['donor_values_submit'])) {
  158. Donations::update_rank($UserID, $_POST['donor_rank'], $_POST['total_donor_rank'], $_POST['reason']);
  159. }
  160. // If we're deleting the user, we can ignore all the other crap
  161. if ($_POST['UserStatus'] === 'delete' && check_perms('users_delete_users')) {
  162. Misc::write_log("User account $UserID (".$Cur['Username'].") was deleted by ".$LoggedUser['Username']);
  163. $DB->query("
  164. DELETE FROM users_main
  165. WHERE id = $UserID");
  166. $DB->query("
  167. DELETE FROM users_info
  168. WHERE UserID = $UserID");
  169. $Cache->delete_value("user_info_$UserID");
  170. Tracker::update_tracker('remove_user', array('passkey' => $Cur['torrent_pass']));
  171. header("Location: log.php?search=User+$UserID");
  172. error();
  173. }
  174. // User was not deleted. Perform other stuff.
  175. $UpdateSet = [];
  176. $EditSummary = [];
  177. $TrackerUserUpdates = array('passkey' => $Cur['torrent_pass']);
  178. $QueryID = G::$DB->get_query_id();
  179. if ($LockType == '---' || $LockedAccount == 0) {
  180. if ($Cur['Type']) {
  181. $DB->query("DELETE FROM locked_accounts WHERE UserID = '" . $UserID . "'");
  182. $EditSummary[] = 'Account unlocked';
  183. $Cache->delete_value('user_' . $Cur['torrent_pass']);
  184. }
  185. } elseif (!$Cur['Type'] || $Cur['Type'] != $LockType) {
  186. $DB->query("INSERT INTO locked_accounts (UserID, Type)
  187. VALUES ('" . $UserID . "', '" . $LockType . "')
  188. ON DUPLICATE KEY UPDATE Type = '" . $LockType . "'");
  189. $Cache->delete_value('user_' . $Cur['torrent_pass']);
  190. if ($Cur['Type'] != $LockType) {
  191. $EditSummary[] = 'Account lock reason changed to ' . $LockType;
  192. } else {
  193. $EditSummary[] = 'Account locked (' . $LockType . ')';
  194. }
  195. }
  196. $Cache->delete_value("user_info_" . $UserID);
  197. $DB->set_query_id($QueryID);
  198. if ($_POST['ResetRatioWatch'] && check_perms('users_edit_reset_keys')) {
  199. $DB->query("
  200. UPDATE users_info
  201. SET RatioWatchEnds = NULL, RatioWatchDownload = '0', RatioWatchTimes = '0'
  202. WHERE UserID = '$UserID'");
  203. $EditSummary[] = 'RatioWatch history reset';
  204. }
  205. if ($_POST['ResetIPHistory'] && check_perms('users_edit_reset_keys')) {
  206. $GenericIP = Crypto::encrypt('127.0.0.1');
  207. $DB->query("
  208. DELETE FROM users_history_ips
  209. WHERE UserID = '$UserID'");
  210. $DB->query("
  211. UPDATE users_main
  212. SET IP = '$GenericIP'
  213. WHERE ID = '$UserID'");
  214. $DB->query("
  215. UPDATE xbt_snatched
  216. SET IP = ''
  217. WHERE uid = '$UserID'");
  218. $DB->query("
  219. UPDATE users_history_passwords
  220. SET ChangerIP = ''
  221. WHERE UserID = $UserID");
  222. $DB->query("
  223. UPDATE users_history_passkeys
  224. SET ChangerIP = ''
  225. WHERE UserID = $UserID");
  226. $DB->query("
  227. UPDATE users_sessions
  228. SET IP = '$GenericIP'
  229. WHERE UserID = $UserID");
  230. }
  231. if ($_POST['ResetSnatchList'] && check_perms('users_edit_reset_keys')) {
  232. $DB->query("
  233. DELETE FROM xbt_snatched
  234. WHERE uid = '$UserID'");
  235. $EditSummary[] = 'Snatch list cleared';
  236. $Cache->delete_value("recent_snatches_$UserID");
  237. }
  238. if ($_POST['ResetDownloadList'] && check_perms('users_edit_reset_keys')) {
  239. $DB->query("
  240. DELETE FROM users_downloads
  241. WHERE UserID = '$UserID'");
  242. $EditSummary[] = 'Download list cleared';
  243. }
  244. if (($_POST['ResetSession'] || $_POST['LogOut']) && check_perms('users_logout')) {
  245. $Cache->delete_value("user_info_$UserID");
  246. $Cache->delete_value("user_info_heavy_$UserID");
  247. $Cache->delete_value("user_stats_$UserID");
  248. $Cache->delete_value("enabled_$UserID");
  249. if ($_POST['LogOut']) {
  250. $DB->query("
  251. SELECT SessionID
  252. FROM users_sessions
  253. WHERE UserID = '$UserID'");
  254. while (list($SessionID) = $DB->next_record()) {
  255. $Cache->delete_value("session_{$UserID}_$SessionID");
  256. }
  257. $Cache->delete_value("users_sessions_$UserID");
  258. $DB->query("
  259. DELETE FROM users_sessions
  260. WHERE UserID = '$UserID'");
  261. }
  262. }
  263. // Start building SQL query and edit summary
  264. if ($Classes[$Class]['Level'] != $Cur['Class']
  265. && (
  266. ($Classes[$Class]['Level'] < $LoggedUser['Class'] && check_perms('users_promote_below', $Cur['Class']))
  267. || ($Classes[$Class]['Level'] <= $LoggedUser['Class'] && check_perms('users_promote_to', $Cur['Class'] - 1))
  268. )
  269. ) {
  270. $UpdateSet[] = "PermissionID = '$Class'";
  271. $EditSummary[] = 'class changed to '.Users::make_class_string($Class);
  272. $LightUpdates['PermissionID'] = $Class;
  273. $DeleteKeys = true;
  274. $DB->query("
  275. SELECT DISTINCT DisplayStaff
  276. FROM permissions
  277. WHERE ID = $Class
  278. OR ID = ".$ClassLevels[$Cur['Class']]['ID']);
  279. if ($DB->record_count() === 2) {
  280. if ($Classes[$Class]['Level'] < $Cur['Class']) {
  281. $SupportFor = '';
  282. }
  283. $ClearStaffIDCache = true;
  284. }
  285. $Cache->delete_value("donor_info_$UserID");
  286. }
  287. if ($Username != $Cur['Username'] && check_perms('users_edit_usernames', $Cur['Class'] - 1)) {
  288. $DB->query("
  289. SELECT ID
  290. FROM users_main
  291. WHERE Username = '$Username'");
  292. if ($DB->next_record() > 0) {
  293. list($UsedUsernameID) = $DB->next_record();
  294. error("Username already in use by <a href=\"user.php?id=$UsedUsernameID\">$Username</a>");
  295. header("Location: user.php?id=$UserID");
  296. error();
  297. } elseif ($Username == '0' || $Username == '1') {
  298. error('You cannot set a username of "0" or "1".');
  299. header("Location: user.php?id=$UserID");
  300. error();
  301. } else {
  302. $UpdateSet[] = "Username = '$Username'";
  303. $EditSummary[] = "username changed from ".$Cur['Username']." to $Username";
  304. $LightUpdates['Username'] = $Username;
  305. }
  306. }
  307. if ($Title != db_string($Cur['Title']) && check_perms('users_edit_titles')) {
  308. // Using the unescaped value for the test to avoid confusion
  309. if (strlen($_POST['Title']) > 1024) {
  310. error("Custom titles have a maximum length of 1,024 characters.");
  311. header("Location: user.php?id=$UserID");
  312. error();
  313. } else {
  314. $UpdateSet[] = "Title = '$Title'";
  315. $EditSummary[] = "title changed to [code]{$Title}[/code]";
  316. $LightUpdates['Title'] = $_POST['Title'];
  317. }
  318. }
  319. if ($Donor != $Cur['Donor'] && check_perms('users_give_donor')) {
  320. $UpdateSet[] = "Donor = '$Donor'";
  321. $EditSummary[] = 'donor status changed';
  322. $LightUpdates['Donor'] = $Donor;
  323. }
  324. // Secondary classes
  325. $OldClasses = $Cur['SecondaryClasses'] ? explode(',', $Cur['SecondaryClasses']) : [];
  326. $DroppedClasses = array_diff($OldClasses, $SecondaryClasses);
  327. $AddedClasses = array_diff($SecondaryClasses, $OldClasses);
  328. if (count($DroppedClasses) > 0) {
  329. $ClassChanges = [];
  330. foreach ($DroppedClasses as $PermID) {
  331. $ClassChanges[] = $Classes[$PermID]['Name'];
  332. }
  333. $EditSummary[] = 'Secondary classes dropped: '.implode(', ', $ClassChanges);
  334. $DB->query("
  335. DELETE FROM users_levels
  336. WHERE UserID = '$UserID'
  337. AND PermissionID IN (".implode(',', $DroppedClasses).')');
  338. if (count($SecondaryClasses) > 0) {
  339. $LightUpdates['ExtraClasses'] = array_fill_keys($SecondaryClasses, 1);
  340. } else {
  341. $LightUpdates['ExtraClasses'] = [];
  342. }
  343. $DeleteKeys = true;
  344. }
  345. if (count($AddedClasses) > 0) {
  346. $ClassChanges = [];
  347. foreach ($AddedClasses as $PermID) {
  348. $ClassChanges[] = $Classes[$PermID]['Name'];
  349. }
  350. $EditSummary[] = "Secondary classes added: ".implode(', ', $ClassChanges);
  351. $Values = [];
  352. foreach ($AddedClasses as $PermID) {
  353. $Values[] = "($UserID, $PermID)";
  354. }
  355. $DB->query("
  356. INSERT INTO users_levels (UserID, PermissionID)
  357. VALUES ".implode(', ', $Values));
  358. //$LightUpdates['ExtraClasses'] = array_fill_keys($SecondaryClasses, 1);
  359. $DeleteKeys = true;
  360. }
  361. if ($Visible != $Cur['Visible'] && check_perms('users_make_invisible')) {
  362. $UpdateSet[] = "Visible = '$Visible'";
  363. $EditSummary[] = 'visibility changed';
  364. $LightUpdates['Visible'] = $Visible;
  365. $TrackerUserUpdates['visible'] = $Visible;
  366. }
  367. if ($Uploaded != $Cur['Uploaded'] && $Uploaded != $_POST['OldUploaded'] && (check_perms('users_edit_ratio')
  368. || (check_perms('users_edit_own_ratio') && $UserID == $LoggedUser['ID']))) {
  369. $UpdateSet[] = "Uploaded = '$Uploaded'";
  370. $EditSummary[] = "uploaded changed from ".Format::get_size($Cur['Uploaded']).' to '.Format::get_size($Uploaded);
  371. $Cache->delete_value("user_stats_$UserID");
  372. }
  373. if ($Downloaded != $Cur['Downloaded'] && $Downloaded != $_POST['OldDownloaded'] && (check_perms('users_edit_ratio')
  374. || (check_perms('users_edit_own_ratio') && $UserID == $LoggedUser['ID']))) {
  375. $UpdateSet[] = "Downloaded = '$Downloaded'";
  376. $EditSummary[] = "downloaded changed from ".Format::get_size($Cur['Downloaded']).' to '.Format::get_size($Downloaded);
  377. $Cache->delete_value("user_stats_$UserID");
  378. }
  379. if ($BonusPoints != $Cur['BonusPoints'] && (check_perms('users_edit_ratio') || (check_perms('users_edit_own_ratio') && $UserID == $LoggedUser['ID']))) {
  380. $UpdateSet[] = "BonusPoints = $BonusPoints";
  381. $EditSummary[] = "Bonus Points changed from ".$Cur['BonusPoints']." to $BonusPoints";
  382. $HeavyUpdates['BonusPoints'] = $BonusPoints;
  383. }
  384. if ($FLTokens != $Cur['FLTokens'] && (check_perms('users_edit_ratio') || (check_perms('users_edit_own_ratio') && $UserID == $LoggedUser['ID']))) {
  385. $UpdateSet[] = "FLTokens = $FLTokens";
  386. $EditSummary[] = "Freeleech Tokens changed from ".$Cur['FLTokens']." to $FLTokens";
  387. $HeavyUpdates['FLTokens'] = $FLTokens;
  388. }
  389. if ($Invites != $Cur['Invites'] && check_perms('users_edit_invites')) {
  390. $UpdateSet[] = "invites = '$Invites'";
  391. $EditSummary[] = "number of invites changed to $Invites";
  392. $HeavyUpdates['Invites'] = $Invites;
  393. }
  394. if (check_perms('users_edit_badges')) {
  395. $query = "DELETE FROM users_badges WHERE UserID = $UserID";
  396. if (!empty($Badges)) {
  397. $query .= " AND BadgeID NOT IN (".implode(',', $Badges).")";
  398. }
  399. $DB->query($query);
  400. if (!empty($Badges)) {
  401. $query = "INSERT IGNORE INTO users_badges (UserID, BadgeID) VALUES ";
  402. $len = count($Badges);
  403. foreach ($Badges as $i => $BadgeID) {
  404. $query .= "($UserID, $BadgeID)";
  405. if ($i < ($len-1)) {
  406. $query .= ", ";
  407. }
  408. }
  409. $DB->query($query);
  410. }
  411. $Cache->delete_value("user_badges_".$UserID);
  412. }
  413. if ($Warned == 1 && !$Cur['Warned'] && check_perms('users_warn')) {
  414. $Weeks = 'week' . ($WarnLength === 1 ? '' : 's');
  415. Misc::send_pm($UserID, 0, 'You have received a warning', "You have been [url=".site_url()."wiki.php?action=article&amp;name=warnings]warned for $WarnLength {$Weeks}[/url] by [user]".$LoggedUser['Username']."[/user]. The reason given was:
  416. [quote]{$WarnReason}[/quote]");
  417. $UpdateSet[] = "Warned = NOW() + INTERVAL $WarnLength WEEK";
  418. $Msg = "warned for $WarnLength $Weeks";
  419. if ($WarnReason) {
  420. $Msg .= " for \"$WarnReason\"";
  421. }
  422. $EditSummary[] = db_string($Msg);
  423. $LightUpdates['Warned'] = time_plus(3600 * 24 * 7 * $WarnLength);
  424. } elseif ($Warned == 0 && $Cur['Warned'] && check_perms('users_warn')) {
  425. $UpdateSet[] = "Warned = NULL";
  426. $EditSummary[] = 'warning removed';
  427. $LightUpdates['Warned'] = null;
  428. } elseif ($Warned == 1 && $ExtendWarning != '---' && check_perms('users_warn')) {
  429. $Weeks = 'week' . ($ExtendWarning === 1 ? '' : 's');
  430. Misc::send_pm($UserID, 0, 'Your warning has been extended', "Your warning has been extended by $ExtendWarning $Weeks by [user]".$LoggedUser['Username']."[/user]. The reason given was:
  431. [quote]{$WarnReason}[/quote]");
  432. $UpdateSet[] = "Warned = Warned + INTERVAL $ExtendWarning WEEK";
  433. $DB->query("
  434. SELECT Warned + INTERVAL $ExtendWarning WEEK
  435. FROM users_info
  436. WHERE UserID = '$UserID'");
  437. list($WarnedUntil) = $DB->next_record();
  438. $Msg = "warning extended by $ExtendWarning $Weeks to $WarnedUntil";
  439. if ($WarnReason) {
  440. $Msg .= " for \"$WarnReason\"";
  441. }
  442. $EditSummary[] = db_string($Msg);
  443. $LightUpdates['Warned'] = $WarnedUntil;
  444. } elseif ($Warned == 1 && $ExtendWarning == '---' && $ReduceWarning != '---' && check_perms('users_warn')) {
  445. $Weeks = 'week' . ($ReduceWarning === 1 ? '' : 's');
  446. Misc::send_pm($UserID, 0, 'Your warning has been reduced', "Your warning has been reduced by $ReduceWarning $Weeks by [user]".$LoggedUser['Username']."[/user]. The reason given was:
  447. [quote]{$WarnReason}[/quote]");
  448. $UpdateSet[] = "Warned = Warned - INTERVAL $ReduceWarning WEEK";
  449. $DB->query("
  450. SELECT Warned - INTERVAL $ReduceWarning WEEK
  451. FROM users_info
  452. WHERE UserID = '$UserID'");
  453. list($WarnedUntil) = $DB->next_record();
  454. $Msg = "warning reduced by $ReduceWarning $Weeks to $WarnedUntil";
  455. if ($WarnReason) {
  456. $Msg .= " for \"$WarnReason\"";
  457. }
  458. $EditSummary[] = db_string($Msg);
  459. $LightUpdates['Warned'] = $WarnedUntil;
  460. }
  461. if ($SupportFor != db_string($Cur['SupportFor']) && (check_perms('admin_manage_fls') || (check_perms('users_mod') && $UserID == $LoggedUser['ID']))) {
  462. $UpdateSet[] = "SupportFor = '$SupportFor'";
  463. $EditSummary[] = "First-Line Support status changed to \"$SupportFor\"";
  464. }
  465. if ($RestrictedForums != db_string($Cur['RestrictedForums']) && check_perms('users_mod')) {
  466. $UpdateSet[] = "RestrictedForums = '$RestrictedForums'";
  467. $EditSummary[] = "restricted forum(s): $RestrictedForums";
  468. $DeleteKeys = true;
  469. }
  470. if ($PermittedForums != db_string($Cur['PermittedForums']) && check_perms('users_mod')) {
  471. $ForumSet = explode(',', $PermittedForums);
  472. $ForumList = [];
  473. foreach ($ForumSet as $ForumID) {
  474. if ($Forums[$ForumID]['MinClassCreate'] <= $LoggedUser['EffectiveClass']) {
  475. $ForumList[] = $ForumID;
  476. }
  477. }
  478. $PermittedForums = implode(',', $ForumSet);
  479. $UpdateSet[] = "PermittedForums = '$PermittedForums'";
  480. $EditSummary[] = "permitted forum(s): $PermittedForums";
  481. $DeleteKeys = true;
  482. }
  483. if ($DisableAvatar != $Cur['DisableAvatar'] && check_perms('users_disable_any')) {
  484. $UpdateSet[] = "DisableAvatar = '$DisableAvatar'";
  485. $EditSummary[] = 'avatar privileges ' . ($DisableAvatar ? 'disabled' : 'enabled');
  486. $HeavyUpdates['DisableAvatar'] = $DisableAvatar;
  487. if (!empty($UserReason)) {
  488. Misc::send_pm($UserID, 0, 'Your avatar privileges have been disabled', "Your avatar privileges have been disabled. The reason given was: [quote]{$UserReason}[/quote] If you would like to discuss this, please join ".DISABLED_CHAN.' on our IRC network. Instructions can be found [url='.site_url().'wiki.php?action=article&amp;name=IRC+-+How+to+join]here[/url].');
  489. }
  490. }
  491. if ($DisableLeech != $Cur['can_leech'] && check_perms('users_disable_any')) {
  492. $UpdateSet[] = "can_leech = '$DisableLeech'";
  493. $EditSummary[] = "leeching status changed (".translateLeechStatus($Cur['can_leech'])." -> ".translateLeechStatus($DisableLeech).")";
  494. $HeavyUpdates['DisableLeech'] = $DisableLeech;
  495. $HeavyUpdates['CanLeech'] = $DisableLeech;
  496. if (!empty($UserReason)) {
  497. Misc::send_pm($UserID, 0, 'Your leeching privileges have been disabled', "Your leeching privileges have been disabled. The reason given was: [quote]{$UserReason}[/quote] If you would like to discuss this, please join ".DISABLED_CHAN.' on our IRC network. Instructions can be found [url='.site_url().'wiki.php?action=article&amp;name=IRC+-+How+to+join]here[/url].');
  498. }
  499. $TrackerUserUpdates['can_leech'] = $DisableLeech;
  500. }
  501. if ($DisableInvites != $Cur['DisableInvites'] && check_perms('users_disable_any')) {
  502. $UpdateSet[] = "DisableInvites = '$DisableInvites'";
  503. if ($DisableInvites == 1) {
  504. //$UpdateSet[] = "Invites = '0'";
  505. if (!empty($UserReason)) {
  506. Misc::send_pm($UserID, 0, 'Your invite privileges have been disabled', "Your invite privileges have been disabled. The reason given was: [quote]{$UserReason}[/quote] If you would like to discuss this, please join ".DISABLED_CHAN.' on our IRC network. Instructions can be found [url='.site_url().'wiki.php?action=article&amp;name=IRC+-+How+to+join]here[/url].');
  507. }
  508. }
  509. $EditSummary[] = 'invites privileges ' . ($DisableInvites ? 'disabled' : 'enabled');
  510. $HeavyUpdates['DisableInvites'] = $DisableInvites;
  511. }
  512. if ($DisablePosting != $Cur['DisablePosting'] && check_perms('users_disable_posts')) {
  513. $UpdateSet[] = "DisablePosting = '$DisablePosting'";
  514. $EditSummary[] = 'posting privileges ' . ($DisablePosting ? 'disabled' : 'enabled');
  515. $HeavyUpdates['DisablePosting'] = $DisablePosting;
  516. if (!empty($UserReason)) {
  517. Misc::send_pm($UserID, 0, 'Your forum posting privileges have been disabled', "Your forum posting privileges have been disabled. The reason given was: [quote]{$UserReason}[/quote] If you would like to discuss this, please join ".DISABLED_CHAN.' on our IRC network. Instructions can be found [url='.site_url().'wiki.php?action=article&amp;name=IRC+-+How+to+join]here[/url].');
  518. }
  519. }
  520. if ($DisableForums != $Cur['DisableForums'] && check_perms('users_disable_posts')) {
  521. $UpdateSet[] = "DisableForums = '$DisableForums'";
  522. $EditSummary[] = 'forums privileges ' . ($DisableForums ? 'disabled' : 'enabled');
  523. $HeavyUpdates['DisableForums'] = $DisableForums;
  524. if (!empty($UserReason)) {
  525. Misc::send_pm($UserID, 0, 'Your forum privileges have been disabled', "Your forum privileges have been disabled. The reason given was: [quote]{$UserReason}[/quote] If you would like to discuss this, please join ".DISABLED_CHAN.' on our IRC network. Instructions can be found [url='.site_url().'wiki.php?action=article&amp;name=IRC+-+How+to+join]here[/url].');
  526. }
  527. }
  528. if ($DisableTagging != $Cur['DisableTagging'] && check_perms('users_disable_any')) {
  529. $UpdateSet[] = "DisableTagging = '$DisableTagging'";
  530. $EditSummary[] = 'tagging privileges ' . ($DisableTagging ? 'disabled' : 'enabled');
  531. $HeavyUpdates['DisableTagging'] = $DisableTagging;
  532. if (!empty($UserReason)) {
  533. Misc::send_pm($UserID, 0, 'Your tagging privileges have been disabled', "Your tagging privileges have been disabled. The reason given was: [quote]{$UserReason}[/quote] If you would like to discuss this, please join ".DISABLED_CHAN.' on our IRC network. Instructions can be found [url='.site_url().'wiki.php?action=article&amp;name=IRC+-+How+to+join]here[/url].');
  534. }
  535. }
  536. if ($DisableUpload != $Cur['DisableUpload'] && check_perms('users_disable_any')) {
  537. $UpdateSet[] = "DisableUpload = '$DisableUpload'";
  538. $EditSummary[] = 'upload privileges ' . ($DisableUpload ? 'disabled' : 'enabled');
  539. $HeavyUpdates['DisableUpload'] = $DisableUpload;
  540. if ($DisableUpload == 1) {
  541. Misc::send_pm($UserID, 0, 'Your upload privileges have been disabled', "Your upload privileges have been disabled. The reason given was: [quote]{$UserReason}[/quote] If you would like to discuss this, please join ".DISABLED_CHAN.' on our IRC network. Instructions can be found [url='.site_url().'wiki.php?action=article&amp;name=IRC+-+How+to+join]here[/url].');
  542. }
  543. }
  544. if ($DisableWiki != $Cur['DisableWiki'] && check_perms('users_disable_any')) {
  545. $UpdateSet[] = "DisableWiki = '$DisableWiki'";
  546. $EditSummary[] = 'wiki privileges ' . ($DisableWiki ? 'disabled' : 'enabled');
  547. $HeavyUpdates['DisableWiki'] = $DisableWiki;
  548. $HeavyUpdates['site_edit_wiki'] = 0;
  549. if (!empty($UserReason)) {
  550. Misc::send_pm($UserID, 0, 'Your site editing privileges have been disabled', "Your site editing privileges have been disabled. The reason given was: [quote]{$UserReason}[/quote] If you would like to discuss this, please join ".DISABLED_CHAN.' on our IRC network. Instructions can be found [url='.site_url().'wiki.php?action=article&amp;name=IRC+-+How+to+join]here[/url].');
  551. }
  552. }
  553. if ($DisablePM != $Cur['DisablePM'] && check_perms('users_disable_any')) {
  554. $UpdateSet[] = "DisablePM = '$DisablePM'";
  555. $EditSummary[] = 'PM privileges ' . ($DisablePM ? 'disabled' : 'enabled');
  556. $HeavyUpdates['DisablePM'] = $DisablePM;
  557. if (!empty($UserReason)) {
  558. Misc::send_pm($UserID, 0, 'Your PM privileges have been disabled', "Your PM privileges have been disabled. The reason given was: [quote]{$UserReason}[/quote] If you would like to discuss this, please join ".DISABLED_CHAN.' on our IRC network. Instructions can be found [url='.site_url().'wiki.php?action=article&amp;name=IRC+-+How+to+join]here[/url].');
  559. }
  560. }
  561. if ($DisablePoints != $Cur['DisablePoints'] && check_perms('users_disable_any')) {
  562. $UpdateSet[] = "DisablePoints = '$DisablePoints'";
  563. $EditSummary[] = BONUS_POINTS.' earning ' . ($DisablePoints ? 'disabled' : 'enabled');
  564. $HeavyUpdates['DisablePoints'] = $DisablePoints;
  565. if (!empty($UserReason)) {
  566. Misc::send_pm($UserID, 0, 'Your '.BONUS_POINTS.'-earning ability has been disabled', "Your ".BONUS_POINTS."-earning ability has been disabled. The reason given was: [quote]{$UserReason}[/quote] If you would like to discuss this, please join ".DISABLED_CHAN.' on our IRC network. Instructions can be found [url='.site_url().'wiki.php?action=article&amp;name=IRC+-+How+to+join]here[/url].');
  567. }
  568. }
  569. if ($DisablePromotion != $Cur['DisablePromotion'] && check_perms('users_disable_any')) {
  570. $UpdateSet[] = "DisablePromotion = '$DisablePromotion'";
  571. $EditSummary[] = 'Class purchasing ' . ($DisablePromotion ? 'disabled' : 'enabled');
  572. $HeavyUpdates['DisablePromotion'] = $DisablePromotion;
  573. if (!empty($UserReason)) {
  574. Misc::send_pm($UserID, 0, 'Your promotion purchasing ability has been disabled', "Your promotion purchasing ability has been disabled. The reason given was: [quote]{$UserReason}[/quote] If you would like to discuss this, please join ".DISABLED_CHAN.' on our IRC network. Instructions can be found [url='.site_url().'wiki.php?action=article&amp;name=IRC+-+How+to+join]here[/url].');
  575. }
  576. }
  577. if ($DisableIRC != $Cur['DisableIRC'] && check_perms('users_disable_any')) {
  578. $UpdateSet[] = "DisableIRC = '$DisableIRC'";
  579. $EditSummary[] = 'IRC privileges ' . ($DisableIRC ? 'disabled' : 'enabled');
  580. $HeavyUpdates['DisableIRC'] = $DisableIRC;
  581. if (!empty($UserReason)) {
  582. Misc::send_pm($UserID, 0, 'Your IRC privileges have been disabled', "Your IRC privileges have been disabled. The reason given was: [quote]{$UserReason}[/quote] If you would like to discuss this, please join ".DISABLED_CHAN.' on our IRC network. Instructions can be found [url='.site_url().'wiki.php?action=article&amp;name=IRC+-+How+to+join]here[/url]. This loss of privileges does not affect the ability to join and talk to staff in '.DISABLED_CHAN.'.');
  583. }
  584. }
  585. if ($DisableRequests != $Cur['DisableRequests'] && check_perms('users_disable_any')) {
  586. $UpdateSet[] = "DisableRequests = '$DisableRequests'";
  587. $EditSummary[] = 'request privileges ' . ($DisableRequests ? 'disabled' : 'enabled');
  588. $HeavyUpdates['DisableRequests'] = $DisableRequests;
  589. if (!empty($UserReason)) {
  590. Misc::send_pm($UserID, 0, 'Your request privileges have been disabled', "Your request privileges have been disabled. The reason given was: [quote]{$UserReason}[/quote] If you would like to discuss this, please join ".DISABLED_CHAN.' on our IRC network. Instructions can be found [url='.site_url().'wiki.php?action=article&amp;name=IRC+-+How+to+join]here[/url].');
  591. }
  592. }
  593. if ($EnableUser != $Cur['Enabled'] && check_perms('users_disable_users')) {
  594. $EnableStr = 'account '.translateUserStatus($Cur['Enabled']).'->'.translateUserStatus($EnableUser);
  595. if ($EnableUser == '2') {
  596. Tools::disable_users($UserID, '', 1);
  597. $TrackerUserUpdates = [];
  598. } elseif ($EnableUser == '1') {
  599. $Cache->increment('stats_user_count');
  600. $VisibleTrIP = ($Visible && Crypto::decrypt($Cur['IP']) != '127.0.0.1') ? '1' : '0';
  601. Tracker::update_tracker('add_user', array('id' => $UserID, 'passkey' => $Cur['torrent_pass'], 'visible' => $VisibleTrIP));
  602. if (($Cur['Downloaded'] == 0) || ($Cur['Uploaded'] / $Cur['Downloaded'] >= $Cur['RequiredRatio'])) {
  603. $UpdateSet[] = "i.RatioWatchEnds = NULL";
  604. $CanLeech = 1;
  605. $UpdateSet[] = "m.can_leech = '1'";
  606. $UpdateSet[] = "i.RatioWatchDownload = '0'";
  607. } else {
  608. $EnableStr .= ' (Ratio: '.Format::get_ratio_html($Cur['Uploaded'], $Cur['Downloaded'], false).', RR: '.number_format($Cur['RequiredRatio'], 2).')';
  609. if ($Cur['RatioWatchEnds']) {
  610. $UpdateSet[] = "i.RatioWatchEnds = NOW()";
  611. $UpdateSet[] = "i.RatioWatchDownload = m.Downloaded";
  612. $CanLeech = 0;
  613. }
  614. $TrackerUserUpdates['can_leech'] = 0;
  615. }
  616. $UpdateSet[] = "i.BanReason = '0'";
  617. $UpdateSet[] = "Enabled = '1'";
  618. $LightUpdates['Enabled'] = 1;
  619. }
  620. $EditSummary[] = $EnableStr;
  621. $Cache->replace_value("enabled_$UserID", $EnableUser, 0);
  622. }
  623. if ($ResetPasskey == 1 && check_perms('users_edit_reset_keys')) {
  624. $Passkey = db_string(Users::make_secret());
  625. $UpdateSet[] = "torrent_pass = '$Passkey'";
  626. $EditSummary[] = 'passkey reset';
  627. $HeavyUpdates['torrent_pass'] = $Passkey;
  628. $TrackerUserUpdates['passkey'] = $Passkey;
  629. $Cache->delete_value('user_'.$Cur['torrent_pass']);
  630. // MUST come after the case for updating can_leech
  631. $DB->query("
  632. INSERT INTO users_history_passkeys
  633. (UserID, OldPassKey, NewPassKey, ChangerIP, ChangeTime)
  634. VALUES
  635. ('$UserID', '".$Cur['torrent_pass']."', '$Passkey', '".Crypto::encrypt('0.0.0.0')."', NOW())");
  636. Tracker::update_tracker('change_passkey', array('oldpasskey' => $Cur['torrent_pass'], 'newpasskey' => $Passkey));
  637. }
  638. if ($ResetAuthkey == 1 && check_perms('users_edit_reset_keys')) {
  639. $Authkey = db_string(Users::make_secret());
  640. $UpdateSet[] = "AuthKey = '$Authkey'";
  641. $EditSummary[] = 'authkey reset';
  642. $HeavyUpdates['AuthKey'] = $Authkey;
  643. }
  644. if ($SendHackedMail && check_perms('users_disable_any')) {
  645. $EditSummary[] = "hacked account email sent to $HackedEmail";
  646. Misc::send_email($HackedEmail, "Your $ENV->SITE_NAME account", "Your $ENV->SITE_NAME account appears to have been compromised. As a security measure, we have disabled your account. To resolve this, please visit us on Slack.");
  647. }
  648. if ($MergeStatsFrom && check_perms('users_edit_ratio')) {
  649. $DB->query("
  650. SELECT ID, Uploaded, Downloaded
  651. FROM users_main
  652. WHERE Username LIKE '$MergeStatsFrom'");
  653. if ($DB->has_results()) {
  654. list($MergeID, $MergeUploaded, $MergeDownloaded) = $DB->next_record();
  655. $DB->query("
  656. UPDATE users_main AS um
  657. JOIN users_info AS ui ON um.ID = ui.UserID
  658. SET
  659. um.Uploaded = 0,
  660. um.Downloaded = 0,
  661. ui.AdminComment = CONCAT('".sqltime().' - Stats (Uploaded: '.Format::get_size($MergeUploaded).', Downloaded: '.Format::get_size($MergeDownloaded).', Ratio: '.Format::get_ratio($MergeUploaded, $MergeDownloaded).') merged into '.site_url()."user.php?id=$UserID (".$Cur['Username'].') by '.$LoggedUser['Username']."\n\n', ui.AdminComment)
  662. WHERE ID = $MergeID");
  663. $UpdateSet[] = "Uploaded = Uploaded + '$MergeUploaded'";
  664. $UpdateSet[] = "Downloaded = Downloaded + '$MergeDownloaded'";
  665. $EditSummary[] = 'stats merged from '.site_url()."user.php?id=$MergeID ($MergeStatsFrom) (previous stats: Uploaded: ".Format::get_size($Cur['Uploaded']).', Downloaded: '.Format::get_size($Cur['Downloaded']).', Ratio: '.Format::get_ratio($Cur['Uploaded'], $Cur['Downloaded']).')';
  666. $Cache->delete_value("user_stats_$UserID");
  667. $Cache->delete_value("user_stats_$MergeID");
  668. }
  669. }
  670. if ($Pass && check_perms('users_edit_password')) {
  671. $UpdateSet[] = "PassHash = '".db_string(Users::make_sec_hash($Pass))."'";
  672. $EditSummary[] = 'password reset';
  673. $Cache->delete_value("user_info_$UserID");
  674. $Cache->delete_value("user_info_heavy_$UserID");
  675. $Cache->delete_value("user_stats_$UserID");
  676. $Cache->delete_value("enabled_$UserID");
  677. $DB->query("
  678. SELECT SessionID
  679. FROM users_sessions
  680. WHERE UserID = '$UserID'");
  681. while (list($SessionID) = $DB->next_record()) {
  682. $Cache->delete_value("session_{$UserID}_$SessionID");
  683. }
  684. $Cache->delete_value("users_sessions_$UserID");
  685. $DB->query("
  686. DELETE FROM users_sessions
  687. WHERE UserID = '$UserID'");
  688. }
  689. if (empty($UpdateSet) && empty($EditSummary)) {
  690. if (!$Reason) {
  691. if (str_replace("\r", '', $Cur['AdminComment']) != str_replace("\r", '', $AdminComment) && check_perms('users_disable_any')) {
  692. $UpdateSet[] = "AdminComment = '$AdminComment'";
  693. } else {
  694. header("Location: user.php?id=$UserID");
  695. error();
  696. }
  697. } else {
  698. $EditSummary[] = 'notes added';
  699. }
  700. }
  701. if (count($TrackerUserUpdates) > 1) {
  702. Tracker::update_tracker('update_user', $TrackerUserUpdates);
  703. }
  704. if ($DeleteKeys) {
  705. $Cache->delete_value("user_info_$UserID");
  706. $Cache->delete_value("user_info_heavy_$UserID");
  707. } else {
  708. $Cache->begin_transaction("user_info_$UserID");
  709. $Cache->update_row(false, $LightUpdates);
  710. $Cache->commit_transaction(0);
  711. $Cache->begin_transaction("user_info_heavy_$UserID");
  712. $Cache->update_row(false, $HeavyUpdates);
  713. $Cache->commit_transaction(0);
  714. }
  715. $Summary = '';
  716. // Create edit summary
  717. if ($EditSummary) {
  718. $Summary = implode(', ', $EditSummary) . ' by ' . $LoggedUser['Username'];
  719. $Summary = sqltime() . ' - ' . ucfirst($Summary);
  720. if ($Reason) {
  721. $Summary .= "\nReason: $Reason";
  722. }
  723. $Summary .= "\n\n$AdminComment";
  724. } elseif (empty($UpdateSet) && empty($EditSummary) && $Cur['AdminComment'] == $_POST['AdminComment']) {
  725. $Summary = sqltime() . ' - Comment added by ' . $LoggedUser['Username'] . ': ' . "$Reason\n\n";
  726. }
  727. if (!empty($Summary)) {
  728. $UpdateSet[] = "AdminComment = '$Summary'";
  729. } else {
  730. $UpdateSet[] = "AdminComment = '$AdminComment'";
  731. }
  732. // Update cache
  733. // Build query
  734. $SET = implode(', ', $UpdateSet);
  735. $SQL = "
  736. UPDATE users_main AS m
  737. JOIN users_info AS i ON m.ID = i.UserID
  738. SET $SET
  739. WHERE m.ID = '$UserID'";
  740. // Perform update
  741. //die($SQL);
  742. $DB->query($SQL);
  743. if (isset($ClearStaffIDCache)) {
  744. $Cache->delete_value('staff_ids');
  745. }
  746. // redirect to user page
  747. header("location: user.php?id=$UserID");
  748. function translateUserStatus($Status)
  749. {
  750. switch ($Status) {
  751. case 0:
  752. return 'Unconfirmed';
  753. case 1:
  754. return 'Enabled';
  755. case 2:
  756. return 'Disabled';
  757. default:
  758. return $Status;
  759. }
  760. }
  761. function translateLeechStatus($Status)
  762. {
  763. switch ($Status) {
  764. case 0:
  765. return 'Disabled';
  766. case 1:
  767. return 'Enabled';
  768. default:
  769. return $Status;
  770. }
  771. }