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.

take_edit.php 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. <?php
  2. #declare(strict_types=1);
  3. /**
  4. * START CHECKS
  5. */
  6. authorize();
  7. $UserID = (int) $_REQUEST['userid'];
  8. Security::checkInt($UserID);
  9. // For this entire page, we should generally be using $UserID not $LoggedUser['ID'] and $U[] not $LoggedUser[]
  10. $U = Users::user_info($UserID);
  11. if (!$U) {
  12. error(404);
  13. }
  14. $Permissions = Permissions::get_permissions($U['PermissionID']);
  15. if ((int) $UserID !== $LoggedUser['ID'] && !check_perms('users_edit_profiles', $Permissions['Class'])) {
  16. send_irc(ADMIN_CHAN, 'User '.$LoggedUser['Username'].' ('.site_url().'user.php?id='.$LoggedUser['ID'].') just tried to edit the profile of '.site_url().'user.php?id='.$_REQUEST['userid']);
  17. error(403);
  18. }
  19. $Val->SetFields('stylesheet', 1, "number", "You forgot to select a stylesheet.");
  20. $Val->SetFields('styleurl', 0, "regex", "You did not enter a valid stylesheet URL.", ['regex' => '/^'.CSS_REGEX.'$/i']);
  21. // The next two are commented out because the drop-down menus were replaced with a check box and radio buttons
  22. //$Val->SetFields('disablegrouping', 0, "number", "You forgot to select your torrent grouping option.");
  23. //$Val->SetFields('torrentgrouping', 0, "number", "You forgot to select your torrent grouping option.");
  24. $Val->SetFields('postsperpage', 1, "number", "You forgot to select your posts per page option.", ['inarray' => [25, 50, 100]]);
  25. //$Val->SetFields('hidecollage', 1, "number", "You forgot to select your collage option.", ['minlength' => 0, 'maxlength' => 1]);
  26. $Val->SetFields('collagecovers', 1, "number", "You forgot to select your collage option.");
  27. $Val->SetFields('avatar', 0, "regex", "You did not enter a valid avatar URL.", ['regex' => "/^".IMAGE_REGEX."$/i"]);
  28. $Val->SetFields('email', 1, "email", "You did not enter a valid email address.");
  29. $Val->SetFields('irckey', 0, "string", "You did not enter a valid IRC key. An IRC key must be between 6 and 32 characters long.", ['minlength' => 6, 'maxlength' => 32]);
  30. $Val->SetFields('new_pass_1', 0, "regex", "You did not enter a valid password. A valid password is 15 characters or longer.", ['regex' => '/(?=^.{15,}$).*$/']);
  31. #$Val->SetFields('new_pass_1', 0, "regex", "You did not enter a valid password. A valid password is 6 characters or longer.", ['regex' => '/(?=^.{6,}$).*$/']);
  32. $Val->SetFields('new_pass_2', 1, "compare", "Your passwords do not match.", ['comparefield' => 'new_pass_1']);
  33. /*
  34. if (check_perms('site_advanced_search')) {
  35. $Val->SetFields('searchtype', 1, "number", "You forgot to select your default search preference.", ['minlength' => 0, 'maxlength' => 1]);
  36. }
  37. */
  38. $ValErr = $Val->ValidateForm($_POST);
  39. if ($ValErr) {
  40. error($ValErr);
  41. }
  42. if (!apcu_exists('DBKEY')) {
  43. error("Cannot edit profile until database fully decrypted");
  44. }
  45. /**
  46. * END CHECKS
  47. */
  48. // Begin building $Paranoia
  49. // Reduce the user's input paranoia until it becomes consistent
  50. if (isset($_POST['p_uniquegroups_l'])) {
  51. $_POST['p_uploads_l'] = 'on';
  52. $_POST['p_uploads_c'] = 'on';
  53. }
  54. if (isset($_POST['p_uploads_l'])) {
  55. $_POST['p_uniquegroups_l'] = 'on';
  56. $_POST['p_uniquegroups_c'] = 'on';
  57. $_POST['p_perfectflacs_l'] = 'on';
  58. $_POST['p_perfectflacs_c'] = 'on';
  59. $_POST['p_artistsadded'] = 'on';
  60. }
  61. if (isset($_POST['p_collagecontribs_l'])) {
  62. $_POST['p_collages_l'] = 'on';
  63. $_POST['p_collages_c'] = 'on';
  64. }
  65. if (isset($_POST['p_snatched_c']) && isset($_POST['p_seeding_c']) && isset($_POST['p_downloaded'])) {
  66. $_POST['p_requiredratio'] = 'on';
  67. }
  68. // if showing exactly 2 of stats, show all 3 of stats
  69. $StatsShown = 0;
  70. $Stats = ['downloaded', 'uploaded', 'ratio'];
  71. foreach ($Stats as $S) {
  72. if (isset($_POST["p_$S"])) {
  73. $StatsShown++;
  74. }
  75. }
  76. if ($StatsShown === 2) {
  77. foreach ($Stats as $S) {
  78. $_POST["p_$S"] = 'on';
  79. }
  80. }
  81. $Paranoia = [];
  82. $Checkboxes = ['downloaded', 'uploaded', 'ratio', 'lastseen', 'requiredratio', 'invitedcount', 'artistsadded', 'notifications'];
  83. foreach ($Checkboxes as $C) {
  84. if (!isset($_POST["p_$C"])) {
  85. $Paranoia[] = $C;
  86. }
  87. }
  88. $SimpleSelects = ['torrentcomments', 'collages', 'collagecontribs', 'uploads', 'uniquegroups', 'perfectflacs', 'seeding', 'leeching', 'snatched'];
  89. foreach ($SimpleSelects as $S) {
  90. if (!isset($_POST["p_$S".'_c']) && !isset($_POST["p_$S".'_l'])) {
  91. // Very paranoid - don't show count or list
  92. $Paranoia[] = "$S+";
  93. } elseif (!isset($_POST["p_$S".'_l'])) {
  94. // A little paranoid - show count, don't show list
  95. $Paranoia[] = $S;
  96. }
  97. }
  98. $Bounties = ['requestsfilled', 'requestsvoted'];
  99. foreach ($Bounties as $B) {
  100. if (isset($_POST["p_$B".'_list'])) {
  101. $_POST["p_$B".'_count'] = 'on';
  102. $_POST["p_$B".'_bounty'] = 'on';
  103. }
  104. if (!isset($_POST["p_$B".'_list'])) {
  105. $Paranoia[] = $B.'_list';
  106. }
  107. if (!isset($_POST["p_$B".'_count'])) {
  108. $Paranoia[] = $B.'_count';
  109. }
  110. if (!isset($_POST["p_$B".'_bounty'])) {
  111. $Paranoia[] = $B.'_bounty';
  112. }
  113. }
  114. if (!isset($_POST['p_donor_heart'])) {
  115. $Paranoia[] = 'hide_donor_heart';
  116. }
  117. if (isset($_POST['p_donor_stats'])) {
  118. Donations::show_stats($UserID);
  119. } else {
  120. Donations::hide_stats($UserID);
  121. }
  122. // End building $Paranoia
  123. $DB->query("
  124. SELECT Email, PassHash, IRCKey
  125. FROM users_main
  126. WHERE ID = ?", $UserID);
  127. list($CurEmail, $CurPassHash, $CurIRCKey) = $DB->next_record();
  128. function require_password($Setting = false)
  129. {
  130. global $CurPassHash;
  131. if (empty($_POST['cur_pass'])) {
  132. error('A setting you changed requires you to enter your current password'.($Setting ? ' (Setting: '.$Setting.')' : ''));
  133. }
  134. if (!Users::check_password($_POST['cur_pass'], $CurPassHash)) {
  135. error('The password you entered was incorrect'.($Setting ? ' (Required by setting: '.$Setting.')' : ''));
  136. }
  137. }
  138. // Email change
  139. $CurEmail = Crypto::decrypt($CurEmail);
  140. if ($CurEmail !== $_POST['email']) {
  141. // Non-admins have to authenticate to change email
  142. if (!check_perms('users_edit_profiles')) {
  143. require_password("Change Email");
  144. }
  145. // Update the time of their last email change to the current time *not* the current change.
  146. $DB->query("
  147. UPDATE users_history_emails
  148. SET Time = NOW()
  149. WHERE UserID = ?
  150. AND Time IS NULL", $UserID);
  151. $DB->query("
  152. INSERT INTO users_history_emails
  153. (UserID, Email, Time, IP)
  154. VALUES
  155. (?, ?, NULL, ?)", $UserID, Crypto::encrypt($_POST['email']), Crypto::encrypt($_SERVER['REMOTE_ADDR']));
  156. }
  157. if (!empty($_POST['new_pass_1']) && !empty($_POST['new_pass_2'])) {
  158. require_password("Change Password");
  159. $ResetPassword = true;
  160. }
  161. if ($CurIRCKey != $_POST['irckey']) {
  162. require_password("Change IRC Key");
  163. }
  164. if (isset($_POST['resetpasskey'])) {
  165. require_password("Reset Passkey");
  166. }
  167. if ($LoggedUser['DisableAvatar'] && $_POST['avatar'] != $U['Avatar']) {
  168. error('Your avatar privileges have been revoked.');
  169. }
  170. if (!empty($LoggedUser['DefaultSearch'])) {
  171. $Options['DefaultSearch'] = $LoggedUser['DefaultSearch'];
  172. }
  173. $Options['DisableGrouping2'] = (!empty($_POST['disablegrouping']) ? 0 : 1);
  174. $Options['TorrentGrouping'] = (!empty($_POST['torrentgrouping']) ? 1 : 0);
  175. $Options['PostsPerPage'] = (int)$_POST['postsperpage'];
  176. $Options['CollageCovers'] = (empty($_POST['collagecovers']) ? 0 : $_POST['collagecovers']);
  177. $Options['ShowTorFilter'] = (empty($_POST['showtfilter']) ? 0 : 1);
  178. $Options['ShowTags'] = (!empty($_POST['showtags']) ? 1 : 0);
  179. $Options['AutoSubscribe'] = (!empty($_POST['autosubscribe']) ? 1 : 0);
  180. $Options['DisableSmileys'] = (!empty($_POST['disablesmileys']) ? 1 : 0);
  181. $Options['AutoloadCommStats'] = (check_perms('users_mod') && !empty($_POST['autoload_comm_stats']) ? 1 : 0);
  182. $Options['DisableAvatars'] = db_string($_POST['disableavatars']);
  183. $Options['Identicons'] = (!empty($_POST['identicons']) ? (int)$_POST['identicons'] : 0);
  184. $Options['DisablePMAvatars'] = (!empty($_POST['disablepmavatars']) ? 1 : 0);
  185. $Options['NotifyOnQuote'] = (!empty($_POST['notifications_Quotes_popup']) ? 1 : 0);
  186. $Options['ListUnreadPMsFirst'] = (!empty($_POST['list_unread_pms_first']) ? 1 : 0);
  187. $Options['ShowSnatched'] = (!empty($_POST['showsnatched']) ? 1 : 0);
  188. $Options['DisableAutoSave'] = (!empty($_POST['disableautosave']) ? 1 : 0);
  189. $Options['CoverArt'] = (int)!empty($_POST['coverart']);
  190. $Options['ShowExtraCovers'] = (int)!empty($_POST['show_extra_covers']);
  191. $Options['HideLolicon'] = (int)!empty($_POST['hide_lolicon']);
  192. $Options['HideScat'] = (int)!empty($_POST['hide_scat']);
  193. $Options['HideSnuff'] = (int)!empty($_POST['hide_snuff']);
  194. $Options['AutoComplete'] = (int)$_POST['autocomplete'];
  195. $Options['StyleAdditions'] = $_POST['style_additions'] ?? [];
  196. if (isset($LoggedUser['DisableFreeTorrentTop10'])) {
  197. $Options['DisableFreeTorrentTop10'] = $LoggedUser['DisableFreeTorrentTop10'];
  198. }
  199. if (!empty($_POST['sorthide'])) {
  200. $JSON = json_decode($_POST['sorthide']);
  201. foreach ($JSON as $J) {
  202. $E = explode('_', $J);
  203. $Options['SortHide'][$E[0]] = $E[1];
  204. }
  205. } else {
  206. $Options['SortHide'] = [];
  207. }
  208. if (check_perms('site_advanced_search')) {
  209. $Options['SearchType'] = $_POST['searchtype'];
  210. } else {
  211. unset($Options['SearchType']);
  212. }
  213. // todo: Remove the following after a significant amount of time
  214. unset($Options['ArtistNoRedirect']);
  215. unset($Options['ShowQueryList']);
  216. unset($Options['ShowCacheList']);
  217. $UnseededAlerts = isset($_POST['unseededalerts']) ? 1 : 0;
  218. Donations::update_rewards($UserID);
  219. NotificationsManager::save_settings($UserID);
  220. // Begin Badge settings
  221. if (!empty($_POST['badges'])) {
  222. $BadgeIDs = array_slice($_POST['badges'], 0, 5);
  223. } else {
  224. $BadgeIDs = [];
  225. }
  226. $NewBadges = [];
  227. $BadgesChanged = false;
  228. $Badges = Users::user_info($UserID)['Badges'];
  229. foreach ($Badges as $BadgeID => $OldDisplayed) {
  230. if (in_array($BadgeID, $BadgeIDs)) { // Is the current badge in the list of badges the user wants to display?
  231. $Displayed = true;
  232. $DisplayedBadgeIDs[] = $BadgeID;
  233. if ($OldDisplayed == 0) { // The user wants to display a badge that wasn't displayed before
  234. $BadgesChanged = true;
  235. }
  236. } else { // The user no longer wants to display a badge that was displayed before
  237. $Displayed = false;
  238. $BadgesChanged = true;
  239. }
  240. $NewBadges[$BadgeID] = $Displayed?'1':'0';
  241. }
  242. // End Badge settings
  243. $Cache->begin_transaction("user_info_$UserID");
  244. $Cache->update_row(false, [
  245. 'Avatar' => display_str($_POST['avatar']),
  246. 'Paranoia' => $Paranoia,
  247. 'Badges' => $NewBadges
  248. ]);
  249. $Cache->commit_transaction(0);
  250. $Cache->begin_transaction("user_info_heavy_$UserID");
  251. $Cache->update_row(false, [
  252. 'StyleID' => $_POST['stylesheet'],
  253. 'StyleURL' => display_str($_POST['styleurl'])
  254. ]);
  255. $Cache->update_row(false, $Options);
  256. $Cache->commit_transaction(0);
  257. $SQL = "
  258. UPDATE users_main AS m
  259. JOIN users_info AS i ON m.ID = i.UserID
  260. SET
  261. i.StyleID = '".db_string($_POST['stylesheet'])."',
  262. i.StyleURL = '".db_string($_POST['styleurl'])."',
  263. i.Avatar = '".db_string($_POST['avatar'])."',
  264. i.SiteOptions = '".db_string(json_encode($Options))."',
  265. i.NotifyOnQuote = '".db_string($Options['NotifyOnQuote'])."',
  266. i.Info = '".db_string($_POST['info'])."',
  267. i.InfoTitle = '".db_string($_POST['profile_title'])."',
  268. i.UnseededAlerts = '$UnseededAlerts',
  269. m.Email = '".Crypto::encrypt($_POST['email'])."',
  270. m.IRCKey = '".db_string($_POST['irckey'])."',
  271. m.Paranoia = '".db_string(json_encode($Paranoia))."'";
  272. if ($ResetPassword) {
  273. $ChangerIP = Crypto::encrypt($LoggedUser['IP']);
  274. $PassHash = Users::make_sec_hash($_POST['new_pass_1']);
  275. $SQL.= ",m.PassHash = '".db_string($PassHash)."'";
  276. $DB->query("
  277. INSERT INTO users_history_passwords
  278. (UserID, ChangerIP, ChangeTime)
  279. VALUES
  280. (?, ?, NOW())", $UserID, $ChangerIP);
  281. }
  282. if (isset($_POST['resetpasskey'])) {
  283. $UserInfo = Users::user_heavy_info($UserID);
  284. $OldPassKey = $UserInfo['torrent_pass'];
  285. $NewPassKey = Users::make_secret();
  286. $ChangerIP = Crypto::encrypt($LoggedUser['IP']);
  287. $SQL .= ",m.torrent_pass = '$NewPassKey'";
  288. $DB->query(
  289. "
  290. INSERT INTO users_history_passkeys
  291. (UserID, OldPassKey, NewPassKey, ChangerIP, ChangeTime)
  292. VALUES
  293. (?, ?, ?, ?, NOW())",
  294. $USerID,
  295. $OldPassKey,
  296. $NewPassKey,
  297. $ChangerIP
  298. );
  299. $Cache->begin_transaction("user_info_heavy_$UserID");
  300. $Cache->update_row(false, ['torrent_pass' => $NewPassKey]);
  301. $Cache->commit_transaction(0);
  302. $Cache->delete_value("user_$OldPassKey");
  303. Tracker::update_tracker('change_passkey', ['oldpasskey' => $OldPassKey, 'newpasskey' => $NewPassKey]);
  304. }
  305. $SQL .= "WHERE m.ID = '".db_string($UserID)."'";
  306. $DB->query($SQL);
  307. if ($BadgesChanged) {
  308. $DB->query("
  309. UPDATE users_badges
  310. SET Displayed = 0
  311. WHERE UserID = ?", $UserID);
  312. if (!empty($BadgeIDs)) {
  313. $DB->query("
  314. UPDATE users_badges
  315. SET Displayed = 1
  316. WHERE UserID = $UserID
  317. AND BadgeID IN (".db_string(implode(',', $BadgeIDs)).")");
  318. }
  319. }
  320. if ($ResetPassword) {
  321. logout_all_sessions();
  322. }
  323. header("Location: user.php?action=edit&userid=$UserID");