PageRenderTime 78ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/campsite/src/include/phorum/include/db/mysql.php

https://github.com/joechrysler/Campsite
PHP | 4826 lines | 2735 code | 952 blank | 1139 comment | 641 complexity | 59bf8d53d9cc8b3908053949cfff1479 MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, LGPL-2.1, Apache-2.0
  1. <?php
  2. ////////////////////////////////////////////////////////////////////////////////
  3. // //
  4. // Copyright (C) 2006 Phorum Development Team //
  5. // http://www.phorum.org //
  6. // //
  7. // This program is free software. You can redistribute it and/or modify //
  8. // it under the terms of either the current Phorum License (viewable at //
  9. // phorum.org) or the Phorum License that was distributed with this file //
  10. // //
  11. // This program is distributed in the hope that it will be useful, //
  12. // but WITHOUT ANY WARRANTY, without even the implied warranty of //
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. //
  14. // //
  15. // You should have received a copy of the Phorum License //
  16. // along with this program. //
  17. ////////////////////////////////////////////////////////////////////////////////
  18. // cvs-info: $Id: mysql.php 1039 2006-05-10 16:01:56Z brian $
  19. if (!defined("PHORUM")) return;
  20. /**
  21. * The other Phorum code does not care how the messages are stored.
  22. * The only requirement is that they are returned from these functions
  23. * in the right way. This means each database can use as many or as
  24. * few tables as it likes. It can store the fields anyway it wants.
  25. * The only thing to worry about is the table_prefix for the tables.
  26. * all tables for a Phorum install should be prefixed with the
  27. * table_prefix that will be entered in include/db/config.php. This
  28. * will allow multiple Phorum installations to use the same database.
  29. */
  30. /**
  31. * These are the table names used for this database system.
  32. */
  33. // tables needed to be "partitioned"
  34. $PHORUM["message_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_messages";
  35. $PHORUM["user_newflags_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_user_newflags";
  36. $PHORUM["subscribers_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_subscribers";
  37. $PHORUM["files_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_files";
  38. $PHORUM["search_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_search";
  39. // tables common to all "partitions"
  40. $PHORUM["settings_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_settings";
  41. $PHORUM["forums_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_forums";
  42. $PHORUM["user_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_users";
  43. $PHORUM["user_permissions_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_user_permissions";
  44. $PHORUM["groups_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_groups";
  45. $PHORUM["forum_group_xref_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_forum_group_xref";
  46. $PHORUM["user_group_xref_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_user_group_xref";
  47. $PHORUM['user_custom_fields_table'] = "{$PHORUM['DBCONFIG']['table_prefix']}_user_custom_fields";
  48. $PHORUM["banlist_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_banlists";
  49. $PHORUM["pm_messages_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_pm_messages";
  50. $PHORUM["pm_folders_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_pm_folders";
  51. $PHORUM["pm_xref_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_pm_xref";
  52. $PHORUM["pm_buddies_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_pm_buddies";
  53. /*
  54. * fields which are always strings, even if they contain only numbers
  55. * used in post-message and update-message, otherwise strange things happen
  56. */
  57. $PHORUM['string_fields']= array('author', 'subject', 'body', 'email');
  58. /* A piece of SQL code that can be used for identifying moved messages. */
  59. define('PHORUM_SQL_MOVEDMESSAGES', '(parent_id = 0 and thread != message_id)');
  60. /**
  61. * Get the visible messages for a given page offset. The main Phorum code
  62. * handles actually sorting the threads into a threaded list if needed.
  63. *
  64. * By default, the message body is not included in the fetch queries.
  65. * If the body is needed in the thread list, $PHORUM['TMP']['bodies_in_list']
  66. * must be set to "1" (for example using setting.tpl).
  67. *
  68. * NOTE: ALL dates should be returned as Unix timestamps
  69. *
  70. * @param int $offset - the index of the page to return, starting with 0
  71. *
  72. * @return array
  73. */
  74. function phorum_db_get_thread_list($offset)
  75. {
  76. $PHORUM = $GLOBALS["PHORUM"];
  77. settype($offset, "int");
  78. $conn = phorum_db_mysql_connect();
  79. $table = $PHORUM["message_table"];
  80. // The messagefields that we want to fetch from the database.
  81. $messagefields =
  82. "$table.author,
  83. $table.datestamp,
  84. $table.email,
  85. $table.message_id,
  86. $table.meta,
  87. $table.moderator_post,
  88. $table.modifystamp,
  89. $table.parent_id,
  90. $table.sort,
  91. $table.status,
  92. $table.subject,
  93. $table.thread,
  94. $table.thread_count,
  95. $table.user_id,
  96. $table.viewcount,
  97. $table.closed";
  98. if(isset($PHORUM['TMP']['bodies_in_list']) && $PHORUM['TMP']['bodies_in_list'] == 1) {
  99. $messagefields .= "\n,$table.body\n,$table.ip";
  100. }
  101. // The sort mechanism to use.
  102. if($PHORUM["float_to_top"]){
  103. $sortfield = "modifystamp";
  104. $index = "list_page_float";
  105. } else{
  106. $sortfield = "thread";
  107. $index = "list_page_flat";
  108. }
  109. // Initialize the return array.
  110. $messages = array();
  111. // The groups of messages we want to fetch from the database.
  112. $groups = array();
  113. if ($offset == 0) $groups[] = "specials";
  114. $groups[] = "threads";
  115. if ($PHORUM["threaded_list"]) $groups[] = "replies";
  116. // for remembering message ids for which we want to fetch the replies.
  117. $replymsgids = array();
  118. // Process all groups.
  119. foreach ($groups as $group) {
  120. $sql = NULL;
  121. switch ($group) {
  122. // Announcements and stickies.
  123. case "specials":
  124. $sql = "select $messagefields
  125. from $table
  126. where
  127. status=".PHORUM_STATUS_APPROVED." and
  128. ((parent_id=0 and sort=".PHORUM_SORT_ANNOUNCEMENT."
  129. and forum_id={$PHORUM['vroot']})
  130. or
  131. (parent_id=0 and sort=".PHORUM_SORT_STICKY."
  132. and forum_id={$PHORUM['forum_id']}))
  133. order by
  134. sort, $sortfield desc";
  135. break;
  136. // Threads.
  137. case "threads":
  138. if ($PHORUM["threaded_list"]) {
  139. $limit = $PHORUM['list_length_threaded'];
  140. $extrasql = '';
  141. } else {
  142. $limit = $PHORUM['list_length_flat'];
  143. }
  144. $start = $offset * $limit;
  145. $sql = "select $messagefields
  146. from $table use index ($index)
  147. where
  148. $sortfield > 0 and
  149. forum_id = {$PHORUM["forum_id"]} and
  150. status = ".PHORUM_STATUS_APPROVED." and
  151. parent_id = 0 and
  152. sort > 1
  153. order by
  154. $sortfield desc
  155. limit $start, $limit";
  156. break;
  157. // Reply messages.
  158. case "replies":
  159. // We're done if we did not collect any messages with replies.
  160. if (! count($replymsgids)) break;
  161. $sortorder = "sort, $sortfield desc, message_id";
  162. if(isset($PHORUM["reverse_threading"]) && $PHORUM["reverse_threading"])
  163. $sortorder.=" desc";
  164. $sql = "select $messagefields
  165. from $table
  166. where
  167. status = ".PHORUM_STATUS_APPROVED." and
  168. thread in (" . implode(",",$replymsgids) .")
  169. order by $sortorder";
  170. break;
  171. } // End of switch ($group)
  172. // Continue with the next group if no SQL query was formulated.
  173. if (is_null($sql)) continue;
  174. // Fetch the messages for the current group.
  175. $res = mysql_query($sql, $conn);
  176. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  177. $rows = mysql_num_rows($res);
  178. if($rows > 0){
  179. while ($rec = mysql_fetch_assoc($res)){
  180. $messages[$rec["message_id"]] = $rec;
  181. $messages[$rec["message_id"]]["meta"] = array();
  182. if(!empty($rec["meta"])){
  183. $messages[$rec["message_id"]]["meta"] = unserialize($rec["meta"]);
  184. }
  185. // We need the message ids for fetching reply messages.
  186. if ($group == 'threads' && $rec["thread_count"] > 1) {
  187. $replymsgids[] = $rec["message_id"];
  188. }
  189. }
  190. }
  191. }
  192. return $messages;
  193. }
  194. /**
  195. * Get the recent messages for all forums the user can read, a particular
  196. * forum, or a particular thread, and returns an array of the messages
  197. * order by message_id. You can optionally retrieve only new threads.
  198. *
  199. * The original version of this function came from Jim Winstead of mysql.com
  200. *
  201. * @param int $count
  202. * Limit the number of returned messages to this number.
  203. * @param int $forum_id
  204. * @param int $thread
  205. * @param boolean $threads_only
  206. * If set to TRUE, only get the top message from each thread.
  207. *
  208. * @return array
  209. */
  210. function phorum_db_get_recent_messages($count, $forum_id = 0, $thread = 0, $threads_only = 0)
  211. {
  212. $PHORUM = $GLOBALS["PHORUM"];
  213. settype($count, "int");
  214. settype($thread, "int");
  215. $arr = array();
  216. $allowed_forums = array();
  217. $conn = phorum_db_mysql_connect();
  218. // we need to differentiate on which key to use
  219. if($thread) {
  220. $use_key='thread_message';
  221. } else {
  222. $use_key='forum_max_message';
  223. }
  224. $sql = "SELECT {$PHORUM['message_table']}.* FROM {$PHORUM['message_table']} USE KEY($use_key) WHERE status=".PHORUM_STATUS_APPROVED;
  225. // have to check what forums they can read first.
  226. // even if $thread is passed, we have to make sure
  227. // the user can read the forum
  228. if($forum_id <= 0) {
  229. $allowed_forums=phorum_user_access_list(PHORUM_USER_ALLOW_READ);
  230. // if they are not allowed to see any forums, return the emtpy $arr;
  231. if(empty($allowed_forums))
  232. return $arr;
  233. } elseif(is_array($forum_id)) {
  234. // for an array, check each one and return if none are allowed
  235. foreach($forum_id as $id){
  236. if(phorum_user_access_allowed(PHORUM_USER_ALLOW_READ,$id)) {
  237. $allowed_forums[]=$id;
  238. }
  239. }
  240. // if they are not allowed to see any forums, return the emtpy $arr;
  241. if(empty($allowed_forums))
  242. return $arr;
  243. } else {
  244. // only single forum, *much* fast this way
  245. if(!phorum_user_access_allowed(PHORUM_USER_ALLOW_READ,$forum_id)) {
  246. return $arr;
  247. }
  248. settype($forum_id, "int");
  249. }
  250. if(count($allowed_forums)){
  251. $sql.=" and forum_id in (".implode(",", $allowed_forums).")";
  252. } else {
  253. $sql.=" and forum_id=$forum_id";
  254. }
  255. if($thread){
  256. $sql.=" and thread=$thread";
  257. }
  258. if($threads_only) {
  259. $sql.= " and parent_id = 0";
  260. $sql.= " ORDER BY thread DESC";
  261. } else {
  262. $sql.= " ORDER BY message_id DESC";
  263. }
  264. if($count){
  265. $sql.= " LIMIT $count";
  266. }
  267. $res = mysql_query($sql, $conn);
  268. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  269. while ($rec = mysql_fetch_assoc($res)){
  270. $arr[$rec["message_id"]] = $rec;
  271. // convert meta field
  272. if(empty($rec["meta"])){
  273. $arr[$rec["message_id"]]["meta"]=array();
  274. } else {
  275. $arr[$rec["message_id"]]["meta"]=unserialize($rec["meta"]);
  276. }
  277. if(empty($arr['users'])) $arr['users']=array();
  278. if($rec["user_id"]){
  279. $arr['users'][]=$rec["user_id"];
  280. }
  281. }
  282. return $arr;
  283. }
  284. /**
  285. * Get messages which have not yet been approved by a moderator.
  286. * The main Phorum code handles actually sorting the threads into
  287. * a threaded list if needed.
  288. *
  289. * NOTE: ALL dates should be returned as Unix timestamps
  290. * @param mixed $forum
  291. * The forum id to work with.
  292. * Set to NULL if you want to search all forums.
  293. * You can also pass an array of forum id's.
  294. * @param boolean $waiting_only
  295. * Only take into account messages which have to
  296. * be approved directly after posting. Do not include
  297. * messages which are hidden by a moderator.
  298. * @param int $moddays
  299. * Limit the search to the last $moddays number of days.
  300. * @return array
  301. * An array of messages, indexed by message ID.
  302. */
  303. function phorum_db_get_unapproved_list($forum = NULL, $waiting_only=false,$moddays=0)
  304. {
  305. $PHORUM = $GLOBALS["PHORUM"];
  306. $conn = phorum_db_mysql_connect();
  307. $table = $PHORUM["message_table"];
  308. $arr = array();
  309. $sql = "select
  310. $table.*
  311. from
  312. $table ";
  313. if (is_array($forum)){
  314. $sql .= "where forum_id in (" . implode(",", $forum) . ") and ";
  315. } elseif (! is_null($forum)){
  316. settype($forum, "int");
  317. $sql .= "where forum_id = $forum and ";
  318. } else {
  319. $sql .= "where ";
  320. }
  321. if($moddays > 0) {
  322. $checktime=time()-(86400*$moddays);
  323. $sql .=" datestamp > $checktime AND";
  324. }
  325. if($waiting_only){
  326. $sql.=" status=".PHORUM_STATUS_HOLD;
  327. } else {
  328. $sql="($sql status=".PHORUM_STATUS_HOLD.") " .
  329. "union ($sql status=".PHORUM_STATUS_HIDDEN.")";
  330. }
  331. $sql .=" order by thread, message_id";
  332. $res = mysql_query($sql, $conn);
  333. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  334. while ($rec = mysql_fetch_assoc($res)){
  335. $arr[$rec["message_id"]] = $rec;
  336. $arr[$rec["message_id"]]["meta"] = array();
  337. if(!empty($rec["meta"])){
  338. $arr[$rec["message_id"]]["meta"] = unserialize($rec["meta"]);
  339. }
  340. }
  341. return $arr;
  342. }
  343. /**
  344. * Add a message. The message will not be posted if it is a duplicate
  345. * and $PHORUM['check_duplicate'] is set.
  346. *
  347. * The $message is passed by reference and when the function completes
  348. * successfully, the "message_id" index will be set to the new value.
  349. * If the "thread" index is set to zero, a new thread will be started and the
  350. * "thread" index will be filled with the new thread ID upon return.
  351. *
  352. * @param array $message
  353. * The $message array must contain the following indexes:
  354. * forum_id, thread, parent_id, author, subject, email, ip,
  355. * user_id, moderator_post, status, sort, msgid, body, closed
  356. *
  357. * @param boolean $convert
  358. *
  359. * @return boolean
  360. * TRUE on success, FALSE on failure.
  361. *
  362. */
  363. function phorum_db_post_message(&$message,$convert=false){
  364. $PHORUM = $GLOBALS["PHORUM"];
  365. $table = $PHORUM["message_table"];
  366. $conn = phorum_db_mysql_connect();
  367. $success = false;
  368. foreach($message as $key => $value){
  369. if (is_numeric($value) && !in_array($key,$PHORUM['string_fields'])){
  370. $message[$key] = (int)$value;
  371. } elseif(is_array($value)) {
  372. $message[$key] = mysql_escape_string(serialize($value));
  373. } else{
  374. $message[$key] = mysql_escape_string($value);
  375. }
  376. }
  377. if(!$convert) {
  378. $NOW = time();
  379. } else {
  380. $NOW = $message['datestamp'];
  381. }
  382. // duplicate-check
  383. if(isset($PHORUM['check_duplicate']) && $PHORUM['check_duplicate'] && !$convert) {
  384. // we check for dupes in that number of minutes
  385. $check_minutes=60;
  386. $check_timestamp =$NOW - ($check_minutes*60);
  387. // check_query
  388. $chk_query="SELECT message_id FROM $table WHERE forum_id = {$message['forum_id']} AND author='{$message['author']}' AND subject='{$message['subject']}' AND body='{$message['body']}' AND datestamp > $check_timestamp";
  389. $res = mysql_query($chk_query, $conn);
  390. if ($err = mysql_error()) phorum_db_mysql_error("$err: $chk_query");
  391. if(mysql_num_rows($res))
  392. return 0;
  393. }
  394. if(isset($message['meta'])){
  395. $metaval=",meta='{$message['meta']}'";
  396. } else {
  397. $metaval="";
  398. }
  399. $sql = "Insert into $table set
  400. forum_id = {$message['forum_id']},
  401. datestamp=$NOW,
  402. thread={$message['thread']},
  403. parent_id={$message['parent_id']},
  404. author='{$message['author']}',
  405. subject='{$message['subject']}',
  406. email='{$message['email']}',
  407. ip='{$message['ip']}',
  408. user_id={$message['user_id']},
  409. moderator_post={$message['moderator_post']},
  410. status={$message['status']},
  411. sort={$message['sort']},
  412. msgid='{$message['msgid']}',
  413. body='{$message['body']}',
  414. closed={$message['closed']}
  415. $metaval";
  416. // if in conversion we need the message-id too
  417. if($convert && isset($message['message_id'])) {
  418. $sql.=",message_id=".$message['message_id'];
  419. }
  420. if(isset($message['modifystamp'])) {
  421. $sql.=",modifystamp=".$message['modifystamp'];
  422. }
  423. if(isset($message['viewcount'])) {
  424. $sql.=",viewcount=".$message['viewcount'];
  425. }
  426. $res = mysql_query($sql, $conn);
  427. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  428. if ($res){
  429. $message["message_id"] = mysql_insert_id($conn);
  430. if(!empty($message["message_id"])){
  431. $message["datestamp"]=$NOW;
  432. if ($message["thread"] == 0){
  433. $message["thread"] = $message["message_id"];
  434. $sql = "update $table set thread={$message['message_id']} where message_id={$message['message_id']}";
  435. $res = mysql_query($sql, $conn);
  436. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  437. }
  438. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  439. // start ft-search stuff
  440. if($PHORUM["DBCONFIG"]["mysql_use_ft"]){
  441. $search_text="$message[author] | $message[subject] | $message[body]";
  442. $sql="insert delayed into {$PHORUM['search_table']} set message_id={$message['message_id']}, forum_id={$message['forum_id']}, search_text='$search_text'";
  443. $res = mysql_query($sql, $conn);
  444. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  445. }
  446. // end ft-search stuff
  447. $success = true;
  448. // some data for later use, i.e. email-notification
  449. $GLOBALS['PHORUM']['post_returns']['message_id']=$message["message_id"];
  450. $GLOBALS['PHORUM']['post_returns']['thread_id']=$message["thread"];
  451. }
  452. }
  453. return $success;
  454. }
  455. /**
  456. * Relate a message to Campsite.
  457. *
  458. * It affects campsite.ArticleComments
  459. *
  460. * @param array $message
  461. * The $message array must contain the following indexes:
  462. * thread, message_id
  463. *
  464. * @return boolean
  465. * TRUE on success, FALSE on failure.
  466. *
  467. */
  468. function phorum_db_relate_message_to_campsite($message)
  469. {
  470. $PHORUM = $GLOBALS["PHORUM"];
  471. $conn = phorum_db_mysql_connect();
  472. $success = false;
  473. $sql = "SELECT fk_article_number, fk_language_id
  474. FROM ArticleComments
  475. WHERE fk_comment_id = '".$message['thread']."'";
  476. $res = mysql_query($sql, $conn);
  477. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  478. if ($res) {
  479. $data = mysql_fetch_array($res);
  480. if (!empty($data['fk_article_number'])) {
  481. $article_number = $data['fk_article_number'];
  482. $article_language = $data['fk_language_id'];
  483. $sql = "INSERT INTO ArticleComments
  484. (fk_article_number, fk_language_id, fk_comment_id, is_first)
  485. VALUES ('".$article_number."', '".$article_language."', '".
  486. $message['message_id']."', '0')";
  487. $res = mysql_query($sql, $conn);
  488. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  489. if ($res) {
  490. $success = true;
  491. }
  492. }
  493. }
  494. return $success;
  495. }
  496. /**
  497. * Delete a message.
  498. *
  499. * @param int $message_id The id of the message which should be deleted
  500. * @param int $mode The mode of deletion,
  501. * PHORUM_DELETE_MESSAGE for reconnecting the children,
  502. * PHORUM_DELETE_TREE for deleting the children
  503. */
  504. function phorum_db_delete_message($message_id, $mode = PHORUM_DELETE_MESSAGE)
  505. {
  506. $PHORUM = $GLOBALS["PHORUM"];
  507. $conn = phorum_db_mysql_connect();
  508. settype($message_id, "int");
  509. $threadset = 0;
  510. // get the parents of the message to delete.
  511. $sql = "select forum_id, message_id, thread, parent_id from {$PHORUM['message_table']} where message_id = $message_id ";
  512. $res = mysql_query($sql, $conn);
  513. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  514. $rec = mysql_fetch_assoc($res);
  515. if($mode == PHORUM_DELETE_TREE){
  516. $mids = phorum_db_get_messagetree($message_id, $rec['forum_id']);
  517. }else{
  518. $mids = $message_id;
  519. }
  520. // unapprove the messages first so replies will not get posted
  521. $sql = "update {$PHORUM['message_table']} set status=".PHORUM_STATUS_HOLD." where message_id in ($mids)";
  522. $res = mysql_query($sql, $conn);
  523. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  524. $thread = $rec['thread'];
  525. if($thread == $message_id && $mode == PHORUM_DELETE_TREE){
  526. $threadset = 1;
  527. }else{
  528. $threadset = 0;
  529. }
  530. if($mode == PHORUM_DELETE_MESSAGE){
  531. $count = 1;
  532. // change the children to point to their parent's parent
  533. // forum_id is in here for speed by using a key only
  534. $sql = "update {$PHORUM['message_table']} set parent_id=$rec[parent_id] where forum_id=$rec[forum_id] and parent_id=$rec[message_id]";
  535. mysql_query($sql, $conn);
  536. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  537. }else{
  538. $count = count(explode(",", $mids));
  539. }
  540. // delete the messages
  541. $sql = "delete from {$PHORUM['message_table']} where message_id in ($mids)";
  542. mysql_query($sql, $conn);
  543. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  544. // start ft-search stuff
  545. $sql="delete from {$PHORUM['search_table']} where message_id in ($mids)";
  546. $res = mysql_query($sql, $conn);
  547. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  548. // end ft-search stuff
  549. // it kind of sucks to have this here, but it is the best way
  550. // to ensure that it gets done if stuff is deleted.
  551. // leave this include here, it needs to be conditional
  552. include_once("./include/thread_info.php");
  553. phorum_update_thread_info($thread);
  554. // we need to delete the subscriptions for that thread too
  555. $sql = "DELETE FROM {$PHORUM['subscribers_table']} WHERE forum_id > 0 AND thread=$thread";
  556. $res = mysql_query($sql, $conn);
  557. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  558. // this function will be slow with a lot of messages.
  559. phorum_db_update_forum_stats(true);
  560. return explode(",", $mids);
  561. }
  562. /**
  563. * Get all attached messages to a message.
  564. *
  565. * @param int $parent_id
  566. * @param int $forum_id
  567. *
  568. * @return string
  569. */
  570. function phorum_db_get_messagetree($parent_id, $forum_id){
  571. $PHORUM = $GLOBALS["PHORUM"];
  572. settype($parent_id, "int");
  573. settype($forum_id, "int");
  574. $conn = phorum_db_mysql_connect();
  575. $sql = "Select message_id from {$PHORUM['message_table']} where forum_id=$forum_id and parent_id=$parent_id";
  576. $res = mysql_query($sql, $conn);
  577. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  578. $tree = "$parent_id";
  579. while($rec = mysql_fetch_row($res)){
  580. $tree .= "," . phorum_db_get_messagetree($rec[0],$forum_id);
  581. }
  582. return $tree;
  583. }
  584. /**
  585. * Update a message with new data.
  586. *
  587. * @param int $message_id
  588. * @param array $message
  589. * See phorum_db_post_message() for a list of available fields.
  590. * You can pass in as many or as few fields as you wish to update.
  591. *
  592. * @return boolean
  593. * TRUE on success, FALSE on failure.
  594. */
  595. function phorum_db_update_message($message_id, $message)
  596. {
  597. $PHORUM = $GLOBALS["PHORUM"];
  598. settype($message_id, "int");
  599. if (count($message) > 0){
  600. $conn = phorum_db_mysql_connect();
  601. foreach($message as $field => $value){
  602. if (is_numeric($value) && !in_array($field,$PHORUM['string_fields'])){
  603. $fields[] = "$field=$value";
  604. }elseif (is_array($value)){
  605. $value = mysql_escape_string(serialize($value));
  606. $message[$field] = $value;
  607. $fields[] = "$field='$value'";
  608. }else{
  609. $value = mysql_escape_string($value);
  610. $message[$field] = $value;
  611. $fields[] = "$field='$value'";
  612. }
  613. }
  614. $sql = "update {$PHORUM['message_table']} set " . implode(", ", $fields) . " where message_id=$message_id";
  615. $res = mysql_query($sql, $conn);
  616. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  617. if($res){
  618. // start ft-search stuff
  619. if(isset($message["author"]) && isset($message["subject"]) && isset($message["body"])){
  620. $search_text="$message[author] | $message[subject] | $message[body]";
  621. $sql="replace delayed into {$PHORUM['search_table']} set message_id={$message_id}, forum_id={$message['forum_id']}, search_text='$search_text'";
  622. $res = mysql_query($sql, $conn);
  623. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  624. }
  625. // end ft-search stuff
  626. }
  627. return ($res > 0) ? true : false;
  628. }else{
  629. trigger_error("\$message cannot be empty in phorum_update_message()", E_USER_ERROR);
  630. }
  631. }
  632. /**
  633. * Get the first message that matches the search parameters. If
  634. * you pass in multiple matches targets, this will return an array
  635. * of messages. Otherwise it will return a single message.
  636. *
  637. * @param mixed $value
  638. * The value in the database column that you want to match.
  639. * This can be an array, in which case this will return the messages
  640. * that match any of the given values in the array.
  641. * @param string $field
  642. * The database column you are searching to find $value.
  643. * @param boolean $ignore_forum_id
  644. * @return array
  645. */
  646. function phorum_db_get_message($value, $field="message_id", $ignore_forum_id=false)
  647. {
  648. $PHORUM = $GLOBALS["PHORUM"];
  649. $field=mysql_escape_string($field);
  650. $multiple=false;
  651. $conn = phorum_db_mysql_connect();
  652. $forum_id_check = "";
  653. if (!$ignore_forum_id && !empty($PHORUM["forum_id"])){
  654. $forum_id_check = "(forum_id = {$PHORUM['forum_id']} OR forum_id={$PHORUM['vroot']}) and";
  655. }
  656. if(is_array($value)) {
  657. $checkvar="$field IN('".implode("','",$value)."')";
  658. $multiple=true;
  659. } else {
  660. $value=mysql_escape_string($value);
  661. $checkvar="$field='$value'";
  662. }
  663. $sql = "select {$PHORUM['message_table']}.* from {$PHORUM['message_table']} where $forum_id_check $checkvar";
  664. $res = mysql_query($sql, $conn);
  665. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  666. $ret = $multiple ? array() : NULL;
  667. if(mysql_num_rows($res)){
  668. if($multiple) {
  669. while($rec=mysql_fetch_assoc($res)) {
  670. // convert meta field
  671. if(empty($rec["meta"])){
  672. $rec["meta"]=array();
  673. } else {
  674. $rec["meta"]=unserialize($rec["meta"]);
  675. }
  676. $ret[$rec['message_id']]=$rec;
  677. }
  678. } else {
  679. $rec = mysql_fetch_assoc($res);
  680. // convert meta field
  681. if(empty($rec["meta"])){
  682. $rec["meta"]=array();
  683. } else {
  684. $rec["meta"]=unserialize($rec["meta"]);
  685. }
  686. $ret=$rec;
  687. }
  688. }
  689. return $ret;
  690. }
  691. /**
  692. * Get messages with the given thread id. Returns an array of messages.
  693. *
  694. * @param int $thread
  695. * @param int $page
  696. * @return array
  697. */
  698. function phorum_db_get_messages($thread,$page=0)
  699. {
  700. $PHORUM = $GLOBALS["PHORUM"];
  701. settype($thread, "int");
  702. $conn = phorum_db_mysql_connect();
  703. $forum_id_check = "";
  704. if (!empty($PHORUM["forum_id"])){
  705. $forum_id_check = "(forum_id = {$PHORUM['forum_id']} OR forum_id={$PHORUM['vroot']}) and";
  706. }
  707. // are we really allowed to show this thread/message?
  708. $approvedval = "";
  709. if(!phorum_user_access_allowed(PHORUM_USER_ALLOW_MODERATE_MESSAGES)) {
  710. $approvedval="AND {$PHORUM['message_table']}.status =".PHORUM_STATUS_APPROVED;
  711. }
  712. if($page > 0) {
  713. $start=$PHORUM["read_length"]*($page-1);
  714. $sql = "select {$PHORUM['message_table']}.* from {$PHORUM['message_table']} where $forum_id_check thread=$thread $approvedval order by message_id LIMIT $start,".$PHORUM["read_length"];
  715. } else {
  716. $sql = "select {$PHORUM['message_table']}.* from {$PHORUM['message_table']} where $forum_id_check thread=$thread $approvedval order by message_id";
  717. if(isset($PHORUM["reverse_threading"]) && $PHORUM["reverse_threading"]) $sql.=" desc";
  718. }
  719. $res = mysql_query($sql, $conn);
  720. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  721. $arr = array();
  722. while ($rec = mysql_fetch_assoc($res)){
  723. $arr[$rec["message_id"]] = $rec;
  724. // convert meta field
  725. if(empty($rec["meta"])){
  726. $arr[$rec["message_id"]]["meta"]=array();
  727. } else {
  728. $arr[$rec["message_id"]]["meta"]=unserialize($rec["meta"]);
  729. }
  730. if(empty($arr['users'])) $arr['users']=array();
  731. if($rec["user_id"]){
  732. $arr['users'][]=$rec["user_id"];
  733. }
  734. }
  735. if(count($arr) && $page != 0) {
  736. // selecting the thread-starter
  737. $sql = "select {$PHORUM['message_table']}.* from {$PHORUM['message_table']} where $forum_id_check message_id=$thread $approvedval";
  738. $res = mysql_query($sql, $conn);
  739. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  740. if(mysql_num_rows($res) > 0) {
  741. $rec = mysql_fetch_assoc($res);
  742. $arr[$rec["message_id"]] = $rec;
  743. $arr[$rec["message_id"]]["meta"]=unserialize($rec["meta"]);
  744. }
  745. }
  746. return $arr;
  747. }
  748. /**
  749. * Return the index of a message in a thread.
  750. * @param int $thread
  751. * @param int $message_id
  752. * @return int
  753. */
  754. function phorum_db_get_message_index($thread=0,$message_id=0) {
  755. $PHORUM = $GLOBALS["PHORUM"];
  756. // check for valid values
  757. if(empty($message_id) || empty($message_id)) {
  758. return 0;
  759. }
  760. settype($thread, "int");
  761. settype($message_id, "int");
  762. $approvedval="";
  763. $forum_id_check="";
  764. $conn = phorum_db_mysql_connect();
  765. if (!empty($PHORUM["forum_id"])){
  766. $forum_id_check = "(forum_id = {$PHORUM['forum_id']} OR forum_id={$PHORUM['vroot']}) AND";
  767. }
  768. if(!phorum_user_access_allowed(PHORUM_USER_ALLOW_MODERATE_MESSAGES)) {
  769. $approvedval="AND {$PHORUM['message_table']}.status =".PHORUM_STATUS_APPROVED;
  770. }
  771. $sql = "select count(*) as msg_index from {$PHORUM['message_table']} where $forum_id_check thread=$thread $approvedval AND message_id <= $message_id order by message_id";
  772. $res = mysql_query($sql, $conn);
  773. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  774. $rec = mysql_fetch_assoc($res);
  775. return $rec['msg_index'];
  776. }
  777. /**
  778. * Search the database for the supplied search criteria and returns
  779. * an array with two elements. One is the count of total messages that
  780. * matched, the second is an array of the messages from the results
  781. * based on the $start (0 base) given and the $length given.
  782. *
  783. * @param string $search
  784. * @param int $offset
  785. * @param int $length
  786. * @param string $match_type
  787. * @param int $match_date
  788. * @param string $match_forum
  789. *
  790. * @return array
  791. */
  792. function phorum_db_search($search, $offset, $length, $match_type, $match_date, $match_forum)
  793. {
  794. $PHORUM = $GLOBALS["PHORUM"];
  795. $start = $offset * $PHORUM["list_length"];
  796. $arr = array("count" => 0, "rows" => array());
  797. $conn = phorum_db_mysql_connect();
  798. // have to check what forums they can read first.
  799. $allowed_forums=phorum_user_access_list(PHORUM_USER_ALLOW_READ);
  800. // if they are not allowed to search any forums, return the emtpy $arr;
  801. if(empty($allowed_forums) || ($PHORUM['forum_id']>0 && !in_array($PHORUM['forum_id'], $allowed_forums)) ) return $arr;
  802. // Add forum 0 (for announcements) to the allowed forums.
  803. $allowed_forums[] = 0;
  804. if($PHORUM['forum_id']!=0 && $match_forum!="ALL"){
  805. $forum_where=" and forum_id={$PHORUM['forum_id']}";
  806. } else {
  807. $forum_where=" and forum_id in (".implode(",", $allowed_forums).")";
  808. }
  809. // prepare terms
  810. if($match_type=="PHRASE"){
  811. $terms = array('"'.$search.'"');
  812. } elseif($match_type=="AUTHOR"){
  813. $terms = mysql_escape_string($search);
  814. } else {
  815. $quote_terms=array();
  816. if ( strstr( $search, '"' ) ){
  817. //first pull out all the double quoted strings (e.g. '"iMac DV" or -"iMac DV"')
  818. preg_match_all( '/-*"(.*?)"/', $search, $match );
  819. $search = preg_replace( '/-*".*?"/', '', $search );
  820. $quote_terms = $match[0];
  821. }
  822. //finally pull out the rest words in the string
  823. $terms = preg_split( "/\s+/", $search, 0, PREG_SPLIT_NO_EMPTY );
  824. //merge them all together and return
  825. $terms = array_merge($terms, $quote_terms);
  826. }
  827. if($PHORUM["DBCONFIG"]["mysql_use_ft"]){
  828. if($match_type=="AUTHOR"){
  829. $id_table=$PHORUM['search_table']."_auth_".md5(microtime());
  830. $sql = "create temporary table $id_table (key(message_id)) ENGINE=HEAP select message_id from {$PHORUM['message_table']} where author='$terms' $forum_where";
  831. if($match_date>0){
  832. $ts=time()-86400*$match_date;
  833. $sql.=" and datestamp>=$ts";
  834. }
  835. $res = mysql_query($sql, $conn);
  836. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  837. } else {
  838. if(count($terms)){
  839. $use_key="";
  840. $extra_where="";
  841. /* using this code on larger forums has shown to make the search faster.
  842. However, on smaller forums, it does not appear to help and in fact
  843. appears to slow down searches.
  844. if($match_date){
  845. $min_time=time()-86400*$match_date;
  846. $sql="select min(message_id) as min_id from {$PHORUM['message_table']} where datestamp>=$min_time";
  847. $res=mysql_query($sql, $conn);
  848. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  849. $min_id=mysql_result($res, 0, "min_id");
  850. $use_key=" use key (primary)";
  851. $extra_where="and message_id>=$min_id";
  852. }
  853. */
  854. $id_table=$PHORUM['search_table']."_ft_".md5(microtime());
  855. if($PHORUM["DBCONFIG"]["mysql_use_ft"]){
  856. if($match_type=="ALL" && count($terms)>1){
  857. $against="+".mysql_escape_string(implode(" +", $terms));
  858. } else {
  859. $against=mysql_escape_string(implode(" ", $terms));
  860. }
  861. $clause="MATCH (search_text) AGAINST ('$against' IN BOOLEAN MODE)";
  862. } else {
  863. if($match_type=="ALL"){
  864. $conj="and";
  865. } else {
  866. $conj="or";
  867. }
  868. // quote strings correctly
  869. foreach ($terms as $id => $term) {
  870. $terms[$id] = mysql_escape_string($term);
  871. }
  872. $clause = "( search_text like '%".implode("%' $conj search_text like '%", $terms)."%' )";
  873. }
  874. $sql = "create temporary table $id_table (key(message_id)) ENGINE=HEAP select message_id from {$PHORUM['search_table']} $use_key where $clause $extra_where";
  875. $res = mysql_unbuffered_query($sql, $conn);
  876. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  877. }
  878. }
  879. if(isset($id_table)){
  880. // create a temporary table of the messages we want
  881. $table=$PHORUM['search_table']."_".md5(microtime());
  882. $sql="create temporary table $table (key (forum_id, status, datestamp)) ENGINE=HEAP select {$PHORUM['message_table']}.message_id, {$PHORUM['message_table']}.datestamp, status, forum_id from {$PHORUM['message_table']} inner join $id_table using (message_id) where status=".PHORUM_STATUS_APPROVED." $forum_where";
  883. if($match_date>0){
  884. $ts=time()-86400*$match_date;
  885. $sql.=" and datestamp>=$ts";
  886. }
  887. $res=mysql_query($sql, $conn);
  888. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  889. $sql="select count(*) as count from $table";
  890. $res = mysql_query($sql, $conn);
  891. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  892. $total_count=mysql_result($res, 0, 0);
  893. $sql="select message_id from $table order by datestamp desc limit $start, $length";
  894. $res = mysql_unbuffered_query($sql, $conn);
  895. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  896. $idstring="";
  897. while ($rec = mysql_fetch_row($res)){
  898. $idstring.="$rec[0],";
  899. }
  900. $idstring=substr($idstring, 0, -1);
  901. }
  902. } else { // not using full text matching
  903. if($match_type=="AUTHOR"){
  904. $sql_core = "from {$PHORUM['message_table']} where author='$terms' $forum_where";
  905. if($match_date>0){
  906. $ts=time()-86400*$match_date;
  907. $sql_core.=" and datestamp>=$ts";
  908. }
  909. $sql = "select count(*) $sql_core";
  910. $res = mysql_query($sql, $conn);
  911. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  912. $total_count=mysql_result($res, 0, 0);
  913. $sql = "select message_id $sql_core order by datestamp desc limit $start, $length";
  914. $res = mysql_unbuffered_query($sql, $conn);
  915. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  916. $idstring="";
  917. while ($rec = mysql_fetch_row($res)){
  918. $idstring.="$rec[0],";
  919. }
  920. $idstring=substr($idstring, 0, -1);
  921. } else {
  922. if(count($terms)){
  923. $id_table=$PHORUM['search_table']."_ft_".md5(microtime());
  924. if($match_type=="ALL"){
  925. $conj="and";
  926. } else {
  927. $conj="or";
  928. }
  929. // quote strings correctly
  930. foreach ($terms as $id => $term) {
  931. $terms[$id] = mysql_escape_string($term);
  932. }
  933. $clause = "( concat(author, ' | ', subject, ' | ', body) like '%".implode("%' $conj concat(author, ' | ', subject, ' | ', body) like '%", $terms)."%' )";
  934. $sql = "select count(*) from {$PHORUM['message_table']} where status=".PHORUM_STATUS_APPROVED." and $clause $forum_where";
  935. $res = mysql_query($sql, $conn);
  936. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  937. $total_count=mysql_result($res, 0, 0);
  938. $sql = "select message_id from {$PHORUM['message_table']} where status=".PHORUM_STATUS_APPROVED." and $clause $forum_where order by datestamp desc limit $start, $length";
  939. $res = mysql_unbuffered_query($sql, $conn);
  940. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  941. $idstring="";
  942. while ($rec = mysql_fetch_row($res)){
  943. $idstring.="$rec[0],";
  944. }
  945. $idstring=substr($idstring, 0, -1);
  946. }
  947. }
  948. }
  949. if($idstring){
  950. $sql="select * from {$PHORUM['message_table']} where message_id in ($idstring) order by datestamp desc";
  951. $res = mysql_unbuffered_query($sql, $conn);
  952. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  953. $rows = array();
  954. while ($rec = mysql_fetch_assoc($res)){
  955. $rows[$rec["message_id"]] = $rec;
  956. }
  957. $arr = array("count" => $total_count, "rows" => $rows);
  958. }
  959. return $arr;
  960. }
  961. /**
  962. * Return the closest thread that is greater than $key.
  963. * @param int $key
  964. * @return mixed
  965. */
  966. function phorum_db_get_newer_thread($key){
  967. $PHORUM = $GLOBALS["PHORUM"];
  968. settype($key, "int");
  969. $conn = phorum_db_mysql_connect();
  970. $keyfield = ($PHORUM["float_to_top"]) ? "modifystamp" : "thread";
  971. // are we really allowed to show this thread/message?
  972. $approvedval = "";
  973. if(!phorum_user_access_allowed(PHORUM_USER_ALLOW_MODERATE_MESSAGES) && $PHORUM["moderation"] == PHORUM_MODERATE_ON) {
  974. $approvedval="AND {$PHORUM['message_table']}.status =".PHORUM_STATUS_APPROVED;
  975. } else {
  976. $approvedval="AND {$PHORUM['message_table']}.parent_id = 0";
  977. }
  978. $sql = "select thread from {$PHORUM['message_table']} where forum_id={$PHORUM['forum_id']} $approvedval and $keyfield>$key order by $keyfield limit 1";
  979. $res = mysql_query($sql, $conn);
  980. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  981. return (mysql_num_rows($res)) ? mysql_result($res, 0, "thread") : 0;
  982. }
  983. /**
  984. * Returns the closest thread that is less than $key.
  985. * @param int $key
  986. * @return mixed
  987. */
  988. function phorum_db_get_older_thread($key){
  989. $PHORUM = $GLOBALS["PHORUM"];
  990. settype($key, "int");
  991. $conn = phorum_db_mysql_connect();
  992. $keyfield = ($PHORUM["float_to_top"]) ? "modifystamp" : "thread";
  993. // are we really allowed to show this thread/message?
  994. $approvedval = "";
  995. if(!phorum_user_access_allowed(PHORUM_USER_ALLOW_MODERATE_MESSAGES) && $PHORUM["moderation"] == PHORUM_MODERATE_ON) {
  996. $approvedval="AND {$PHORUM['message_table']}.status=".PHORUM_STATUS_APPROVED;
  997. } else {
  998. $approvedval="AND {$PHORUM['message_table']}.parent_id = 0";
  999. }
  1000. $sql = "select thread from {$PHORUM['message_table']} where forum_id={$PHORUM['forum_id']} $approvedval and $keyfield<$key order by $keyfield desc limit 1";
  1001. $res = mysql_query($sql, $conn);
  1002. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1003. return (mysql_num_rows($res)) ? mysql_result($res, 0, "thread") : 0;
  1004. }
  1005. /**
  1006. * Load the settings in the global $PHORUM['SETTINGS'] variable.
  1007. *
  1008. * @return void
  1009. */
  1010. function phorum_db_load_settings(){
  1011. global $PHORUM;
  1012. $conn = phorum_db_mysql_connect();
  1013. $sql = "select * from {$PHORUM['settings_table']}";
  1014. $res = mysql_query($sql, $conn);
  1015. if(!$res && !defined("PHORUM_ADMIN")){
  1016. if (mysql_errno($conn)==1146){
  1017. // settings table does not exist
  1018. return;
  1019. } elseif(($err = mysql_error())){
  1020. phorum_db_mysql_error("$err: $sql");
  1021. }
  1022. }
  1023. if (empty($err) && $res){
  1024. while ($rec = mysql_fetch_assoc($res)){
  1025. // only load the default forum options in the admin
  1026. if($rec["name"]=="default_forum_options" && !defined("PHORUM_ADMIN")) continue;
  1027. if ($rec["type"] == "V"){
  1028. if ($rec["data"] == 'true'){
  1029. $val = true;
  1030. }elseif ($rec["data"] == 'false'){
  1031. $val = false;
  1032. }elseif (is_numeric($rec["data"])){
  1033. $val = $rec["data"];
  1034. }else{
  1035. $val = "$rec[data]";
  1036. }
  1037. }else{
  1038. $val = unserialize($rec["data"]);
  1039. }
  1040. $PHORUM[$rec['name']]=$val;
  1041. $PHORUM['SETTINGS'][$rec['name']]=$val;
  1042. }
  1043. }
  1044. }
  1045. /**
  1046. * Update Phorum settings.
  1047. *
  1048. * @param array $settings
  1049. *
  1050. * @return boolean
  1051. */
  1052. function phorum_db_update_settings($settings){
  1053. global $PHORUM;
  1054. if (count($settings) > 0){
  1055. $conn = phorum_db_mysql_connect();
  1056. foreach($settings as $field => $value){
  1057. if (is_numeric($value)){
  1058. $type = 'V';
  1059. }elseif (is_string($value)){
  1060. $value = mysql_escape_string($value);
  1061. $type = 'V';
  1062. }else{
  1063. $value = mysql_escape_string(serialize($value));
  1064. $type = 'S';
  1065. }
  1066. $sql = "replace into {$PHORUM['settings_table']} set data='$value', type='$type', name='$field'";
  1067. $res = mysql_query($sql, $conn);
  1068. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1069. }
  1070. return ($res > 0) ? true : false;
  1071. }else{
  1072. trigger_error("\$settings cannot be empty in phorum_db_update_settings()", E_USER_ERROR);
  1073. }
  1074. }
  1075. /**
  1076. * Get all forums for a flat/collapsed display and return the data in
  1077. * an array.
  1078. *
  1079. * @param mixed $forum_ids
  1080. * Can be an array of forum IDs or an int for one forum ID.
  1081. * @param int $parent_id
  1082. * @param unknown $vroot
  1083. * @param unknown $inherit_id
  1084. *
  1085. * @return array
  1086. */
  1087. function phorum_db_get_forums($forum_ids = 0, $parent_id = -1, $vroot = null, $inherit_id = null){
  1088. $PHORUM = $GLOBALS["PHORUM"];
  1089. settype($parent_id, "int");
  1090. $conn = phorum_db_mysql_connect();
  1091. if (is_array($forum_ids)) {
  1092. $int_ids = array();
  1093. foreach ($forum_ids as $id) {
  1094. settype($id, "int");
  1095. $int_ids[] = $id;
  1096. }
  1097. $forum_ids = implode(",", $int_ids);
  1098. } else {
  1099. settype($forum_ids, "int");
  1100. }
  1101. $sql = "select * from {$PHORUM['forums_table']} ";
  1102. if ($forum_ids){
  1103. $sql .= " where forum_id in ($forum_ids)";
  1104. } elseif ($inherit_id !== null) {
  1105. $sql .= " where inherit_id = $inherit_id";
  1106. if(!defined("PHORUM_ADMIN")) $sql.=" and active=1";
  1107. } elseif ($parent_id >= 0) {
  1108. $sql .= " where parent_id = $parent_id";
  1109. if(!defined("PHORUM_ADMIN")) $sql.=" and active=1";
  1110. } elseif($vroot !== null) {
  1111. $sql .= " where vroot = $vroot";
  1112. } else {
  1113. $sql .= " where forum_id <> 0";
  1114. }
  1115. $sql .= " order by display_order ASC, name";
  1116. $res = mysql_query($sql, $conn);
  1117. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1118. $forums = array();
  1119. while ($row = mysql_fetch_assoc($res)){
  1120. $forums[$row["forum_id"]] = $row;
  1121. }
  1122. return $forums;
  1123. }
  1124. /**
  1125. * Update the forums stats.
  1126. *
  1127. * @param boolean $refresh
  1128. * If true, it pulls the numbers from the table.
  1129. * @param int $msg_count_change
  1130. * @param int $timestamp
  1131. * @param int $thread_count_change
  1132. * @param int $sticky_count_change
  1133. *
  1134. * @return void
  1135. */
  1136. function phorum_db_update_forum_stats($refresh=false, $msg_count_change=0, $timestamp=0, $thread_count_change=0, $sticky_count_change=0)
  1137. {
  1138. $PHORUM = $GLOBALS["PHORUM"];
  1139. $conn = phorum_db_mysql_connect();
  1140. // always refresh on small forums
  1141. if (isset($PHORUM["message_count"]) && $PHORUM["message_count"]<1000) {
  1142. $refresh=true;
  1143. }
  1144. if($refresh || empty($msg_count_change)){
  1145. $sql = "select count(*) as message_count from {$PHORUM['message_table']} where forum_id={$PHORUM['forum_id']} and status=".PHORUM_STATUS_APPROVED;
  1146. $res = mysql_query($sql, $conn);
  1147. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1148. $message_count = (int)mysql_result($res, 0, "message_count");
  1149. } else {
  1150. $message_count="message_count+$msg_count_change";
  1151. }
  1152. if($refresh || empty($timestamp)){
  1153. $sql = "select max(modifystamp) as last_post_time from {$PHORUM['message_table']} where status=".PHORUM_STATUS_APPROVED." and forum_id={$PHORUM['forum_id']}";
  1154. $res = mysql_query($sql, $conn);
  1155. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1156. $last_post_time = (int)mysql_result($res, 0, "last_post_time");
  1157. } else {
  1158. $last_post_time = $timestamp;
  1159. }
  1160. if($refresh || empty($thread_count_change)){
  1161. $sql = "select count(*) as thread_count from {$PHORUM['message_table']} where forum_id={$PHORUM['forum_id']} and parent_id=0 and status=".PHORUM_STATUS_APPROVED;
  1162. $res = mysql_query($sql, $conn);
  1163. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1164. $thread_count = (int)mysql_result($res, 0, "thread_count");
  1165. } else {
  1166. $thread_count="thread_count+$thread_count_change";
  1167. }
  1168. if($refresh || empty($sticky_count_change)){
  1169. $sql = "select count(*) as sticky_count from {$PHORUM['message_table']} where forum_id={$PHORUM['forum_id']} and sort=".PHORUM_SORT_STICKY." and parent_id=0 and status=".PHORUM_STATUS_APPROVED;
  1170. $res = mysql_query($sql, $conn);
  1171. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1172. $sticky_count = (int)mysql_result($res, 0, "sticky_count");
  1173. } else {
  1174. $sticky_count="sticky_count+$sticky_count_change";
  1175. }
  1176. $sql = "update {$PHORUM['forums_table']} set thread_count=$thread_count, message_count=$message_count, sticky_count=$sticky_count, last_post_time=$last_post_time where forum_id={$PHORUM['forum_id']}";
  1177. mysql_query($sql, $conn);
  1178. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1179. }
  1180. /**
  1181. * Move a thread to the given forum.
  1182. *
  1183. * @param int $thread_id
  1184. * @param int $toforum
  1185. *
  1186. * @return void
  1187. */
  1188. function phorum_db_move_thread($thread_id, $toforum)
  1189. {
  1190. $PHORUM = $GLOBALS["PHORUM"];
  1191. settype($thread_id, "int");
  1192. settype($toforum, "int");
  1193. if($toforum > 0 && $thread_id > 0){
  1194. $conn = phorum_db_mysql_connect();
  1195. // retrieving the messages for the newflags and search updates below
  1196. $thread_messages=phorum_db_get_messages($thread_id);
  1197. // just changing the forum-id, simple isn't it?
  1198. $sql = "UPDATE {$PHORUM['message_table']} SET forum_id=$toforum where thread=$thread_id";
  1199. $res = mysql_query($sql, $conn);
  1200. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1201. // we need to update the number of posts in the current forum
  1202. phorum_db_update_forum_stats(true);
  1203. // and of the new forum
  1204. $old_id=$GLOBALS["PHORUM"]["forum_id"];
  1205. $GLOBALS["PHORUM"]["forum_id"]=$toforum;
  1206. phorum_db_update_forum_stats(true);
  1207. $GLOBALS["PHORUM"]["forum_id"]=$old_id;
  1208. // move the new-flags and the search records for this thread
  1209. // to the new forum too
  1210. unset($thread_messages['users']);
  1211. $new_newflags=phorum_db_newflag_get_flags($toforum);
  1212. $message_ids = array();
  1213. $delete_ids = array();
  1214. $search_ids = array();
  1215. foreach($thread_messages as $mid => $data) {
  1216. // gather information for updating the newflags
  1217. if($mid > $new_newflags['min_id']) { // only using it if its higher than min_id
  1218. $message_ids[]=$mid;
  1219. } else { // newflags to delete
  1220. $delete_ids[]=$mid;
  1221. }
  1222. // gather the information for updating the search table
  1223. $search_ids[] = $mid;
  1224. }
  1225. if(count($message_ids)) { // we only go in if there are messages ... otherwise an error occured
  1226. $ids_str=implode(",",$message_ids);
  1227. // then doing the update to newflags
  1228. $sql="UPDATE IGNORE {$PHORUM['user_newflags_table']} SET forum_id = $toforum where message_id IN($ids_str)";
  1229. $res = mysql_query($sql, $conn);
  1230. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1231. // then doing the update to subscriptions
  1232. $sql="UPDATE {$PHORUM['subscribers_table']} SET forum_id = $toforum where thread IN($ids_str)";
  1233. $res = mysql_query($sql, $conn);
  1234. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1235. }
  1236. if(count($delete_ids)) {
  1237. $ids_str=implode(",",$delete_ids);
  1238. // then doing the delete
  1239. $sql="DELETE FROM {$PHORUM['user_newflags_table']} where message_id IN($ids_str)";
  1240. mysql_query($sql, $conn);
  1241. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1242. }
  1243. if (count($search_ids)) {
  1244. $ids_str = implode(",",$search_ids);
  1245. // then doing the search table update
  1246. $sql = "UPDATE {$PHORUM['search_table']} set forum_id = $toforum where message_id in ($ids_str)";
  1247. mysql_query($sql, $conn);
  1248. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1249. }
  1250. }
  1251. }
  1252. /**
  1253. * Close the given thread.
  1254. * @param int $thread_id
  1255. * @return void
  1256. */
  1257. function phorum_db_close_thread($thread_id){
  1258. $PHORUM = $GLOBALS["PHORUM"];
  1259. settype($thread_id, "int");
  1260. if($thread_id > 0){
  1261. $conn = phorum_db_mysql_connect();
  1262. $sql = "UPDATE {$PHORUM['message_table']} SET closed=1 where thread=$thread_id";
  1263. $res = mysql_query($sql, $conn);
  1264. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1265. }
  1266. }
  1267. /**
  1268. * (Re)opens the given thread.
  1269. *
  1270. * @param int $thread_id
  1271. *
  1272. * @return void
  1273. */
  1274. function phorum_db_reopen_thread($thread_id){
  1275. $PHORUM = $GLOBALS["PHORUM"];
  1276. settype($thread_id, "int");
  1277. if($thread_id > 0){
  1278. $conn = phorum_db_mysql_connect();
  1279. $sql = "UPDATE {$PHORUM['message_table']} SET closed=0 where thread=$thread_id";
  1280. $res = mysql_query($sql, $conn);
  1281. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1282. }
  1283. }
  1284. /**
  1285. * Create a forum.
  1286. *
  1287. * @param array $forum
  1288. * <pre>
  1289. * Example:
  1290. * "name"=>'Test Forum',
  1291. * "active"=>1,
  1292. * "description"=>'This is a test forum.',
  1293. * "template"=>'default',
  1294. * "folder_flag"=>0,
  1295. * "parent_id"=>0,
  1296. * "list_length_flat"=>30,
  1297. * "list_length_threaded"=>15,
  1298. * "read_length"=>20,
  1299. * "moderation"=>0,
  1300. * "threaded_list"=>0,
  1301. * "threaded_read"=>0,
  1302. * "float_to_top"=>1,
  1303. * "display_ip_address"=>0,
  1304. * "allow_email_notify"=>1,
  1305. * "language"=>'english',
  1306. * "email_moderators"=>0,
  1307. * "display_order"=>0,
  1308. * "edit_post"=>1,
  1309. * "pub_perms" => 1,
  1310. * "reg_perms" => 15
  1311. * </pre>
  1312. * @return int
  1313. * Return the forum ID on success, zero on failure.
  1314. */
  1315. function phorum_db_add_forum($forum)
  1316. {
  1317. $PHORUM = $GLOBALS["PHORUM"];
  1318. $conn = phorum_db_mysql_connect();
  1319. foreach($forum as $key => $value){
  1320. if (is_numeric($value)){
  1321. $value = (int)$value;
  1322. $fields[] = "$key=$value";
  1323. } elseif($value=="NULL") {
  1324. $fields[] = "$key=$value";
  1325. }else{
  1326. $value = mysql_escape_string($value);
  1327. $fields[] = "$key='$value'";
  1328. }
  1329. }
  1330. $sql = "insert into {$PHORUM['forums_table']} set " . implode(", ", $fields);
  1331. $res = mysql_query($sql, $conn);
  1332. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1333. $forum_id = 0;
  1334. if ($res){
  1335. $forum_id = mysql_insert_id($conn);
  1336. }
  1337. return $forum_id;
  1338. }
  1339. /**
  1340. * Delete a forum and all of its messages.
  1341. * @param int $forum_id
  1342. * @return void
  1343. */
  1344. function phorum_db_drop_forum($forum_id)
  1345. {
  1346. $PHORUM = $GLOBALS["PHORUM"];
  1347. settype($forum_id, "int");
  1348. $conn = phorum_db_mysql_connect();
  1349. $tables = array (
  1350. $PHORUM['message_table'],
  1351. $PHORUM['user_permissions_table'],
  1352. $PHORUM['user_newflags_table'],
  1353. $PHORUM['subscribers_table'],
  1354. $PHORUM['forum_group_xref_table'],
  1355. $PHORUM['forums_table'],
  1356. $PHORUM['banlist_table'],
  1357. $PHORUM['search_table']
  1358. );
  1359. foreach($tables as $table){
  1360. $sql = "delete from $table where forum_id=$forum_id";
  1361. $res = mysql_query($sql, $conn);
  1362. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1363. }
  1364. $sql = "select file_id from {$PHORUM['files_table']} left join {$PHORUM['message_table']} using (message_id) where {$PHORUM['files_table']}.message_id > 0 AND link='" . PHORUM_LINK_MESSAGE . "' AND {$PHORUM['message_table']}.message_id is NULL";
  1365. $res = mysql_query($sql, $conn);
  1366. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1367. while($rec=mysql_fetch_assoc($res)){
  1368. $files[]=$rec["file_id"];
  1369. }
  1370. if(isset($files)){
  1371. $sql = "delete from {$PHORUM['files_table']} where file_id in (".implode(",", $files).")";
  1372. $res = mysql_query($sql, $conn);
  1373. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1374. }
  1375. }
  1376. /**
  1377. * Remove a folder from the forums and change the parent of its children.
  1378. * @param int $forum_id
  1379. * @return void
  1380. */
  1381. function phorum_db_drop_folder($forum_id)
  1382. {
  1383. $PHORUM = $GLOBALS["PHORUM"];
  1384. settype($forum_id, "int");
  1385. $conn = phorum_db_mysql_connect();
  1386. $sql = "select parent_id from {$PHORUM['forums_table']} where forum_id=$forum_id";
  1387. $res = mysql_query($sql, $conn);
  1388. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1389. $new_parent_id = mysql_result($res, 0, "parent_id");
  1390. $sql = "update {$PHORUM['forums_table']} set parent_id=$new_parent_id where parent_id=$forum_id";
  1391. $res = mysql_query($sql, $conn);
  1392. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1393. $sql = "delete from {$PHORUM['forums_table']} where forum_id=$forum_id";
  1394. $res = mysql_query($sql, $conn);
  1395. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1396. }
  1397. /**
  1398. * Update a forum.
  1399. *
  1400. * @param array $forum
  1401. * See phorum_db_add_forum() for a list of possible values.
  1402. *
  1403. * @return boolean
  1404. */
  1405. function phorum_db_update_forum($forum){
  1406. $PHORUM = $GLOBALS["PHORUM"];
  1407. $res = 0;
  1408. if (!empty($forum["forum_id"])){
  1409. // this way we can also update multiple forums at once
  1410. if(is_array($forum["forum_id"])) {
  1411. $forumwhere="forum_id IN (".implode(",",$forum["forum_id"]).")";
  1412. } else {
  1413. $forumwhere="forum_id=".$forum["forum_id"];
  1414. }
  1415. unset($forum["forum_id"]);
  1416. $conn = phorum_db_mysql_connect();
  1417. foreach($forum as $key => $value){
  1418. if (is_numeric($value)){
  1419. $value = (int)$value;
  1420. $fields[] = "$key=$value";
  1421. } elseif($value=="NULL") {
  1422. $fields[] = "$key=$value";
  1423. } else {
  1424. $value = mysql_escape_string($value);
  1425. $fields[] = "$key='$value'";
  1426. }
  1427. }
  1428. $sql = "update {$PHORUM['forums_table']} set " . implode(", ", $fields) . " where $forumwhere";
  1429. $res = mysql_query($sql, $conn);
  1430. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1431. }else{
  1432. trigger_error("\$forum[forum_id] cannot be empty in phorum_update_forum()", E_USER_ERROR);
  1433. }
  1434. return $res;
  1435. }
  1436. /**
  1437. * Get groups that match the given group ID.
  1438. * @param int $group_id
  1439. * @return array
  1440. */
  1441. function phorum_db_get_groups($group_id=0)
  1442. {
  1443. $PHORUM = $GLOBALS["PHORUM"];
  1444. $conn = phorum_db_mysql_connect();
  1445. settype($group_id, "integer");
  1446. $sql="select * from {$PHORUM['groups_table']}";
  1447. if($group_id!=0) $sql.=" where group_id=$group_id";
  1448. $res = mysql_query($sql, $conn);
  1449. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1450. $groups=array();
  1451. while($rec=mysql_fetch_assoc($res)){
  1452. $groups[$rec["group_id"]]=$rec;
  1453. $groups[$rec["group_id"]]["permissions"]=array();
  1454. }
  1455. $sql="select * from {$PHORUM['forum_group_xref_table']}";
  1456. if($group_id!=0) $sql.=" where group_id=$group_id";
  1457. $res = mysql_query($sql, $conn);
  1458. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1459. while($rec=mysql_fetch_assoc($res)){
  1460. $groups[$rec["group_id"]]["permissions"][$rec["forum_id"]]=$rec["permission"];
  1461. }
  1462. return $groups;
  1463. }
  1464. /**
  1465. * Get the members of a group.
  1466. *
  1467. * @param int group_id - can be an integer (single group), or an array of groups
  1468. * @param int status - a specific status to look for, defaults to all
  1469. *
  1470. * @return array - users (key is userid, value is group membership status)
  1471. */
  1472. function phorum_db_get_group_members($group_id, $status = PHORUM_USER_GROUP_REMOVE)
  1473. {
  1474. $PHORUM = $GLOBALS["PHORUM"];
  1475. $conn = phorum_db_mysql_connect();
  1476. if(is_array($group_id)){
  1477. $group_id=implode(",", $group_id);
  1478. } else {
  1479. settype($group_id, "int");
  1480. }
  1481. // this join is only here so that the list of users comes out sorted
  1482. // if phorum_db_user_get() sorts results itself, this join can go away
  1483. $sql="select {$PHORUM['user_group_xref_table']}.user_id, {$PHORUM['user_group_xref_table']}.status from {$PHORUM['user_table']}, {$PHORUM['user_group_xref_table']} where {$PHORUM['user_table']}.user_id = {$PHORUM['user_group_xref_table']}.user_id and group_id in ($group_id)";
  1484. if ($status != PHORUM_USER_GROUP_REMOVE) $sql.=" and {$PHORUM['user_group_xref_table']}.status = $status";
  1485. $sql .=" order by username asc";
  1486. $res = mysql_query($sql, $conn);
  1487. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1488. $users=array();
  1489. while($rec=mysql_fetch_assoc($res)){
  1490. $users[$rec["user_id"]]=$rec["status"];
  1491. }
  1492. return $users;
  1493. }
  1494. /**
  1495. * Update a group.
  1496. *
  1497. * @param array $group
  1498. *
  1499. * @return boolean
  1500. */
  1501. function phorum_db_save_group($group)
  1502. {
  1503. $PHORUM = $GLOBALS["PHORUM"];
  1504. $conn = phorum_db_mysql_connect();
  1505. $ret=false;
  1506. if(isset($group["name"])){
  1507. $sql="update {$PHORUM['groups_table']} set name='{$group['name']}', open={$group['open']} where group_id={$group['group_id']}";
  1508. $res=mysql_query($sql, $conn);
  1509. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1510. }
  1511. if(!$err){
  1512. if(isset($group["permissions"])){
  1513. $sql="delete from {$PHORUM['forum_group_xref_table']} where group_id={$group['group_id']}";
  1514. $res=mysql_query($sql, $conn);
  1515. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1516. foreach($group["permissions"] as $forum_id=>$permission){
  1517. $sql="insert into {$PHORUM['forum_group_xref_table']} set group_id={$group['group_id']}, permission=$permission, forum_id=$forum_id";
  1518. $res=mysql_query($sql, $conn);
  1519. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1520. if(!$res) break;
  1521. }
  1522. }
  1523. }
  1524. if($res>0) $ret=true;
  1525. return $ret;
  1526. }
  1527. /**
  1528. * Delete a group.
  1529. *
  1530. * @param int $group_id
  1531. * @return void
  1532. */
  1533. function phorum_db_delete_group($group_id)
  1534. {
  1535. $PHORUM = $GLOBALS["PHORUM"];
  1536. $conn = phorum_db_mysql_connect();
  1537. settype($group_id, "int");
  1538. $sql = "delete from {$PHORUM['groups_table']} where group_id = $group_id";
  1539. $res = mysql_query($sql, $conn);
  1540. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1541. // delete things associated with groups
  1542. $sql = "delete from {$PHORUM['user_group_xref_table']} where group_id = $group_id";
  1543. $res = mysql_query($sql, $conn);
  1544. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1545. $sql = "delete from {$PHORUM['forum_group_xref_table']} where group_id = $group_id";
  1546. $res = mysql_query($sql, $conn);
  1547. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1548. }
  1549. /**
  1550. * Add a group.
  1551. *
  1552. * @param string $group_name
  1553. * @param int $group_id
  1554. *
  1555. * @return int
  1556. */
  1557. function phorum_db_add_group($group_name,$group_id=0)
  1558. {
  1559. $PHORUM = $GLOBALS["PHORUM"];
  1560. $conn = phorum_db_mysql_connect();
  1561. settype($group_id, "int");
  1562. if($group_id > 0) { // only used in conversion
  1563. $sql="insert into {$PHORUM['groups_table']} (group_id,name) values ($group_id,'$group_name')";
  1564. } else {
  1565. $sql="insert into {$PHORUM['groups_table']} (name) values ('$group_name')";
  1566. }
  1567. $res = mysql_query($sql, $conn);
  1568. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1569. $group_id = 0;
  1570. if ($res) {
  1571. $group_id = mysql_insert_id($conn);
  1572. }
  1573. return $group_id;
  1574. }
  1575. /**
  1576. * Get all moderators for a particular forum.
  1577. *
  1578. * @param int $forum_id
  1579. * @param boolean $ignore_user_perms
  1580. * @param boolean $for_email
  1581. *
  1582. * @return array
  1583. */
  1584. function phorum_db_user_get_moderators($forum_id,$ignore_user_perms=false,$for_email=false) {
  1585. $PHORUM = $GLOBALS["PHORUM"];
  1586. $userinfo=array();
  1587. $conn = phorum_db_mysql_connect();
  1588. settype($forum_id, "int");
  1589. if(!$ignore_user_perms) { // sometimes we just don't need them
  1590. if(!$PHORUM['email_ignore_admin']) {
  1591. $admincheck=" OR user.admin=1";
  1592. } else {
  1593. $admincheck="";
  1594. }
  1595. $sql="SELECT DISTINCT user.user_id, user.email, user.moderation_email FROM {$PHORUM['user_table']} as user LEFT JOIN {$PHORUM['user_permissions_table']} as perm ON perm.user_id=user.user_id WHERE (perm.permission >= ".PHORUM_USER_ALLOW_MODERATE_MESSAGES." AND (perm.permission & ".PHORUM_USER_ALLOW_MODERATE_MESSAGES." > 0) AND perm.forum_id=$forum_id)$admincheck";
  1596. $res = mysql_query($sql, $conn);
  1597. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1598. while ($row = mysql_fetch_row($res)){
  1599. if(!$for_email || $row[2] == 1)
  1600. $userinfo[$row[0]]=$row[1];
  1601. }
  1602. }
  1603. // get users who belong to groups that have moderator access
  1604. $sql = "SELECT DISTINCT user.user_id, user.email, user.moderation_email FROM {$PHORUM['user_table']} AS user, {$PHORUM['groups_table']} AS groups, {$PHORUM['user_group_xref_table']} AS usergroup, {$PHORUM['forum_group_xref_table']} AS forumgroup WHERE user.user_id = usergroup.user_id AND usergroup.group_id = groups.group_id AND groups.group_id = forumgroup.group_id AND forum_id = $forum_id AND permission & ".PHORUM_USER_ALLOW_MODERATE_MESSAGES." > 0 AND usergroup.status >= ".PHORUM_USER_GROUP_APPROVED;
  1605. $res = mysql_query($sql, $conn);
  1606. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1607. while ($row = mysql_fetch_row($res)){
  1608. if(!$for_email || $row[2] == 1)
  1609. $userinfo[$row[0]]=$row[1];
  1610. }
  1611. return $userinfo;
  1612. }
  1613. /**
  1614. * Get a user.
  1615. *
  1616. * @param int $user_id
  1617. * @param boolean $detailed
  1618. *
  1619. * @return array
  1620. */
  1621. function phorum_db_user_get($user_id, $detailed)
  1622. {
  1623. $PHORUM = $GLOBALS["PHORUM"];
  1624. $conn = phorum_db_mysql_connect();
  1625. if(is_array($user_id)){
  1626. $user_ids=implode(",", $user_id);
  1627. } else {
  1628. $user_ids=(int)$user_id;
  1629. }
  1630. $users = array();
  1631. $sql = "select * from {$PHORUM['user_table']} where user_id in ($user_ids)";
  1632. $res = mysql_query($sql, $conn);
  1633. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1634. if (mysql_num_rows($res)){
  1635. while($rec=mysql_fetch_assoc($res)){
  1636. $users[$rec["user_id"]] = $rec;
  1637. }
  1638. if ($detailed){
  1639. // get the users' permissions
  1640. $sql = "select * from {$PHORUM['user_permissions_table']} where user_id in ($user_ids)";
  1641. $res = mysql_query($sql, $conn);
  1642. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1643. while ($row = mysql_fetch_assoc($res)){
  1644. $users[$row["user_id"]]["forum_permissions"][$row["forum_id"]] = $row["permission"];
  1645. }
  1646. // get the users' groups and forum permissions through those groups
  1647. $sql = "select user_id, {$PHORUM['user_group_xref_table']}.group_id, forum_id, permission from {$PHORUM['user_group_xref_table']} left join {$PHORUM['forum_group_xref_table']} using (group_id) where user_id in ($user_ids) AND {$PHORUM['user_group_xref_table']}.status >= ".PHORUM_USER_GROUP_APPROVED;
  1648. $res = mysql_query($sql, $conn);
  1649. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1650. while ($row = mysql_fetch_assoc($res)){
  1651. $users[$row["user_id"]]["groups"][$row["group_id"]] = $row["group_id"];
  1652. if(!empty($row["forum_id"])){
  1653. if(!isset($users[$row["user_id"]]["group_permissions"][$row["forum_id"]])) {
  1654. $users[$row["user_id"]]["group_permissions"][$row["forum_id"]] = 0;
  1655. }
  1656. $users[$row["user_id"]]["group_permissions"][$row["forum_id"]] = $users[$row["user_id"]]["group_permissions"][$row["forum_id"]] | $row["permission"];
  1657. }
  1658. }
  1659. }
  1660. $sql = "select * from {$PHORUM['user_custom_fields_table']} where user_id in ($user_ids)";
  1661. $res = mysql_query($sql, $conn);
  1662. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1663. while ($row = mysql_fetch_assoc($res)){
  1664. if(isset($PHORUM["PROFILE_FIELDS"][$row['type']])) {
  1665. if($PHORUM["PROFILE_FIELDS"][$row['type']]['html_disabled']) {
  1666. $users[$row["user_id"]][$PHORUM["PROFILE_FIELDS"][$row['type']]['name']] = htmlspecialchars($row["data"]);
  1667. } else { // not html-disabled
  1668. if(substr($row["data"],0,6) == 'P_SER:') {
  1669. // P_SER (PHORUM_SERIALIZED) is our marker telling this field is serialized
  1670. $users[$row["user_id"]][$PHORUM["PROFILE_FIELDS"][$row['type']]['name']] = unserialize(substr($row["data"],6));
  1671. } else {
  1672. $users[$row["user_id"]][$PHORUM["PROFILE_FIELDS"][$row['type']]['name']] = $row["data"];
  1673. }
  1674. }
  1675. }
  1676. }
  1677. }
  1678. if(is_array($user_id)){
  1679. return $users;
  1680. } else {
  1681. return isset($users[$user_id]) ? $users[$user_id] : NULL;
  1682. }
  1683. }
  1684. /**
  1685. * Retrieve a couple of fields from the user-table for a couple of
  1686. * users or only one of them.
  1687. *
  1688. * @param mixed $user_id
  1689. * Can be an int or array or ints.
  1690. * @param mixed $fields
  1691. * Can be a string or an array of strings.
  1692. *
  1693. * @return array
  1694. * One or more users.
  1695. */
  1696. function phorum_db_user_get_fields($user_id, $fields)
  1697. {
  1698. $PHORUM = $GLOBALS["PHORUM"];
  1699. $conn = phorum_db_mysql_connect();
  1700. // input could be either array or string
  1701. if(is_array($user_id)){
  1702. $user_ids=implode(",", $user_id);
  1703. } else {
  1704. $user_ids=(int)$user_id;
  1705. }
  1706. if(is_array($fields)) {
  1707. $fields_str=implode(",",$fields);
  1708. } else {
  1709. $fields_str=$fields;
  1710. }
  1711. $users = array();
  1712. $sql = "select user_id,$fields_str from {$PHORUM['user_table']} where user_id in ($user_ids)";
  1713. $res = mysql_query($sql, $conn);
  1714. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1715. if (mysql_num_rows($res)){
  1716. while($rec=mysql_fetch_assoc($res)){
  1717. $users[$rec["user_id"]] = $rec;
  1718. }
  1719. }
  1720. return $users;
  1721. }
  1722. /**
  1723. * Get a list of all the active users.
  1724. *
  1725. * @return array - (key: userid, value: array (username, displayname)
  1726. */
  1727. function phorum_db_user_get_list(){
  1728. $PHORUM = $GLOBALS["PHORUM"];
  1729. $conn = phorum_db_mysql_connect();
  1730. $users = array();
  1731. $sql = "select user_id, username from {$PHORUM['user_table']} order by username asc";
  1732. $res = mysql_query($sql, $conn);
  1733. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1734. while ($row = mysql_fetch_assoc($res)){
  1735. $users[$row["user_id"]] = array("username" => $row["username"], "displayname" => $row["username"]);
  1736. }
  1737. return $users;
  1738. }
  1739. /**
  1740. * Check if the user's password is correct.
  1741. *
  1742. * @param string $username
  1743. * @param string $password
  1744. * @param boolean $temp_password
  1745. *
  1746. * @return int
  1747. * Return the user ID if the password is correct, or zero if not.
  1748. */
  1749. function phorum_db_user_check_pass($username, $password, $temp_password=false){
  1750. $PHORUM = $GLOBALS["PHORUM"];
  1751. $conn = phorum_db_mysql_connect();
  1752. $username = mysql_escape_string($username);
  1753. $password = mysql_escape_string($password);
  1754. $pass_field = ($temp_password) ? "password_temp" : "password";
  1755. $sql = "select user_id from {$PHORUM['user_table']} where username='$username' and $pass_field='$password'";
  1756. $res = mysql_query($sql, $conn);
  1757. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1758. return ($res && mysql_num_rows($res)) ? mysql_result($res, 0, "user_id") : 0;
  1759. }
  1760. /**
  1761. * Check for the given field in the user table and return the user_id
  1762. * of the user it matches or 0 if no match is found.
  1763. *
  1764. * The parameters can be arrays. If they are, all must be passed and all
  1765. * must have the same number of values.
  1766. *
  1767. * If $return_array is true, an array of all matching rows will be returned.
  1768. * Otherwise, only the first user_id from the results will be returned.
  1769. *
  1770. * @param mixed $field
  1771. * @param mixed $value
  1772. * @param string $operator
  1773. * @param boolean $return_array
  1774. *
  1775. * @return mixed
  1776. */
  1777. function phorum_db_user_check_field($field, $value, $operator="=", $return_array=false){
  1778. $PHORUM = $GLOBALS["PHORUM"];
  1779. $ret = 0;
  1780. $conn = phorum_db_mysql_connect();
  1781. if(!is_array($field)){
  1782. $field=array($field);
  1783. }
  1784. if(!is_array($value)){
  1785. $value=array($value);
  1786. }
  1787. if(!is_array($operator)){
  1788. $operator=array($operator);
  1789. }
  1790. foreach($field as $key=>$name){
  1791. $value[$key] = mysql_escape_string($value[$key]);
  1792. $clauses[]="$name $operator[$key] '$value[$key]'";
  1793. }
  1794. $sql = "select user_id from {$PHORUM['user_table']} where ".implode(" and ", $clauses);
  1795. $res = mysql_query($sql, $conn);
  1796. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1797. if ($res && mysql_num_rows($res)){
  1798. if($return_array){
  1799. $ret=array();
  1800. while($row=mysql_fetch_assoc($res)){
  1801. $ret[$row["user_id"]]=$row["user_id"];
  1802. }
  1803. } else {
  1804. $ret = mysql_result($res, 0, "user_id");
  1805. }
  1806. }
  1807. return $ret;
  1808. }
  1809. /**
  1810. * Add a user.
  1811. *
  1812. * @param array $userdata
  1813. *
  1814. * @return int
  1815. * The user ID of the new user.
  1816. */
  1817. function phorum_db_user_add($userdata){
  1818. $PHORUM = $GLOBALS["PHORUM"];
  1819. $conn = phorum_db_mysql_connect();
  1820. if (isset($userdata["forum_permissions"]) && !empty($userdata["forum_permissions"])){
  1821. $forum_perms = $userdata["forum_permissions"];
  1822. unset($userdata["forum_permissions"]);
  1823. }
  1824. if (isset($userdata["user_data"]) && !empty($userdata["user_data"])){
  1825. $user_data = $userdata["user_data"];
  1826. unset($userdata["user_data"]);
  1827. }
  1828. $sql = "insert into {$PHORUM['user_table']} set ";
  1829. $values = array();
  1830. foreach($userdata as $key => $value){
  1831. if (!is_numeric($value)){
  1832. $value = mysql_escape_string($value);
  1833. $values[] = "$key='$value'";
  1834. }else{
  1835. $values[] = "$key=$value";
  1836. }
  1837. }
  1838. $sql .= implode(", ", $values);
  1839. $res = mysql_query($sql, $conn);
  1840. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1841. $user_id = 0;
  1842. if ($res){
  1843. $user_id = mysql_insert_id($conn);
  1844. }
  1845. if ($res){
  1846. if(isset($forum_perms)) {
  1847. // storing forum-permissions
  1848. foreach($forum_perms as $fid => $p){
  1849. $sql = "insert into {$PHORUM['user_permissions_table']} set user_id=$user_id, forum_id=$fid, permission=$p";
  1850. $res = mysql_query($sql, $conn);
  1851. if ($err = mysql_error()){
  1852. phorum_db_mysql_error("$err: $sql");
  1853. break;
  1854. }
  1855. }
  1856. }
  1857. if(isset($user_data)) {
  1858. /* storing custom-fields */
  1859. foreach($user_data as $key => $val){
  1860. if(is_array($val)) { /* arrays need to be serialized */
  1861. $val = 'P_SER:'.serialize($val);
  1862. /* P_SER: (PHORUM_SERIALIZED is our marker telling this Field is serialized */
  1863. } else { /* other vars need to be escaped */
  1864. $val = mysql_escape_string($val);
  1865. }
  1866. $sql = "insert into {$PHORUM['user_custom_fields_table']} (user_id,type,data) VALUES($user_id,$key,'$val')";
  1867. $res = mysql_query($sql, $conn);
  1868. if ($err = mysql_error()){
  1869. phorum_db_mysql_error("$err: $sql");
  1870. break;
  1871. }
  1872. }
  1873. }
  1874. }
  1875. return $user_id;
  1876. }
  1877. /**
  1878. * Update a user's data.
  1879. *
  1880. * @param array $userdata
  1881. *
  1882. * @return boolean
  1883. */
  1884. function phorum_db_user_save($userdata){
  1885. $PHORUM = $GLOBALS["PHORUM"];
  1886. $conn = phorum_db_mysql_connect();
  1887. if(isset($userdata["permissions"])){
  1888. unset($userdata["permissions"]);
  1889. }
  1890. if (isset($userdata["forum_permissions"])){
  1891. $forum_perms = $userdata["forum_permissions"];
  1892. unset($userdata["forum_permissions"]);
  1893. }
  1894. if (isset($userdata["groups"])){
  1895. $groups = $userdata["groups"];
  1896. unset($userdata["groups"]);
  1897. unset($userdata["group_permissions"]);
  1898. }
  1899. if (isset($userdata["user_data"])){
  1900. $user_data = $userdata["user_data"];
  1901. unset($userdata["user_data"]);
  1902. }
  1903. $user_id = $userdata["user_id"];
  1904. unset($userdata["user_id"]);
  1905. if(count($userdata)){
  1906. $sql = "update {$PHORUM['user_table']} set ";
  1907. $values = array();
  1908. foreach($userdata as $key => $value){
  1909. $values[] = "$key='".mysql_escape_string($value)."'";
  1910. }
  1911. $sql .= implode(", ", $values);
  1912. $sql .= " where user_id=$user_id";
  1913. $res = mysql_query($sql, $conn);
  1914. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1915. }
  1916. if (isset($forum_perms)){
  1917. $sql = "delete from {$PHORUM['user_permissions_table']} where user_id = $user_id";
  1918. $res=mysql_query($sql, $conn);
  1919. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1920. foreach($forum_perms as $fid=>$perms){
  1921. $sql = "insert into {$PHORUM['user_permissions_table']} set user_id=$user_id, forum_id=$fid, permission=$perms";
  1922. $res = mysql_query($sql, $conn);
  1923. if ($err = mysql_error()){
  1924. phorum_db_mysql_error("$err: $sql");
  1925. }
  1926. }
  1927. }
  1928. if(isset($user_data)) {
  1929. // storing custom-fields
  1930. $sql = "delete from {$PHORUM['user_custom_fields_table']} where user_id = $user_id";
  1931. $res=mysql_query($sql, $conn);
  1932. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1933. if(is_array($user_data)) {
  1934. foreach($user_data as $key => $val){
  1935. if(is_array($val)) { /* arrays need to be serialized */
  1936. $val = 'P_SER:'.serialize($val);
  1937. /* P_SER: (PHORUM_SERIALIZED is our marker telling this Field is serialized */
  1938. } else { /* other vars need to be escaped */
  1939. $val = mysql_escape_string($val);
  1940. }
  1941. $sql = "insert into {$PHORUM['user_custom_fields_table']} (user_id,type,data) VALUES($user_id,$key,'$val')";
  1942. $res = mysql_query($sql, $conn);
  1943. if ($err = mysql_error()){
  1944. phorum_db_mysql_error("$err: $sql");
  1945. break;
  1946. }
  1947. }
  1948. }
  1949. }
  1950. return (bool)$res;
  1951. }
  1952. /**
  1953. * Save a user's group permissions.
  1954. *
  1955. * @param int $user_id
  1956. * @param array $groups
  1957. *
  1958. * @return boolean
  1959. */
  1960. function phorum_db_user_save_groups($user_id, $groups)
  1961. {
  1962. $PHORUM = $GLOBALS["PHORUM"];
  1963. if (!$user_id > 0){
  1964. return false;
  1965. }
  1966. settype($user_id, "int");
  1967. // erase the group memberships they have now
  1968. $conn = phorum_db_mysql_connect();
  1969. $sql = "delete from {$PHORUM['user_group_xref_table']} where user_id = $user_id";
  1970. $res=mysql_query($sql, $conn);
  1971. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  1972. foreach($groups as $group_id => $group_perm){
  1973. $sql = "insert into {$PHORUM['user_group_xref_table']} set user_id=$user_id, group_id=$group_id, status=$group_perm";
  1974. mysql_query($sql, $conn);
  1975. if ($err = mysql_error()){
  1976. phorum_db_mysql_error("$err: $sql");
  1977. break;
  1978. }
  1979. }
  1980. return (bool)$res;
  1981. }
  1982. /**
  1983. * Subscribe a user to a forum/thread.
  1984. *
  1985. * @param int $user_id
  1986. * @param int $forum_id
  1987. * @param int $thread
  1988. * @param int $type
  1989. *
  1990. * @return boolean
  1991. */
  1992. function phorum_db_user_subscribe($user_id, $forum_id, $thread, $type)
  1993. {
  1994. $PHORUM = $GLOBALS["PHORUM"];
  1995. settype($user_id, "int");
  1996. settype($forum_id, "int");
  1997. settype($thread, "int");
  1998. settype($type, "int");
  1999. $conn = phorum_db_mysql_connect();
  2000. $sql = "replace into {$PHORUM['subscribers_table']} set user_id=$user_id, forum_id=$forum_id, sub_type=$type, thread=$thread";
  2001. $res = mysql_query($sql, $conn);
  2002. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2003. return (bool)$res;
  2004. }
  2005. /**
  2006. * Increment the post-counter for a user.
  2007. *
  2008. * @return boolean
  2009. */
  2010. function phorum_db_user_addpost() {
  2011. $conn = phorum_db_mysql_connect();
  2012. $sql="UPDATE ".$GLOBALS['PHORUM']['user_table']." SET posts=posts+1 WHERE user_id = ".$GLOBALS['PHORUM']['user']['user_id'];
  2013. $res=mysql_query($sql,$conn);
  2014. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2015. return (bool)$res;
  2016. }
  2017. /**
  2018. * Unsubscribe a user to a forum/thread.
  2019. *
  2020. * @param int $user_id
  2021. * @param int $thread
  2022. * @param int $forum_id
  2023. *
  2024. * @return boolean
  2025. */
  2026. function phorum_db_user_unsubscribe($user_id, $thread, $forum_id=0)
  2027. {
  2028. $PHORUM = $GLOBALS["PHORUM"];
  2029. settype($user_id, "int");
  2030. settype($forum_id, "int");
  2031. settype($thread, "int");
  2032. $conn = phorum_db_mysql_connect();
  2033. $sql = "DELETE FROM {$PHORUM['subscribers_table']} WHERE user_id=$user_id AND thread=$thread";
  2034. if($forum_id) $sql.=" and forum_id=$forum_id";
  2035. $res = mysql_query($sql, $conn);
  2036. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2037. return (bool)$res;
  2038. }
  2039. /**
  2040. * Get a list of groups the user is a member of, as well as the
  2041. * users permissions.
  2042. *
  2043. * @param int $user_id
  2044. *
  2045. * @return array
  2046. */
  2047. function phorum_db_user_get_groups($user_id)
  2048. {
  2049. $PHORUM = $GLOBALS["PHORUM"];
  2050. $groups = array();
  2051. if (!$user_id > 0){
  2052. return $groups;
  2053. }
  2054. settype($user_id, "int");
  2055. $conn = phorum_db_mysql_connect();
  2056. $sql = "SELECT group_id, status FROM {$PHORUM['user_group_xref_table']} WHERE user_id = $user_id ORDER BY status DESC";
  2057. $res = mysql_query($sql, $conn);
  2058. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2059. while($row = mysql_fetch_assoc($res)){
  2060. $groups[$row["group_id"]] = $row["status"];
  2061. }
  2062. return $groups;
  2063. }
  2064. /**
  2065. * Get users whose username or email match the search string.
  2066. *
  2067. * @param string $search
  2068. * If empty, all users will be returned.
  2069. *
  2070. * @return array
  2071. */
  2072. function phorum_db_search_users($search)
  2073. {
  2074. $PHORUM = $GLOBALS["PHORUM"];
  2075. $conn = phorum_db_mysql_connect();
  2076. $users = array();
  2077. $search = trim($search);
  2078. $sql = "select user_id, username, email, active, posts, date_last_active from {$PHORUM['user_table']} where username like '%$search%' or email like '%$search%'order by username";
  2079. $res = mysql_query($sql, $conn);
  2080. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2081. if (mysql_num_rows($res)){
  2082. while ($user = mysql_fetch_assoc($res)){
  2083. $users[$user["user_id"]] = $user;
  2084. }
  2085. }
  2086. return $users;
  2087. }
  2088. /**
  2089. * Gets the users that await approval.
  2090. *
  2091. * @return array
  2092. */
  2093. function phorum_db_user_get_unapproved()
  2094. {
  2095. $PHORUM = $GLOBALS["PHORUM"];
  2096. $conn = phorum_db_mysql_connect();
  2097. $sql="select user_id, username, email from {$PHORUM['user_table']} where active in(".PHORUM_USER_PENDING_BOTH.", ".PHORUM_USER_PENDING_MOD.") order by username";
  2098. $res=mysql_query($sql, $conn);
  2099. if ($err = mysql_error()){
  2100. phorum_db_mysql_error("$err: $sql");
  2101. }
  2102. $users=array();
  2103. if($res){
  2104. while($rec=mysql_fetch_assoc($res)){
  2105. $users[$rec["user_id"]]=$rec;
  2106. }
  2107. }
  2108. return $users;
  2109. }
  2110. /**
  2111. * Delete a user completely.
  2112. *
  2113. * The following will be deleted:
  2114. * - entry in the users-table
  2115. * - entries in the permissions-table
  2116. * - entries in the newflags-table
  2117. * - entries in the subscribers-table
  2118. * - entries in the group_xref-table
  2119. * - entries in the private-messages-table
  2120. * - entries in the files-table
  2121. * - sets entries in the messages-table to anonymous
  2122. *
  2123. * @param int $user_id
  2124. *
  2125. * @return boolean
  2126. */
  2127. function phorum_db_user_delete($user_id) {
  2128. $PHORUM = $GLOBALS["PHORUM"];
  2129. // how would we check success???
  2130. $ret = true;
  2131. settype($user_id, "int");
  2132. $conn = phorum_db_mysql_connect();
  2133. // user-table
  2134. $sql = "delete from {$PHORUM['user_table']} where user_id=$user_id";
  2135. $res = mysql_query($sql, $conn);
  2136. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2137. // permissions-table
  2138. $sql = "delete from {$PHORUM['user_permissions_table']} where user_id=$user_id";
  2139. $res = mysql_query($sql, $conn);
  2140. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2141. // newflags-table
  2142. $sql = "delete from {$PHORUM['user_newflags_table']} where user_id=$user_id";
  2143. $res = mysql_query($sql, $conn);
  2144. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2145. // subscribers-table
  2146. $sql = "delete from {$PHORUM['subscribers_table']} where user_id=$user_id";
  2147. $res = mysql_query($sql, $conn);
  2148. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2149. // group-xref-table
  2150. $sql = "delete from {$PHORUM['user_group_xref_table']} where user_id=$user_id";
  2151. $res = mysql_query($sql, $conn);
  2152. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2153. // private messages
  2154. $sql = "select * from {$PHORUM["pm_xref_table"]} where user_id=$user_id";
  2155. $res = mysql_query($sql, $conn);
  2156. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2157. while ($row = mysql_fetch_assoc($res)) {
  2158. $folder = $row["pm_folder_id"] == 0 ? $row["special_folder"] : $row["pm_folder_id"];
  2159. phorum_db_pm_delete($row["pm_message_id"], $folder, $user_id);
  2160. }
  2161. // pm_buddies
  2162. $sql = "delete from {$PHORUM["pm_buddies_table"]} where user_id=$user_id or buddy_user_id=$user_id";
  2163. $res = mysql_query($sql, $conn);
  2164. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2165. // private message folders
  2166. $sql = "delete from {$PHORUM["pm_folders_table"]} where user_id=$user_id";
  2167. $res = mysql_query($sql, $conn);
  2168. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2169. // files-table
  2170. $sql = "delete from {$PHORUM['files_table']} where user_id=$user_id and message_id=0 and link='" . PHORUM_LINK_USER . "'";
  2171. $res = mysql_query($sql, $conn);
  2172. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2173. // custom-fields-table
  2174. $sql = "delete from {$PHORUM['user_custom_fields_table']} where user_id=$user_id";
  2175. $res = mysql_query($sql, $conn);
  2176. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2177. // messages-table
  2178. if(PHORUM_DELETE_CHANGE_AUTHOR) {
  2179. $sql = "update {$PHORUM['message_table']} set user_id=0,email='',author='".mysql_escape_string($PHORUM['DATA']['LANG']['AnonymousUser'])."' where user_id=$user_id";
  2180. } else {
  2181. $sql = "update {$PHORUM['message_table']} set user_id=0,email='' where user_id=$user_id";
  2182. }
  2183. $res = mysql_query($sql, $conn);
  2184. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2185. return $ret;
  2186. }
  2187. /**
  2188. * Get the users file list.
  2189. * @param int $user_id
  2190. * @return array
  2191. */
  2192. function phorum_db_get_user_file_list($user_id)
  2193. {
  2194. $PHORUM = $GLOBALS["PHORUM"];
  2195. $conn = phorum_db_mysql_connect();
  2196. settype($user_id, "int");
  2197. $files=array();
  2198. $sql="select file_id, filename, filesize, add_datetime from {$PHORUM['files_table']} where user_id=$user_id and message_id=0 and link='" . PHORUM_LINK_USER . "'";
  2199. $res = mysql_query($sql, $conn);
  2200. if ($err = mysql_error()){
  2201. phorum_db_mysql_error("$err: $sql");
  2202. }
  2203. if($res){
  2204. while($rec=mysql_fetch_assoc($res)){
  2205. $files[$rec["file_id"]]=$rec;
  2206. }
  2207. }
  2208. return $files;
  2209. }
  2210. /**
  2211. * Get the message's file list.
  2212. * @param int $message_id
  2213. * @return array
  2214. */
  2215. function phorum_db_get_message_file_list($message_id)
  2216. {
  2217. $PHORUM = $GLOBALS["PHORUM"];
  2218. $conn = phorum_db_mysql_connect();
  2219. $files=array();
  2220. $sql="select file_id, filename, filesize, add_datetime from {$PHORUM['files_table']} where message_id=$message_id and link='" . PHORUM_LINK_MESSAGE . "'";
  2221. $res = mysql_query($sql, $conn);
  2222. if ($err = mysql_error()){
  2223. phorum_db_mysql_error("$err: $sql");
  2224. }
  2225. if($res){
  2226. while($rec=mysql_fetch_assoc($res)){
  2227. $files[$rec["file_id"]]=$rec;
  2228. }
  2229. }
  2230. return $files;
  2231. }
  2232. /**
  2233. * Retrieve a file.
  2234. * @param int $file_id
  2235. * @return array
  2236. */
  2237. function phorum_db_file_get($file_id)
  2238. {
  2239. $PHORUM = $GLOBALS["PHORUM"];
  2240. $conn = phorum_db_mysql_connect();
  2241. settype($file_id, "int");
  2242. $file=array();
  2243. $sql="select * from {$PHORUM['files_table']} where file_id=$file_id";
  2244. $res = mysql_query($sql, $conn);
  2245. if ($err = mysql_error()){
  2246. phorum_db_mysql_error("$err: $sql");
  2247. }
  2248. if($res){
  2249. $file=mysql_fetch_assoc($res);
  2250. }
  2251. return $file;
  2252. }
  2253. /**
  2254. * Save a file to the db and return the new file ID.
  2255. *
  2256. * @param int $user_id
  2257. * @param string $filename
  2258. * @param int $filesize
  2259. * @param string $buffer
  2260. * @param int $message_id
  2261. * @param string $link
  2262. *
  2263. * @return int
  2264. * The file ID.
  2265. */
  2266. function phorum_db_file_save($user_id, $filename, $filesize, $buffer, $message_id=0, $link=null)
  2267. {
  2268. $PHORUM = $GLOBALS["PHORUM"];
  2269. if (is_null($link)) {
  2270. $link = $message_id ? PHORUM_LINK_MESSAGE : PHORUM_LINK_USER;
  2271. } else {
  2272. $link = addslashes($link);
  2273. }
  2274. $conn = phorum_db_mysql_connect();
  2275. $file_id=0;
  2276. settype($user_id, "int");
  2277. settype($message_id, "int");
  2278. settype($filesize, "int");
  2279. $filename=addslashes($filename);
  2280. $sql="insert into {$PHORUM['files_table']} set user_id=$user_id, message_id=$message_id, link='$link', filename='$filename', filesize=$filesize, file_data='$buffer', add_datetime=".time();
  2281. $res = mysql_query($sql, $conn);
  2282. if ($err = mysql_error()){
  2283. phorum_db_mysql_error("$err: $sql");
  2284. }
  2285. if($res){
  2286. $file_id=mysql_insert_id($conn);
  2287. }
  2288. return $file_id;
  2289. }
  2290. /**
  2291. * Delete a file.
  2292. * @param int $file_id
  2293. * @return boolean
  2294. */
  2295. function phorum_db_file_delete($file_id)
  2296. {
  2297. $PHORUM = $GLOBALS["PHORUM"];
  2298. $conn = phorum_db_mysql_connect();
  2299. settype($file_id, "int");
  2300. $sql="delete from {$PHORUM['files_table']} where file_id=$file_id";
  2301. $res = mysql_query($sql, $conn);
  2302. if ($err = mysql_error()){
  2303. phorum_db_mysql_error("$err: $sql");
  2304. }
  2305. return $res;
  2306. }
  2307. /**
  2308. * Link a file to a specific message.
  2309. * @param int $file_id
  2310. * @param int $message_id
  2311. * @param string $link
  2312. * @return boolean
  2313. */
  2314. function phorum_db_file_link($file_id, $message_id, $link = null)
  2315. {
  2316. $PHORUM = $GLOBALS["PHORUM"];
  2317. if (is_null($link)) {
  2318. $link = $message_id ? PHORUM_LINK_MESSAGE : PHORUM_LINK_USER;
  2319. } else {
  2320. $link = addslashes($link);
  2321. }
  2322. $conn = phorum_db_mysql_connect();
  2323. settype($file_id, "int");
  2324. settype($message_id, "int");
  2325. $sql="update {$PHORUM['files_table']} " .
  2326. "set message_id=$message_id, link='$link' " .
  2327. "where file_id=$file_id";
  2328. $res = mysql_query($sql, $conn);
  2329. if ($err = mysql_error()){
  2330. phorum_db_mysql_error("$err: $sql");
  2331. }
  2332. return $res;
  2333. }
  2334. /**
  2335. * Read the current total size of all files for a user.
  2336. *
  2337. * @param int $user_id
  2338. *
  2339. * @return int
  2340. */
  2341. function phorum_db_get_user_filesize_total($user_id)
  2342. {
  2343. $PHORUM = $GLOBALS["PHORUM"];
  2344. $conn = phorum_db_mysql_connect();
  2345. settype($user_id, "int");
  2346. $total=0;
  2347. $sql="select sum(filesize) as total from {$PHORUM['files_table']} where user_id=$user_id and message_id=0 and link='" . PHORUM_LINK_USER . "'";
  2348. $res = mysql_query($sql, $conn);
  2349. if ($err = mysql_error()){
  2350. phorum_db_mysql_error("$err: $sql");
  2351. }
  2352. if($res){
  2353. $total=mysql_result($res, 0,"total");
  2354. }
  2355. return $total;
  2356. }
  2357. /**
  2358. * Clean up stale files from the database. Stale files are files that
  2359. * are not linked to anything. These can for example be caused by users
  2360. * that are writing a message with attachments, but never post it.
  2361. *
  2362. * @param boolean $live_run - If set to false (default), the function
  2363. * will return a list of files that will
  2364. * be purged. If set to true, files will
  2365. * be purged.
  2366. * @return mixed
  2367. * Return TRUE if $live_run is TRUE, return an array of
  2368. * files indexed by file ID.
  2369. */
  2370. function phorum_db_file_purge_stale_files($live_run = false)
  2371. {
  2372. $PHORUM = $GLOBALS["PHORUM"];
  2373. $conn = phorum_db_mysql_connect();
  2374. $where = "link='" . PHORUM_LINK_EDITOR. "' " .
  2375. "and add_datetime<". (time()-PHORUM_MAX_EDIT_TIME);
  2376. // Purge files.
  2377. if ($live_run) {
  2378. // Delete files that are linked to the editor and are
  2379. // added a while ago. These are from abandoned posts.
  2380. $sql = "delete from {$PHORUM['files_table']} " .
  2381. "where $where";
  2382. $res = mysql_query($sql, $conn);
  2383. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2384. return true;
  2385. // Only select a list of files that can be purged.
  2386. } else {
  2387. // Select files that are linked to the editor and are
  2388. // added a while ago. These are from abandoned posts.
  2389. $sql = "select file_id, filename, filesize, add_datetime " .
  2390. "from {$PHORUM['files_table']} " .
  2391. "where $where";
  2392. $res = mysql_query($sql, $conn);
  2393. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2394. $purge_files = array();
  2395. if (mysql_num_rows($res) > 0) {
  2396. while ($row = mysql_fetch_assoc($res)) {
  2397. $row["reason"] = "Stale editor file";
  2398. $purge_files[$row["file_id"]] = $row;
  2399. }
  2400. }
  2401. return $purge_files;
  2402. }
  2403. }
  2404. /**
  2405. * NOTE: this function seems to call phorum_db_newflag_add_read()
  2406. * incorrectly!?
  2407. *
  2408. * @param int $forum_id
  2409. * @return void
  2410. */
  2411. function phorum_db_newflag_allread($forum_id=0)
  2412. {
  2413. $PHORUM = $GLOBALS['PHORUM'];
  2414. $conn = phorum_db_mysql_connect();
  2415. settype($forum_id, "int");
  2416. if(empty($forum_id)) $forum_id=$PHORUM["forum_id"];
  2417. // delete all newflags for this user and forum
  2418. phorum_db_newflag_delete(0,$forum_id);
  2419. // get the maximum message-id in this forum
  2420. $sql = "select max(message_id) from {$PHORUM['message_table']} where forum_id=$forum_id";
  2421. $res = mysql_query($sql, $conn);
  2422. if ($err = mysql_error()){
  2423. phorum_db_mysql_error("$err: $sql");
  2424. }elseif (mysql_num_rows($res) > 0){
  2425. $row = mysql_fetch_row($res);
  2426. if($row[0] > 0) {
  2427. // set this message as min-id
  2428. phorum_db_newflag_add_read(array(0=>array('id'=>$row[0],'forum'=>$forum_id)));
  2429. }
  2430. }
  2431. }
  2432. /**
  2433. * Returns the read messages for the current user and forum
  2434. * optionally for a given forum (for the index).
  2435. *
  2436. * @param int $forum_id
  2437. *
  2438. * @return array
  2439. */
  2440. function phorum_db_newflag_get_flags($forum_id=0)
  2441. {
  2442. $PHORUM = $GLOBALS["PHORUM"];
  2443. settype($forum_id, "int");
  2444. $read_msgs=array('min_id'=>0);
  2445. if(empty($forum_id)) $forum_id=$PHORUM["forum_id"];
  2446. $sql="SELECT message_id,forum_id FROM ".$PHORUM['user_newflags_table']." WHERE user_id={$PHORUM['user']['user_id']} AND forum_id IN({$forum_id},{$PHORUM['vroot']})";
  2447. $conn = phorum_db_mysql_connect();
  2448. $res = mysql_query($sql, $conn);
  2449. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2450. while($row=mysql_fetch_row($res)) {
  2451. // set the min-id if given flag is set
  2452. if($row[1] != $PHORUM['vroot'] && ($read_msgs['min_id']==0 || $row[0] < $read_msgs['min_id'])) {
  2453. $read_msgs['min_id']=$row[0];
  2454. } else {
  2455. $read_msgs[$row[0]]=$row[0];
  2456. }
  2457. }
  2458. return $read_msgs;
  2459. }
  2460. /**
  2461. * Return the count of unread messages the current user and forum
  2462. * optionally for a given forum (for the index).
  2463. *
  2464. * @param int $forum_id
  2465. *
  2466. * @return array
  2467. */
  2468. function phorum_db_newflag_get_unread_count($forum_id=0)
  2469. {
  2470. $PHORUM = $GLOBALS["PHORUM"];
  2471. settype($forum_id, "int");
  2472. if(empty($forum_id)) $forum_id=$PHORUM["forum_id"];
  2473. // get the read message array
  2474. $read_msgs = phorum_db_newflag_get_flags($forum_id);
  2475. if($read_msgs["min_id"]==0) return array(0,0);
  2476. $sql="SELECT count(*) as count FROM ".$PHORUM['message_table']." WHERE message_id NOT in (".implode(",", $read_msgs).") and message_id > {$read_msgs['min_id']} and forum_id in ({$forum_id},0) and status=".PHORUM_STATUS_APPROVED." and not ".PHORUM_SQL_MOVEDMESSAGES;
  2477. $conn = phorum_db_mysql_connect();
  2478. $res = mysql_query($sql, $conn);
  2479. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2480. $counts[] = mysql_result($res, 0, "count");
  2481. $sql="SELECT count(*) as count FROM ".$PHORUM['message_table']." WHERE message_id NOT in (".implode(",", $read_msgs).") and message_id > {$read_msgs['min_id']} and forum_id in ({$forum_id},0) and parent_id=0 and status=".PHORUM_STATUS_APPROVED." and not ".PHORUM_SQL_MOVEDMESSAGES;
  2482. $conn = phorum_db_mysql_connect();
  2483. $res = mysql_query($sql, $conn);
  2484. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2485. $counts[] = mysql_result($res, 0, "count");
  2486. return $counts;
  2487. }
  2488. /**
  2489. * Mark a message as read.
  2490. *
  2491. * @param array $message_ids
  2492. * This can also be a single int if you just want to
  2493. * mark one message as read.
  2494. *
  2495. * @return void
  2496. */
  2497. function phorum_db_newflag_add_read($message_ids) {
  2498. $PHORUM = $GLOBALS["PHORUM"];
  2499. $num_newflags=phorum_db_newflag_get_count();
  2500. // maybe got just one message
  2501. if(!is_array($message_ids)) {
  2502. $message_ids=array(0=>(int)$message_ids);
  2503. }
  2504. // deleting messages which are too much
  2505. $num_end=$num_newflags+count($message_ids);
  2506. if($num_end > PHORUM_MAX_NEW_INFO) {
  2507. phorum_db_newflag_delete($num_end - PHORUM_MAX_NEW_INFO);
  2508. }
  2509. // building the query
  2510. $values=array();
  2511. $cnt=0;
  2512. foreach($message_ids as $id=>$data) {
  2513. if(is_array($data)) {
  2514. $values[]="({$PHORUM['user']['user_id']},{$data['forum']},{$data['id']})";
  2515. } else {
  2516. $values[]="({$PHORUM['user']['user_id']},{$PHORUM['forum_id']},$data)";
  2517. }
  2518. $cnt++;
  2519. }
  2520. if($cnt) {
  2521. $insert_sql="INSERT IGNORE INTO ".$PHORUM['user_newflags_table']." (user_id,forum_id,message_id) VALUES".join(",",$values);
  2522. // fire away
  2523. $conn = phorum_db_mysql_connect();
  2524. $res = mysql_query($insert_sql, $conn);
  2525. if ($err = mysql_error()) phorum_db_mysql_error("$err: $insert_sql");
  2526. }
  2527. }
  2528. /**
  2529. * Return the number of newflags for this user and forum.
  2530. *
  2531. * @param int $forum_id
  2532. *
  2533. * @return int
  2534. */
  2535. function phorum_db_newflag_get_count($forum_id=0)
  2536. {
  2537. $PHORUM = $GLOBALS["PHORUM"];
  2538. settype($forum_id, "int");
  2539. if(empty($forum_id)) $forum_id=$PHORUM["forum_id"];
  2540. $sql="SELECT count(*) FROM ".$PHORUM['user_newflags_table']." WHERE user_id={$PHORUM['user']['user_id']} AND forum_id={$forum_id}";
  2541. // fire away
  2542. $conn = phorum_db_mysql_connect();
  2543. $res = mysql_query($sql, $conn);
  2544. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2545. $row=mysql_fetch_row($res);
  2546. return $row[0];
  2547. }
  2548. /**
  2549. * Remove a number of newflags for this user and forum.
  2550. *
  2551. * @param int $numdelete
  2552. * Limit the number of flags deleted to this number.
  2553. * @param int $forum_id
  2554. *
  2555. * @return void
  2556. */
  2557. function phorum_db_newflag_delete($numdelete=0,$forum_id=0)
  2558. {
  2559. $PHORUM = $GLOBALS["PHORUM"];
  2560. settype($forum_id, "int");
  2561. settype($numdelete, "int");
  2562. if(empty($forum_id)) $forum_id=$PHORUM["forum_id"];
  2563. if($numdelete>0) {
  2564. $lvar=" ORDER BY message_id ASC LIMIT $numdelete";
  2565. } else {
  2566. $lvar="";
  2567. }
  2568. // delete the number of newflags given
  2569. $del_sql="DELETE FROM ".$PHORUM['user_newflags_table']." WHERE user_id={$PHORUM['user']['user_id']} AND forum_id={$forum_id}".$lvar;
  2570. // fire away
  2571. $conn = phorum_db_mysql_connect();
  2572. $res = mysql_query($del_sql, $conn);
  2573. if ($err = mysql_error()) phorum_db_mysql_error("$err: $del_sql");
  2574. }
  2575. /**
  2576. * Get the user ids of the users subscribed to a forum/thread.
  2577. *
  2578. * @param int $forum_id
  2579. * @param int $thread
  2580. * @param int $type
  2581. *
  2582. * @return array
  2583. */
  2584. function phorum_db_get_subscribed_users($forum_id, $thread, $type){
  2585. $PHORUM = $GLOBALS["PHORUM"];
  2586. settype($forum_id, "int");
  2587. settype($thread, "int");
  2588. settype($type, "int");
  2589. $conn = phorum_db_mysql_connect();
  2590. $userignore="";
  2591. if ($PHORUM["DATA"]["LOGGEDIN"])
  2592. $userignore="and b.user_id != {$PHORUM['user']['user_id']}";
  2593. $sql = "select DISTINCT(b.email),user_language from {$PHORUM['subscribers_table']} as a,{$PHORUM['user_table']} as b where a.forum_id=$forum_id and (a.thread=$thread or a.thread=0) and a.sub_type=$type and b.user_id=a.user_id $userignore";
  2594. $res = mysql_query($sql, $conn);
  2595. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2596. $arr=array();
  2597. while ($rec = mysql_fetch_row($res)){
  2598. if(!empty($rec[1])) // user-language is set
  2599. $arr[$rec[1]][] = $rec[0];
  2600. else // no user-language is set
  2601. $arr[$PHORUM['language']][]= $rec[0];
  2602. }
  2603. return $arr;
  2604. }
  2605. /**
  2606. * Get the subscriptions of a user-id, together with the forum-id
  2607. * and subjects of the threads.
  2608. *
  2609. * @param int $user_id
  2610. * @param int $days
  2611. *
  2612. * @return array
  2613. */
  2614. function phorum_db_get_message_subscriptions($user_id,$days=2){
  2615. $PHORUM = $GLOBALS["PHORUM"];
  2616. $conn = phorum_db_mysql_connect();
  2617. $userignore="";
  2618. if ($PHORUM["DATA"]["LOGGEDIN"])
  2619. $userignore="and b.user_id != {$PHORUM['user']['user_id']}";
  2620. if($days > 0) {
  2621. $timestr=" AND (".time()." - b.modifystamp) <= ($days * 86400)";
  2622. } else {
  2623. $timestr="";
  2624. }
  2625. $sql = "select a.thread, a.forum_id, a.sub_type, b.subject,b.modifystamp,b.author,b.user_id,b.email from {$PHORUM['subscribers_table']} as a,{$PHORUM['message_table']} as b where a.user_id=$user_id and b.message_id=a.thread and (a.sub_type=".PHORUM_SUBSCRIPTION_MESSAGE." or a.sub_type=".PHORUM_SUBSCRIPTION_BOOKMARK.")"."$timestr ORDER BY b.modifystamp desc";
  2626. $res = mysql_query($sql, $conn);
  2627. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2628. $arr=array();
  2629. $forum_ids=array();
  2630. while ($rec = mysql_fetch_assoc($res)){
  2631. $unsub_url=phorum_get_url(PHORUM_CONTROLCENTER_URL, "panel=".PHORUM_CC_SUBSCRIPTION_THREADS, "unsub_id=".$rec['thread'], "unsub_forum=".$rec['forum_id'], "unsub_type=".$rec['sub_type']);
  2632. $rec['unsubscribe_url']=$unsub_url;
  2633. $arr[] = $rec;
  2634. $forum_ids[]=$rec['forum_id'];
  2635. }
  2636. $arr['forum_ids']=$forum_ids;
  2637. return $arr;
  2638. }
  2639. /**
  2640. * Find out if a user is subscribed to a thread.
  2641. *
  2642. * @param int $forum_id
  2643. * @param int $thread
  2644. * @param int $user_id
  2645. * @param int $type
  2646. *
  2647. * @return boolean
  2648. */
  2649. function phorum_db_get_if_subscribed($forum_id, $thread, $user_id, $type=PHORUM_SUBSCRIPTION_MESSAGE)
  2650. {
  2651. $PHORUM = $GLOBALS["PHORUM"];
  2652. settype($forum_id, "int");
  2653. settype($thread, "int");
  2654. settype($user_id, "int");
  2655. settype($type, "int");
  2656. $conn = phorum_db_mysql_connect();
  2657. $sql = "select user_id from {$PHORUM['subscribers_table']} where forum_id=$forum_id and thread=$thread and user_id=$user_id and sub_type=$type";
  2658. $res = mysql_query($sql, $conn);
  2659. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2660. if (mysql_num_rows($res) > 0){
  2661. $retval = true;
  2662. }else{
  2663. $retval = false;
  2664. }
  2665. return $retval;
  2666. }
  2667. /**
  2668. * Retrieve the banlists for the current forum.
  2669. * @param boolean $ordered
  2670. * @return array
  2671. */
  2672. function phorum_db_get_banlists($ordered=false) {
  2673. $PHORUM = $GLOBALS["PHORUM"];
  2674. $retarr = array();
  2675. $forumstr = "";
  2676. $conn = phorum_db_mysql_connect();
  2677. if(isset($PHORUM['forum_id']) && !empty($PHORUM['forum_id']))
  2678. $forumstr = "WHERE forum_id = {$PHORUM['forum_id']} OR forum_id = 0";
  2679. if(isset($PHORUM['vroot']) && !empty($PHORUM['vroot']))
  2680. $forumstr .= " OR forum_id = {$PHORUM['vroot']}";
  2681. $sql = "SELECT * FROM {$PHORUM['banlist_table']} $forumstr";
  2682. if($ordered) {
  2683. $sql.= " ORDER BY type, string";
  2684. }
  2685. $res = mysql_query($sql, $conn);
  2686. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2687. if (mysql_num_rows($res) > 0){
  2688. while($row = mysql_fetch_assoc($res)) {
  2689. $retarr[$row['type']][$row['id']]=array('pcre'=>$row['pcre'],'string'=>$row['string'],'forum_id'=>$row['forum_id']);
  2690. }
  2691. }
  2692. return $retarr;
  2693. }
  2694. /**
  2695. * Retrieve an item from the banlists.
  2696. *
  2697. * @param int $banid
  2698. *
  2699. * @return array
  2700. */
  2701. function phorum_db_get_banitem($banid) {
  2702. $PHORUM = $GLOBALS["PHORUM"];
  2703. $retarr = array();
  2704. $conn = phorum_db_mysql_connect();
  2705. settype($banid, "int");
  2706. $sql = "SELECT * FROM {$PHORUM['banlist_table']} WHERE id = $banid";
  2707. $res = mysql_query($sql, $conn);
  2708. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2709. if (mysql_num_rows($res) > 0){
  2710. while($row = mysql_fetch_assoc($res)) {
  2711. $retarr=array('pcre'=>$row['pcre'],'string'=>$row['string'],'forumid'=>$row['forum_id'],'type'=>$row['type']);
  2712. }
  2713. }
  2714. return $retarr;
  2715. }
  2716. /**
  2717. * Delete one item from the banlists.
  2718. * @param int $banid
  2719. * @return boolean
  2720. */
  2721. function phorum_db_del_banitem($banid) {
  2722. $PHORUM = $GLOBALS["PHORUM"];
  2723. $conn = phorum_db_mysql_connect();
  2724. $sql = "DELETE FROM {$PHORUM['banlist_table']} WHERE id = $banid";
  2725. $res = mysql_query($sql, $conn);
  2726. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2727. if(mysql_affected_rows($conn) > 0) {
  2728. return true;
  2729. } else {
  2730. return false;
  2731. }
  2732. }
  2733. /**
  2734. * Add or modify a banlist-entry.
  2735. *
  2736. * @param int $type
  2737. * Can be one of:
  2738. * PHORUM_BAD_IPS
  2739. * PHORUM_BAD_NAMES
  2740. * PHORUM_BAD_EMAILS
  2741. * PHORUM_BAD_WORDS
  2742. * PHORUM_BAD_USERID
  2743. * PHORUM_BAD_SPAM_WORDS
  2744. *
  2745. * @param int $pcre
  2746. * Set to zero if $string isnt a regular expression, set to 1 if
  2747. * it is.
  2748. *
  2749. * @param string $string
  2750. * String to match to see if something is banned.
  2751. *
  2752. * @param int $forum_id
  2753. * @param int $id
  2754. * The ID of the banlist entry, use only if you are modifying an entry.
  2755. * @return boolean
  2756. */
  2757. function phorum_db_mod_banlists($type,$pcre,$string,$forum_id,$id=0) {
  2758. $PHORUM = $GLOBALS["PHORUM"];
  2759. $retarr = array();
  2760. $conn = phorum_db_mysql_connect();
  2761. settype($type, "int");
  2762. settype($pcre, "int");
  2763. settype($forum_id, "int");
  2764. settype($id, "int");
  2765. if($id > 0) { // modifying an entry
  2766. $sql = "UPDATE {$PHORUM['banlist_table']} SET forum_id = $forum_id, type = $type, pcre = $pcre, string = '".mysql_escape_string($string)."' where id = $id";
  2767. } else { // adding an entry
  2768. $sql = "INSERT INTO {$PHORUM['banlist_table']} (forum_id,type,pcre,string) VALUES($forum_id,$type,$pcre,'".mysql_escape_string($string)."')";
  2769. }
  2770. $res = mysql_query($sql, $conn);
  2771. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2772. if(mysql_affected_rows($conn) > 0) {
  2773. return true;
  2774. } else {
  2775. return false;
  2776. }
  2777. }
  2778. /**
  2779. * Get all private messages in a folder.
  2780. *
  2781. * @param mixed $folder - The folder to use. Either a special folder
  2782. * (PHORUM_PM_INBOX or PHORUM_PM_OUTBOX) or the
  2783. * id of a user's custom folder.
  2784. * @param int $user_id - The user to retrieve messages for or NULL
  2785. * to use the current user (default).
  2786. * @param boolean $reverse - If set to a true value (default), sorting
  2787. * of messages is done in reverse (newest first).
  2788. *
  2789. * @return array
  2790. */
  2791. function phorum_db_pm_list($folder, $user_id = NULL, $reverse = true)
  2792. {
  2793. $PHORUM = $GLOBALS["PHORUM"];
  2794. $conn = phorum_db_mysql_connect();
  2795. if ($user_id == NULL) $user_id = $PHORUM['user']['user_id'];
  2796. settype($user_id, "int");
  2797. $folder_sql = "user_id = $user_id AND ";
  2798. if (is_numeric($folder)) {
  2799. $folder_sql .= "pm_folder_id=$folder";
  2800. } elseif ($folder == PHORUM_PM_INBOX || $folder == PHORUM_PM_OUTBOX) {
  2801. $folder_sql .= "pm_folder_id=0 AND special_folder='$folder'";
  2802. } else {
  2803. die ("Illegal folder '$folder' requested for user id '$user_id'");
  2804. }
  2805. $sql = "SELECT m.pm_message_id, from_user_id, from_username, subject, " .
  2806. "datestamp, meta, pm_xref_id, user_id, pm_folder_id, " .
  2807. "special_folder, read_flag, reply_flag " .
  2808. "FROM {$PHORUM['pm_messages_table']} as m, {$PHORUM['pm_xref_table']} as x " .
  2809. "WHERE $folder_sql " .
  2810. "AND x.pm_message_id = m.pm_message_id " .
  2811. "ORDER BY x.pm_message_id " . ($reverse ? "DESC" : "ASC");
  2812. $res = mysql_query($sql, $conn);
  2813. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2814. $list = array();
  2815. if (mysql_num_rows($res) > 0){
  2816. while($row = mysql_fetch_assoc($res)) {
  2817. // Add the recipient information unserialized to the message..
  2818. $meta = unserialize($row['meta']);
  2819. $row['recipients'] = $meta['recipients'];
  2820. $list[$row["pm_message_id"]]=$row;
  2821. }
  2822. }
  2823. return $list;
  2824. }
  2825. /**
  2826. * Retrieve a private message from the database.
  2827. *
  2828. * @param int $pm_id - The id for the private message to retrieve.
  2829. * @param string $folder - The folder to retrieve the message from or
  2830. * NULL if the folder does not matter.
  2831. * @param int $user_id - The user to retrieve messages for or NULL
  2832. * to use the current user (default).
  2833. *
  2834. * @return mixed
  2835. * Return an array (the message) on success,
  2836. * return NULL if the message was not found.
  2837. */
  2838. function phorum_db_pm_get($pm_id, $folder = NULL, $user_id = NULL)
  2839. {
  2840. $PHORUM = $GLOBALS["PHORUM"];
  2841. $conn = phorum_db_mysql_connect();
  2842. if ($user_id == NULL) $user_id = $PHORUM['user']['user_id'];
  2843. settype($user_id, "int");
  2844. settype($pm_id, "int");
  2845. if (is_null($folder)) {
  2846. $folder_sql = '';
  2847. } elseif (is_numeric($folder)) {
  2848. $folder_sql = "pm_folder_id=$folder AND ";
  2849. } elseif ($folder == PHORUM_PM_INBOX || $folder == PHORUM_PM_OUTBOX) {
  2850. $folder_sql = "pm_folder_id=0 AND special_folder='$folder' AND ";
  2851. } else {
  2852. die ("Illegal folder '$folder' requested for message id '$pm_id'");
  2853. }
  2854. $sql = "SELECT * " .
  2855. "FROM {$PHORUM['pm_messages_table']} as m, {$PHORUM['pm_xref_table']} as x " .
  2856. "WHERE $folder_sql x.pm_message_id = $pm_id AND x.user_id = $user_id " .
  2857. "AND x.pm_message_id = m.pm_message_id";
  2858. $res = mysql_query($sql, $conn);
  2859. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2860. if (mysql_num_rows($res) > 0){
  2861. $row = mysql_fetch_assoc($res);
  2862. // Add the recipient information unserialized to the message..
  2863. $meta = unserialize($row['meta']);
  2864. $row['recipients'] = $meta['recipients'];
  2865. return $row;
  2866. } else {
  2867. return NULL;
  2868. }
  2869. }
  2870. /**
  2871. * Create a new folder for a user.
  2872. *
  2873. * @param string $foldername - The name of the folder to create.
  2874. * @param int $user_id - The user to create the folder for or
  2875. * NULL to use the current user (default).
  2876. *
  2877. * @return boolean
  2878. */
  2879. function phorum_db_pm_create_folder($foldername, $user_id = NULL)
  2880. {
  2881. $PHORUM = $GLOBALS["PHORUM"];
  2882. $conn = phorum_db_mysql_connect();
  2883. if ($user_id == NULL) $user_id = $PHORUM['user']['user_id'];
  2884. settype($user_id, "int");
  2885. $sql = "INSERT INTO {$PHORUM['pm_folders_table']} SET " .
  2886. "user_id=$user_id, " .
  2887. "foldername='".mysql_escape_string($foldername)."'";
  2888. $res = mysql_query($sql, $conn);
  2889. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2890. return $res;
  2891. }
  2892. /**
  2893. * Rename a folder for a user.
  2894. *
  2895. * @param int $folder_id - The id of the folder to rename.
  2896. * @param string $newname - The new name for the folder.
  2897. * @param int $user_id - The user to rename the folder for or
  2898. * NULL to use the current user (default).
  2899. *
  2900. * @return boolean
  2901. */
  2902. function phorum_db_pm_rename_folder($folder_id, $newname, $user_id = NULL)
  2903. {
  2904. $PHORUM = $GLOBALS["PHORUM"];
  2905. $conn = phorum_db_mysql_connect();
  2906. if ($user_id == NULL) $user_id = $PHORUM['user']['user_id'];
  2907. settype($user_id, "int");
  2908. settype($folder_id, "int");
  2909. $sql = "UPDATE {$PHORUM['pm_folders_table']} " .
  2910. "SET foldername = '".mysql_escape_string($newname)."' " .
  2911. "WHERE pm_folder_id = $folder_id AND user_id = $user_id";
  2912. $res = mysql_query($sql, $conn);
  2913. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2914. return $res;
  2915. }
  2916. /**
  2917. * Delete a folder for a user. Along with the folder, all contained
  2918. * messages are deleted as well.
  2919. *
  2920. * @param int $folder_id - The id of the folder to delete.
  2921. * @param int $user_id - The user to delete the folder for or
  2922. * NULL to use the current user (default).
  2923. *
  2924. * @return boolean
  2925. */
  2926. function phorum_db_pm_delete_folder($folder_id, $user_id = NULL)
  2927. {
  2928. $PHORUM = $GLOBALS["PHORUM"];
  2929. $conn = phorum_db_mysql_connect();
  2930. if ($user_id == NULL) $user_id = $PHORUM['user']['user_id'];
  2931. settype($user_id, "int");
  2932. settype($folder_id, "int");
  2933. // Get messages in this folder and delete them.
  2934. $list = phorum_db_pm_list($folder_id, $user_id);
  2935. foreach ($list as $id => $data) {
  2936. phorum_db_pm_delete($id, $folder_id, $user_id);
  2937. }
  2938. // Delete the folder itself.
  2939. $sql = "DELETE FROM {$PHORUM['pm_folders_table']} " .
  2940. "WHERE pm_folder_id = $folder_id AND user_id = $user_id";
  2941. $res = mysql_query($sql, $conn);
  2942. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2943. return $res;
  2944. }
  2945. /**
  2946. * Retrieve the list of folders for a user.
  2947. *
  2948. * @param int $user_id - The user to retrieve folders for or NULL
  2949. * to use the current user (default).
  2950. * @param boolean $count_messages - Count the number of messages for the
  2951. * folders. Default, this is not done.
  2952. *
  2953. * @return array
  2954. */
  2955. function phorum_db_pm_getfolders($user_id = NULL, $count_messages = false)
  2956. {
  2957. $PHORUM = $GLOBALS["PHORUM"];
  2958. $conn = phorum_db_mysql_connect();
  2959. if ($user_id == NULL) $user_id = $PHORUM['user']['user_id'];
  2960. settype($user_id, "int");
  2961. // Setup the list of folders. Our special folders are
  2962. // not in the database, so these are added here.
  2963. $folders = array(
  2964. PHORUM_PM_INBOX => array(
  2965. 'id' => PHORUM_PM_INBOX,
  2966. 'name' => $PHORUM["DATA"]["LANG"]["INBOX"],
  2967. ),
  2968. );
  2969. // Select all custom folders for the user.
  2970. $sql = "SELECT * FROM {$PHORUM['pm_folders_table']} " .
  2971. "WHERE user_id = $user_id ORDER BY foldername";
  2972. $res = mysql_query($sql, $conn);
  2973. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  2974. // Add them to the folderlist.
  2975. if (mysql_num_rows($res) > 0){
  2976. while (($row = mysql_fetch_assoc($res))) {
  2977. $folders[$row["pm_folder_id"]] = array(
  2978. 'id' => $row["pm_folder_id"],
  2979. 'name' => $row["foldername"],
  2980. );
  2981. }
  2982. }
  2983. // Add the outgoing box.
  2984. $folders[PHORUM_PM_OUTBOX] = array(
  2985. 'id' => PHORUM_PM_OUTBOX,
  2986. 'name' => $PHORUM["DATA"]["LANG"]["SentItems"],
  2987. );
  2988. // Count messages if requested.
  2989. if ($count_messages)
  2990. {
  2991. // Initialize counters.
  2992. foreach ($folders as $id => $data) {
  2993. $folders[$id]["total"] = $folders[$id]["new"] = 0;
  2994. }
  2995. // Collect count information.
  2996. $sql = "SELECT pm_folder_id, special_folder, " .
  2997. "count(*) as total, (count(*) - sum(read_flag)) as new " .
  2998. "FROM {$PHORUM['pm_xref_table']} " .
  2999. "WHERE user_id = $user_id " .
  3000. "GROUP BY pm_folder_id, special_folder";
  3001. $res = mysql_query($sql, $conn);
  3002. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  3003. // Add counters to the folderlist.
  3004. if (mysql_num_rows($res) > 0){
  3005. while (($row = mysql_fetch_assoc($res))) {
  3006. $folder_id = $row["pm_folder_id"] ? $row["pm_folder_id"] : $row["special_folder"];
  3007. // If there are stale messages, we do not want them
  3008. // to create non-existant mailboxes in the list.
  3009. if (isset($folders[$folder_id])) {
  3010. $folders[$folder_id]["total"] = $row["total"];
  3011. $folders[$folder_id]["new"] = $row["new"];
  3012. }
  3013. }
  3014. }
  3015. }
  3016. return $folders;
  3017. }
  3018. /**
  3019. * Compute the number of private messages a user has
  3020. * and return both the total and the number unread.
  3021. *
  3022. * @param mixed $folder - The folder to use. Either a special folder
  3023. * (PHORUM_PM_INBOX or PHORUM_PM_OUTBOX), the
  3024. * id of a user's custom folder or
  3025. * PHORUM_PM_ALLFOLDERS for all folders.
  3026. * @param int $user_id - The user to retrieve messages for or NULL
  3027. * to use the current user (default).
  3028. *
  3029. * @return array
  3030. */
  3031. function phorum_db_pm_messagecount($folder, $user_id = NULL)
  3032. {
  3033. $PHORUM = $GLOBALS["PHORUM"];
  3034. $conn = phorum_db_mysql_connect();
  3035. if ($user_id == NULL) $user_id = $PHORUM['user']['user_id'];
  3036. settype($user_id, "int");
  3037. if (is_numeric($folder)) {
  3038. $folder_sql = "pm_folder_id=$folder AND";
  3039. } elseif ($folder == PHORUM_PM_INBOX || $folder == PHORUM_PM_OUTBOX) {
  3040. $folder_sql = "pm_folder_id=0 AND special_folder='$folder' AND";
  3041. } elseif ($folder == PHORUM_PM_ALLFOLDERS) {
  3042. $folder_sql = '';
  3043. } else {
  3044. die ("Illegal folder '$folder' requested for user id '$user_id'");
  3045. }
  3046. $sql = "SELECT count(*) as total, (count(*) - sum(read_flag)) as new " .
  3047. "FROM {$PHORUM['pm_xref_table']} " .
  3048. "WHERE $folder_sql user_id = $user_id";
  3049. $messagecount=array("total" => 0, "new" => 0);
  3050. $res = mysql_query($sql, $conn);
  3051. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  3052. if (mysql_num_rows($res) > 0){
  3053. $row = mysql_fetch_assoc($res);
  3054. $messagecount["total"] = $row["total"];
  3055. $messagecount["new"] = ($row["new"] >= 1) ? $row["new"] : 0;
  3056. }
  3057. return $messagecount;
  3058. }
  3059. /**
  3060. * Check if the user has new private messages.
  3061. * This is useful in case you only want to know whether the user has
  3062. * new messages or not and when you are not interested in the exact amount
  3063. * of new messages.
  3064. *
  3065. * @param int $user_id - The user to retrieve messages for or NULL
  3066. * to use the current user (default).
  3067. * @return boolean
  3068. * A true value, in case there are new messages available.
  3069. */
  3070. function phorum_db_pm_checknew($user_id = NULL)
  3071. {
  3072. $PHORUM = $GLOBALS["PHORUM"];
  3073. $conn = phorum_db_mysql_connect();
  3074. if ($user_id == NULL) $user_id = $PHORUM['user']['user_id'];
  3075. settype($user_id, "int");
  3076. $sql = "SELECT user_id " .
  3077. "FROM {$PHORUM['pm_xref_table']} " .
  3078. "WHERE user_id = $user_id AND read_flag = 0 LIMIT 1";
  3079. $res = mysql_query($sql, $conn);
  3080. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  3081. return mysql_num_rows($res);
  3082. }
  3083. /**
  3084. * Insert a private message in the database. The return value
  3085. * is the pm_message_id of the created message.
  3086. *
  3087. * @param string $subject - The subject for the private message.
  3088. * @param string $message - The message text for the private message.
  3089. * @param mixed $to - A single user_id or an array of user_ids for the recipients.
  3090. * @param int $from - The user_id of the sender. The current user is used in case
  3091. * the parameter is set to NULL (default).
  3092. * @param boolean $keepcopy - If set to a true value, a copy of the mail will be put in
  3093. * the outbox of the user. Default value is false.
  3094. *
  3095. * @return int
  3096. */
  3097. function phorum_db_pm_send($subject, $message, $to, $from=NULL, $keepcopy=false)
  3098. {
  3099. $PHORUM = $GLOBALS["PHORUM"];
  3100. $conn = phorum_db_mysql_connect();
  3101. // Prepare the sender.
  3102. if ($from == NULL) $from = $PHORUM['user']['user_id'];
  3103. settype($from, "int");
  3104. $fromuser = phorum_db_user_get($from, false);
  3105. if (! $fromuser) die("Unknown sender user_id '$from'");
  3106. // This array will be filled with xref database entries.
  3107. $xref_entries = array();
  3108. // Prepare the list of recipients.
  3109. $rcpts = array();
  3110. if (! is_array($to)) $to = array($to);
  3111. foreach ($to as $user_id) {
  3112. settype($user_id, "int");
  3113. $user = phorum_db_user_get($user_id, false);
  3114. if (! $user) die("Unknown recipient user_id '$user_id'");
  3115. $rcpts[$user_id] = array(
  3116. 'user_id' => $user_id,
  3117. 'username' => $user["username"],
  3118. 'read_flag' => 0,
  3119. );
  3120. $xref_entries[] = array(
  3121. 'user_id' => $user_id,
  3122. 'pm_folder_id' => 0,
  3123. 'special_folder' => PHORUM_PM_INBOX,
  3124. 'read_flag' => 0,
  3125. );
  3126. }
  3127. // Keep copy of this message in outbox?
  3128. if ($keepcopy) {
  3129. $xref_entries[] = array(
  3130. 'user_id' => $from,
  3131. 'pm_folder_id' => 0,
  3132. 'special_folder' => PHORUM_PM_OUTBOX,
  3133. 'read_flag' => 1,
  3134. );
  3135. }
  3136. // Prepare message meta data.
  3137. $meta = mysql_escape_string(serialize(array(
  3138. 'recipients' => $rcpts
  3139. )));
  3140. // Create the message.
  3141. $sql = "INSERT INTO {$PHORUM["pm_messages_table"]} SET " .
  3142. "from_user_id = $from, " .
  3143. "from_username = '".mysql_escape_string($fromuser["username"])."', " .
  3144. "subject = '".mysql_escape_string($subject)."', " .
  3145. "message = '".mysql_escape_string($message)."', " .
  3146. "datestamp = '".time()."', " .
  3147. "meta = '$meta'";
  3148. mysql_query($sql, $conn);
  3149. if ($err = mysql_error()) {
  3150. phorum_db_mysql_error("$err: $sql");
  3151. return;
  3152. }
  3153. // Get the message id.
  3154. $pm_message_id = mysql_insert_id($conn);
  3155. // Put the message in the recipient inboxes.
  3156. foreach ($xref_entries as $xref) {
  3157. $sql = "INSERT INTO {$PHORUM["pm_xref_table"]} SET " .
  3158. "user_id = {$xref["user_id"]}, " .
  3159. "pm_folder_id={$xref["pm_folder_id"]}, " .
  3160. "special_folder='{$xref["special_folder"]}', " .
  3161. "pm_message_id=$pm_message_id, " .
  3162. "read_flag = {$xref["read_flag"]}, " .
  3163. "reply_flag = 0";
  3164. mysql_query($sql, $conn);
  3165. if ($err = mysql_error()) {
  3166. phorum_db_mysql_error("$err: $sql");
  3167. return;
  3168. }
  3169. }
  3170. return $pm_message_id;
  3171. }
  3172. /**
  3173. * Update a flag for a private message.
  3174. *
  3175. * @param int $pm_id - The id of the message to update.
  3176. * @param int $flag - The flag to update. Options are PHORUM_PM_READ_FLAG
  3177. * and PHORUM_PM_REPLY_FLAG.
  3178. * @param boolean $value - The value for the flag (true or false).
  3179. * @param int $user_id - The user to set a flag for or NULL
  3180. * to use the current user (default).
  3181. *
  3182. * @return boolean
  3183. */
  3184. function phorum_db_pm_setflag($pm_id, $flag, $value, $user_id = NULL)
  3185. {
  3186. $PHORUM = $GLOBALS["PHORUM"];
  3187. $conn = phorum_db_mysql_connect();
  3188. settype($pm_id, "int");
  3189. if ($flag != PHORUM_PM_READ_FLAG && $flag != PHORUM_PM_REPLY_FLAG) {
  3190. trigger_error("Invalid value for \$flag in function phorum_db_pm_setflag(): $flag", E_USER_WARNING);
  3191. return 0;
  3192. }
  3193. $value = $value ? 1 : 0;
  3194. if ($user_id == NULL) $user_id = $PHORUM['user']['user_id'];
  3195. settype($user_id, "int");
  3196. // Update the flag in the database.
  3197. $sql = "UPDATE {$PHORUM["pm_xref_table"]} " .
  3198. "SET $flag = $value " .
  3199. "WHERE pm_message_id = $pm_id AND user_id = $user_id";
  3200. $res = mysql_query($sql, $conn);
  3201. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  3202. // Update message counters.
  3203. if ($flag == PHORUM_PM_READ_FLAG) {
  3204. phorum_db_pm_update_message_info($pm_id);
  3205. }
  3206. return $res;
  3207. }
  3208. /**
  3209. * Delete a private message from a folder.
  3210. *
  3211. * @param int $pm_id - The id of the private message to delete
  3212. * @param string $folder - The folder from which to delete the message
  3213. * @param int $user_id - The user to delete the message for or NULL
  3214. * to use the current user (default).
  3215. *
  3216. * @return boolean
  3217. */
  3218. function phorum_db_pm_delete($pm_id, $folder, $user_id = NULL)
  3219. {
  3220. $PHORUM = $GLOBALS["PHORUM"];
  3221. $conn = phorum_db_mysql_connect();
  3222. settype($pm_id, "int");
  3223. if ($user_id == NULL) $user_id = $PHORUM['user']['user_id'];
  3224. settype($user_id, "int");
  3225. if (is_numeric($folder)) {
  3226. $folder_sql = "pm_folder_id=$folder AND";
  3227. } elseif ($folder == PHORUM_PM_INBOX || $folder == PHORUM_PM_OUTBOX) {
  3228. $folder_sql = "pm_folder_id=0 AND special_folder='$folder' AND";
  3229. } else {
  3230. die ("Illegal folder '$folder' requested for user id '$user_id'");
  3231. }
  3232. $sql = "DELETE FROM {$PHORUM["pm_xref_table"]} " .
  3233. "WHERE $folder_sql " .
  3234. "user_id = $user_id AND pm_message_id = $pm_id";
  3235. $res = mysql_query($sql, $conn);
  3236. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  3237. // Update message counters.
  3238. phorum_db_pm_update_message_info($pm_id);
  3239. return $res;
  3240. }
  3241. /**
  3242. * Move a private message to a different folder.
  3243. *
  3244. * @param int $pm_id - The id of the private message to move.
  3245. * @param int $from - The folder to move the message from.
  3246. * @param int $to - The folder to move the message to.
  3247. * @param int $user_id - The user to move the message for or NULL
  3248. * to use the current user (default).
  3249. *
  3250. * @return boolean
  3251. */
  3252. function phorum_db_pm_move($pm_id, $from, $to, $user_id = NULL)
  3253. {
  3254. $PHORUM = $GLOBALS["PHORUM"];
  3255. $conn = phorum_db_mysql_connect();
  3256. settype($pm_id, "int");
  3257. if ($user_id == NULL) $user_id = $PHORUM['user']['user_id'];
  3258. settype($user_id, "int");
  3259. if (is_numeric($from)) {
  3260. $folder_sql = "pm_folder_id=$from AND";
  3261. } elseif ($from == PHORUM_PM_INBOX || $from == PHORUM_PM_OUTBOX) {
  3262. $folder_sql = "pm_folder_id=0 AND special_folder='$from' AND";
  3263. } else {
  3264. die ("Illegal source folder '$from' specified");
  3265. }
  3266. if (is_numeric($to)) {
  3267. $pm_folder_id = $to;
  3268. $special_folder = 'NULL';
  3269. } elseif ($to == PHORUM_PM_INBOX || $to == PHORUM_PM_OUTBOX) {
  3270. $pm_folder_id = 0;
  3271. $special_folder = "'$to'";
  3272. } else {
  3273. die ("Illegal target folder '$to' specified");
  3274. }
  3275. $sql = "UPDATE {$PHORUM["pm_xref_table"]} SET " .
  3276. "pm_folder_id = $pm_folder_id, " .
  3277. "special_folder = $special_folder " .
  3278. "WHERE $folder_sql user_id = $user_id AND pm_message_id = $pm_id";
  3279. $res = mysql_query($sql, $conn);
  3280. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  3281. return $res;
  3282. }
  3283. /**
  3284. * Update the meta information for a message. If we
  3285. * detect that no xrefs are available for the message anymore,
  3286. * the message will be deleted from the database. So this function
  3287. * has to be called after setting the read_flag and after deleting
  3288. * a message.
  3289. * PMTODO maybe we need some locking here to prevent concurrent
  3290. * updates of the message info.
  3291. *
  3292. * @param int $pm_id
  3293. *
  3294. * @return boolean
  3295. */
  3296. function phorum_db_pm_update_message_info($pm_id)
  3297. {
  3298. $PHORUM = $GLOBALS['PHORUM'];
  3299. $conn = phorum_db_mysql_connect();
  3300. settype($pm_id, "int");
  3301. // Find the message record. Return immediately if no message is found.
  3302. $sql = "SELECT * " .
  3303. "FROM {$PHORUM['pm_messages_table']} " .
  3304. "WHERE pm_message_id = $pm_id";
  3305. $res = mysql_query($sql, $conn);
  3306. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  3307. if (mysql_num_rows($res) == 0) return $res;
  3308. $pm = mysql_fetch_assoc($res);
  3309. // Find the xrefs for this message.
  3310. $sql = "SELECT * " .
  3311. "FROM {$PHORUM["pm_xref_table"]} " .
  3312. "WHERE pm_message_id = $pm_id";
  3313. $res = mysql_query($sql, $conn);
  3314. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  3315. // No xrefs left? Then the message can be fully deleted.
  3316. if (mysql_num_rows($res) == 0) {
  3317. $sql = "DELETE FROM {$PHORUM['pm_messages_table']} " .
  3318. "WHERE pm_message_id = $pm_id";
  3319. $res = mysql_query($sql, $conn);
  3320. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  3321. return $res;
  3322. }
  3323. // Update the read flags for the recipients in the meta data.
  3324. $meta = unserialize($pm["meta"]);
  3325. $rcpts = $meta["recipients"];
  3326. while ($row = mysql_fetch_assoc($res)) {
  3327. // Only update if available. A kept copy in the outbox will
  3328. // not be in the meta list, so if the copy is read, the
  3329. // meta data does not have to be updated here.
  3330. if (isset($rcpts[$row["user_id"]])) {
  3331. $rcpts[$row["user_id"]]["read_flag"] = $row["read_flag"];
  3332. }
  3333. }
  3334. $meta["recipients"] = $rcpts;
  3335. // Store the new meta data.
  3336. $meta = mysql_escape_string(serialize($meta));
  3337. $sql = "UPDATE {$PHORUM['pm_messages_table']} " .
  3338. "SET meta = '$meta' " .
  3339. "WHERE pm_message_id = $pm_id";
  3340. $res = mysql_query($sql, $conn);
  3341. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  3342. return $res;
  3343. }
  3344. /* Take care of warning about deprecation of the old PM API functions. */
  3345. function phorum_db_get_private_messages($arg1, $arg2) {
  3346. phorum_db_pm_deprecated('phorum_db_get_private_messages'); }
  3347. function phorum_db_get_private_message($arg1) {
  3348. phorum_db_pm_deprecated('phorum_db_get_private_message'); }
  3349. function phorum_db_get_private_message_count($arg1) {
  3350. phorum_db_pm_deprecated('phorum_db_get_private_message_count'); }
  3351. function phorum_db_put_private_messages($arg1, $arg2, $arg3, $arg4, $arg5) {
  3352. phorum_db_pm_deprecated('phorum_db_put_private_messages'); }
  3353. function phorum_db_update_private_message($arg1, $arg2, $arg3){
  3354. phorum_db_pm_deprecated('phorum_db_update_private_message'); }
  3355. function phorum_db_pm_deprecated($func) {
  3356. die("${func}() has been deprecated. Please use the new private message API.");
  3357. }
  3358. /**
  3359. * Check if a certain user is buddy of another user.
  3360. * The function return the pm_buddy_id in case the user is a buddy
  3361. * or NULL in case the user isn't.
  3362. *
  3363. * @param int $buddy_user_id - The user_id to check for if it's a buddy.
  3364. * @param int $user_id - The user_id for which the buddy list must be
  3365. * checked or NULL to use the current user (default).
  3366. *
  3367. * @return boolean
  3368. */
  3369. function phorum_db_pm_is_buddy($buddy_user_id, $user_id = NULL)
  3370. {
  3371. $PHORUM = $GLOBALS['PHORUM'];
  3372. $conn = phorum_db_mysql_connect();
  3373. settype($buddyuser_id, "int");
  3374. if (is_null($user_id)) $user_id = $PHORUM["user"]["user_id"];
  3375. settype($user_id, "int");
  3376. $sql = "SELECT pm_buddy_id FROM {$PHORUM["pm_buddies_table"]} " .
  3377. "WHERE user_id = $user_id AND buddy_user_id = $buddy_user_id";
  3378. $res = mysql_query($sql, $conn);
  3379. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  3380. if (mysql_num_rows($res)) {
  3381. $row = mysql_fetch_array($res);
  3382. return $row[0];
  3383. } else {
  3384. return NULL;
  3385. }
  3386. }
  3387. /**
  3388. * Add a buddy for a user. It will return the
  3389. * pm_buddy_id for the new buddy. If the buddy already exists,
  3390. * it will return the existing pm_buddy_id. If a non-existant
  3391. * user_id is used for the buddy_user_id, the function will
  3392. * return NULL.
  3393. *
  3394. * @param int $buddy_user_id - The user_id that has to be added as a buddy.
  3395. * @param int $user_id - The user_id the buddy has to be added for or
  3396. * NULL to use the current user (default).
  3397. *
  3398. * @return mixed
  3399. */
  3400. function phorum_db_pm_buddy_add($buddy_user_id, $user_id = NULL)
  3401. {
  3402. $PHORUM = $GLOBALS['PHORUM'];
  3403. $conn = phorum_db_mysql_connect();
  3404. settype($buddyuser_id, "int");
  3405. if (is_null($user_id)) $user_id = $PHORUM["user"]["user_id"];
  3406. settype($user_id, "int");
  3407. // Check if the buddy_user_id is a valid user_id.
  3408. $valid = phorum_db_user_get($buddy_user_id, false);
  3409. if (! $valid) return NULL;
  3410. $pm_buddy_id = phorum_db_pm_is_buddy($buddy_user_id);
  3411. if (is_null($pm_buddy_id)) {
  3412. $sql = "INSERT INTO {$PHORUM["pm_buddies_table"]} SET " .
  3413. "user_id = $user_id, " .
  3414. "buddy_user_id = $buddy_user_id";
  3415. $res = mysql_query($sql, $conn);
  3416. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  3417. $pm_buddy_id = mysql_insert_id($conn);
  3418. }
  3419. return $pm_buddy_id;
  3420. }
  3421. /**
  3422. * Delete a buddy for a user.
  3423. *
  3424. * @param int $buddy_user_id - The user_id that has to be deleted as a buddy.
  3425. * @param int $user_id - The user_id the buddy has to be delete for or
  3426. * NULL to use the current user (default).
  3427. *
  3428. * @return boolean
  3429. */
  3430. function phorum_db_pm_buddy_delete($buddy_user_id, $user_id = NULL)
  3431. {
  3432. $PHORUM = $GLOBALS['PHORUM'];
  3433. $conn = phorum_db_mysql_connect();
  3434. settype($buddyuser_id, "int");
  3435. if (is_null($user_id)) $user_id = $PHORUM["user"]["user_id"];
  3436. settype($user_id, "int");
  3437. $sql = "DELETE FROM {$PHORUM["pm_buddies_table"]} WHERE " .
  3438. "buddy_user_id = $buddy_user_id AND user_id = $user_id";
  3439. $res = mysql_query($sql, $conn);
  3440. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  3441. return $res;
  3442. }
  3443. /**
  3444. * Retrieve a list of buddies for a user.
  3445. *
  3446. * @param int $user_id - The user_id for which to retrieve the buddies
  3447. * or NULL to user the current user (default).
  3448. * @param boolean $find_mutual - Wheter to find mutual buddies or not (default not).
  3449. *
  3450. * @return array
  3451. */
  3452. function phorum_db_pm_buddy_list($user_id = NULL, $find_mutual = false)
  3453. {
  3454. $PHORUM = $GLOBALS['PHORUM'];
  3455. $conn = phorum_db_mysql_connect();
  3456. if (is_null($user_id)) $user_id = $PHORUM["user"]["user_id"];
  3457. settype($user_id, "int");
  3458. // Get all buddies for this user.
  3459. $sql = "SELECT buddy_user_id FROM {$PHORUM["pm_buddies_table"]} " .
  3460. "WHERE user_id = $user_id";
  3461. $res = mysql_query($sql, $conn);
  3462. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  3463. $buddies = array();
  3464. if (mysql_num_rows($res)) {
  3465. while ($row = mysql_fetch_array($res)) {
  3466. $buddies[$row[0]] = array (
  3467. 'user_id' => $row[0]
  3468. );
  3469. }
  3470. }
  3471. // If we do not have to lookup mutual buddies, we're done.
  3472. if (! $find_mutual) return $buddies;
  3473. // Initialize mutual buddy value.
  3474. foreach ($buddies as $id => $data) {
  3475. $buddies[$id]["mutual"] = false;
  3476. }
  3477. // Get all mutual buddies.
  3478. $sql = "SELECT DISTINCT a.buddy_user_id " .
  3479. "FROM {$PHORUM["pm_buddies_table"]} as a, {$PHORUM["pm_buddies_table"]} as b " .
  3480. "WHERE a.user_id=$user_id " .
  3481. "AND b.user_id=a.buddy_user_id " .
  3482. "AND b.buddy_user_id=$user_id";
  3483. $res = mysql_query($sql, $conn);
  3484. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  3485. if (mysql_num_rows($res)) {
  3486. while ($row = mysql_fetch_array($res)) {
  3487. $buddies[$row[0]]["mutual"] = true;
  3488. }
  3489. }
  3490. return $buddies;
  3491. }
  3492. /**
  3493. * Delete old messages.
  3494. *
  3495. * @param timestamp $time - holds the timestamp the comparison is done against
  3496. * @param int $forum - delete threads from this forum
  3497. * @param int $mode - should we compare against datestamp (1) or modifystamp (2)
  3498. *
  3499. * @return int
  3500. */
  3501. function phorum_db_prune_oldThreads($time,$forum=0,$mode=1) {
  3502. $PHORUM = $GLOBALS['PHORUM'];
  3503. $conn = phorum_db_mysql_connect();
  3504. $numdeleted=0;
  3505. $compare_field = "datestamp";
  3506. if($mode == 2) {
  3507. $compare_field = "modifystamp";
  3508. }
  3509. $forummode="";
  3510. if($forum > 0) {
  3511. $forummode=" AND forum_id = $forum";
  3512. }
  3513. // retrieving which threads to delete
  3514. $sql = "select thread from {$PHORUM['message_table']} where $compare_field < $time AND parent_id=0 $forummode";
  3515. $res = mysql_query($sql, $conn);
  3516. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  3517. $ret=array();
  3518. while($row=mysql_fetch_row($res)) {
  3519. $ret[]=$row[0];
  3520. }
  3521. $thread_ids=implode(",",$ret);
  3522. if(count($ret)) {
  3523. // deleting the messages/threads
  3524. $sql="delete from {$PHORUM['message_table']} where thread IN ($thread_ids)";
  3525. $res = mysql_query($sql, $conn);
  3526. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  3527. $numdeleted = mysql_affected_rows($conn);
  3528. if($numdeleted < 0) {
  3529. $numdeleted=0;
  3530. }
  3531. // deleting the associated notification-entries
  3532. $sql="delete from {$PHORUM['subscribers_table']} where thread IN ($thread_ids)";
  3533. $res = mysql_query($sql, $conn);
  3534. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  3535. // optimizing the message-table
  3536. $sql="optimize table {$PHORUM['message_table']}";
  3537. $res = mysql_query($sql, $conn);
  3538. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  3539. }
  3540. return $numdeleted;
  3541. }
  3542. /**
  3543. * Split a thread.
  3544. *
  3545. * @param int $message
  3546. * @param int $forum_id
  3547. *
  3548. * @return void
  3549. */
  3550. function phorum_db_split_thread($message, $forum_id)
  3551. {
  3552. settype($message, "int");
  3553. settype($forum_id, "int");
  3554. if($message > 0 && $forum_id > 0){
  3555. // get message tree for update thread id
  3556. $tree =phorum_db_get_messagetree($message, $forum_id);
  3557. $queries =array();
  3558. $queries[0]="UPDATE {$GLOBALS['PHORUM']['message_table']} SET thread='$message', parent_id='0' WHERE message_id ='$message'";
  3559. $queries[1]="UPDATE {$GLOBALS['PHORUM']['message_table']} SET thread='$message' WHERE message_id IN ($tree)";
  3560. phorum_db_run_queries($queries);
  3561. }
  3562. }
  3563. /**
  3564. * Returns the maximum message-id in the database.
  3565. * @return int
  3566. */
  3567. function phorum_db_get_max_messageid() {
  3568. $PHORUM = $GLOBALS["PHORUM"];
  3569. $conn = phorum_db_mysql_connect();
  3570. $maxid = 0;
  3571. $sql="SELECT max(message_id) from ".$PHORUM["message_table"];
  3572. $res = mysql_query($sql, $conn);
  3573. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  3574. if (mysql_num_rows($res) > 0){
  3575. $row = mysql_fetch_row($res);
  3576. $maxid = $row[0];
  3577. }
  3578. return $maxid;
  3579. }
  3580. /**
  3581. * Increments the viewcount for a post.
  3582. *
  3583. * @param int $message_id
  3584. *
  3585. * @return boolean
  3586. */
  3587. function phorum_db_viewcount_inc($message_id) {
  3588. if($message_id < 1 || !is_numeric($message_id)) {
  3589. return false;
  3590. }
  3591. $conn = phorum_db_mysql_connect();
  3592. $sql="UPDATE ".$GLOBALS['PHORUM']['message_table']." SET viewcount=viewcount+1 WHERE message_id=$message_id";
  3593. $res = mysql_query($sql, $conn);
  3594. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  3595. return true;
  3596. }
  3597. /**
  3598. * Find users that have a certain string in one of the custom fields.
  3599. *
  3600. * @param int $field_id
  3601. * The custom field to search.
  3602. * @param string $field_content
  3603. * The string to search for.
  3604. * @param boolean $match
  3605. * If FALSE, the $field_content must match exactly,
  3606. * if TRUE, the $field_content can be a substring of the custom field.
  3607. * @return mixed
  3608. * Return an array of users if any matched, or NULL if there were no
  3609. * matches.
  3610. */
  3611. function phorum_db_get_custom_field_users($field_id,$field_content,$match) {
  3612. $field_id=(int)$field_id;
  3613. $field_content=mysql_real_escape_string($field_content);
  3614. $conn = phorum_db_mysql_connect();
  3615. if($match) {
  3616. $compval="LIKE";
  3617. } else {
  3618. $compval="=";
  3619. }
  3620. $sql = "select user_id from {$GLOBALS['PHORUM']['user_custom_fields_table']} where type=$field_id and data $compval '$field_content'";
  3621. $res = mysql_query($sql, $conn);
  3622. if ($err = mysql_error()) phorum_db_mysql_error("$err: $sql");
  3623. if(mysql_num_rows($res)) {
  3624. $retval=array();
  3625. while ($row = mysql_fetch_row($res)){
  3626. $retval[$row[0]]=$row[0];
  3627. }
  3628. } else {
  3629. $retval=NULL;
  3630. }
  3631. return $retval;
  3632. }
  3633. /**
  3634. * Create the tables needed in the database.
  3635. * @return string
  3636. * Return the empty string on success, error message on failure.
  3637. */
  3638. function phorum_db_create_tables()
  3639. {
  3640. $PHORUM = $GLOBALS["PHORUM"];
  3641. $conn = phorum_db_mysql_connect();
  3642. $retmsg = "";
  3643. $queries = array(
  3644. // create tables
  3645. "CREATE TABLE {$PHORUM['forums_table']} ( forum_id int(10) unsigned NOT NULL auto_increment, name varchar(50) NOT NULL default '', active smallint(6) NOT NULL default '0', description text NOT NULL default '', template varchar(50) NOT NULL default '', folder_flag tinyint(1) NOT NULL default '0', parent_id int(10) unsigned NOT NULL default '0', list_length_flat int(10) unsigned NOT NULL default '0', list_length_threaded int(10) unsigned NOT NULL default '0', moderation int(10) unsigned NOT NULL default '0', threaded_list tinyint(4) NOT NULL default '0', threaded_read tinyint(4) NOT NULL default '0', float_to_top tinyint(4) NOT NULL default '0', check_duplicate tinyint(4) NOT NULL default '0', allow_attachment_types varchar(100) NOT NULL default '', max_attachment_size int(10) unsigned NOT NULL default '0', max_totalattachment_size int(10) unsigned NOT NULL default '0', max_attachments int(10) unsigned NOT NULL default '0', pub_perms int(10) unsigned NOT NULL default '0', reg_perms int(10) unsigned NOT NULL default '0', display_ip_address smallint(5) unsigned NOT NULL default '1', allow_email_notify smallint(5) unsigned NOT NULL default '1', language varchar(100) NOT NULL default 'english', email_moderators tinyint(1) NOT NULL default '0', message_count int(10) unsigned NOT NULL default '0', sticky_count int(10) unsigned NOT NULL default '0', thread_count int(10) unsigned NOT NULL default '0', last_post_time int(10) unsigned NOT NULL default '0', display_order int(10) unsigned NOT NULL default '0', read_length int(10) unsigned NOT NULL default '0', vroot int(10) unsigned NOT NULL default '0', edit_post tinyint(1) NOT NULL default '1',template_settings text NOT NULL default '', count_views tinyint(1) unsigned NOT NULL default '0', display_fixed tinyint(1) unsigned NOT NULL default '0', reverse_threading tinyint(1) NOT NULL default '0',inherit_id int(10) unsigned NULL default NULL, PRIMARY KEY (forum_id), KEY name (name), KEY active (active,parent_id), KEY group_id (parent_id)) TYPE=MyISAM",
  3646. "CREATE TABLE {$PHORUM['message_table']} ( message_id int(10) unsigned NOT NULL auto_increment, forum_id int(10) unsigned NOT NULL default '0', thread int(10) unsigned NOT NULL default '0', parent_id int(10) unsigned NOT NULL default '0', author varchar(37) NOT NULL default '', subject varchar(255) NOT NULL default '', body text NOT NULL, email varchar(100) NOT NULL default '', ip varchar(255) NOT NULL default '', status tinyint(4) NOT NULL default '2', msgid varchar(100) NOT NULL default '', modifystamp int(10) unsigned NOT NULL default '0', user_id int(10) unsigned NOT NULL default '0', thread_count int(10) unsigned NOT NULL default '0', moderator_post tinyint(3) unsigned NOT NULL default '0', sort tinyint(4) NOT NULL default '2', datestamp int(10) unsigned NOT NULL default '0', meta mediumtext NOT NULL, viewcount int(10) unsigned NOT NULL default '0', closed tinyint(4) NOT NULL default '0', PRIMARY KEY (message_id), KEY thread_message (thread,message_id), KEY thread_forum (thread,forum_id), KEY special_threads (sort,forum_id), KEY status_forum (status,forum_id), KEY list_page_float (forum_id,parent_id,modifystamp), KEY list_page_flat (forum_id,parent_id,thread), KEY post_count (forum_id,status,parent_id), KEY dup_check (forum_id,author,subject,datestamp), KEY forum_max_message (forum_id,message_id,status,parent_id), KEY last_post_time (forum_id,status,modifystamp), KEY next_prev_thread (forum_id,status,thread), KEY user_id (user_id) ) TYPE=MyISAM",
  3647. "CREATE TABLE {$PHORUM['settings_table']} ( name varchar(255) NOT NULL default '', type enum('V','S') NOT NULL default 'V', data text NOT NULL, PRIMARY KEY (name)) TYPE=MyISAM",
  3648. "CREATE TABLE {$PHORUM['subscribers_table']} ( user_id int(10) unsigned NOT NULL default '0', forum_id int(10) unsigned NOT NULL default '0', sub_type int(10) unsigned NOT NULL default '0', thread int(10) unsigned NOT NULL default '0', PRIMARY KEY (user_id,forum_id,thread), KEY forum_id (forum_id,thread,sub_type)) TYPE=MyISAM",
  3649. "CREATE TABLE {$PHORUM['user_permissions_table']} ( user_id int(10) unsigned NOT NULL default '0', forum_id int(10) unsigned NOT NULL default '0', permission int(10) unsigned NOT NULL default '0', PRIMARY KEY (user_id,forum_id), KEY forum_id (forum_id,permission) ) TYPE=MyISAM",
  3650. "CREATE TABLE {$PHORUM['user_table']} ( user_id int(10) unsigned NOT NULL auto_increment, username varchar(50) NOT NULL default '', password varchar(50) NOT NULL default '',cookie_sessid_lt varchar(50) NOT NULL default '', sessid_st varchar(50) NOT NULL default '', sessid_st_timeout int(10) unsigned NOT NULL default 0, password_temp varchar(50) NOT NULL default '', email varchar(100) NOT NULL default '', email_temp varchar(110) NOT NULL default '', hide_email tinyint(1) NOT NULL default '0', active tinyint(1) NOT NULL default '0', user_data text NOT NULL default '', signature text NOT NULL default '', threaded_list tinyint(4) NOT NULL default '0', posts int(10) NOT NULL default '0', admin tinyint(1) NOT NULL default '0', threaded_read tinyint(4) NOT NULL default '0', date_added int(10) unsigned NOT NULL default '0', date_last_active int(10) unsigned NOT NULL default '0', last_active_forum int(10) unsigned NOT NULL default '0', hide_activity tinyint(1) NOT NULL default '0',show_signature TINYINT( 1 ) DEFAULT '0' NOT NULL, email_notify TINYINT( 1 ) DEFAULT '0' NOT NULL, pm_email_notify TINYINT ( 1 ) DEFAULT '1' NOT NULL, tz_offset TINYINT( 2 ) DEFAULT '-99' NOT NULL,is_dst TINYINT( 1 ) DEFAULT '0' NOT NULL ,user_language VARCHAR( 100 ) NOT NULL default '',user_template VARCHAR( 100 ) NOT NULL default '', moderator_data text NOT NULL default '', moderation_email tinyint(2) unsigned not null default 1, PRIMARY KEY (user_id), UNIQUE KEY username (username), KEY active (active), KEY userpass (username,password), KEY sessid_st (sessid_st), KEY cookie_sessid_lt (cookie_sessid_lt), KEY activity (date_last_active,hide_activity,last_active_forum), KEY date_added (date_added), KEY email_temp (email_temp) ) TYPE=MyISAM",
  3651. "CREATE TABLE {$PHORUM['user_newflags_table']} ( user_id int(11) NOT NULL default '0', forum_id int(11) NOT NULL default '0', message_id int(11) NOT NULL default '0', PRIMARY KEY (user_id,forum_id,message_id) ) TYPE=MyISAM",
  3652. "CREATE TABLE {$PHORUM['groups_table']} ( group_id int(11) NOT NULL auto_increment, name varchar(255) NOT NULL default '0', open tinyint(3) NOT NULL default '0', PRIMARY KEY (group_id) ) TYPE=MyISAM",
  3653. "CREATE TABLE {$PHORUM['forum_group_xref_table']} ( forum_id int(11) NOT NULL default '0', group_id int(11) NOT NULL default '0', permission int(10) unsigned NOT NULL default '0', PRIMARY KEY (forum_id,group_id) ) TYPE=MyISAM",
  3654. "CREATE TABLE {$PHORUM['user_group_xref_table']} ( user_id int(11) NOT NULL default '0', group_id int(11) NOT NULL default '0', status tinyint(3) NOT NULL default '1', PRIMARY KEY (user_id,group_id) ) TYPE=MyISAM",
  3655. "CREATE TABLE {$PHORUM['files_table']} ( file_id int(11) NOT NULL auto_increment, user_id int(11) NOT NULL default '0', filename varchar(255) NOT NULL default '', filesize int(11) NOT NULL default '0', file_data mediumtext NOT NULL default '', add_datetime int(10) unsigned NOT NULL default '0', message_id int(10) unsigned NOT NULL default '0', link varchar(10) NOT NULL default '', PRIMARY KEY (file_id), KEY add_datetime (add_datetime), KEY message_id_link (message_id,link)) TYPE=MyISAM",
  3656. "CREATE TABLE {$PHORUM['banlist_table']} ( id int(11) NOT NULL auto_increment, forum_id int(11) NOT NULL default '0', type tinyint(4) NOT NULL default '0', pcre tinyint(4) NOT NULL default '0', string varchar(255) NOT NULL default '', PRIMARY KEY (id), KEY forum_id (forum_id)) TYPE=MyISAM",
  3657. "CREATE TABLE {$PHORUM['search_table']} ( message_id int(10) unsigned NOT NULL default '0', forum_id int(10) unsigned NOT NULL default '0',search_text mediumtext NOT NULL default '', PRIMARY KEY (message_id), KEY forum_id (forum_id), FULLTEXT KEY search_text (search_text) ) TYPE=MyISAM",
  3658. "CREATE TABLE {$PHORUM['user_custom_fields_table']} ( user_id INT DEFAULT '0' NOT NULL , type INT DEFAULT '0' NOT NULL , data TEXT NOT NULL default '', PRIMARY KEY ( user_id , type )) TYPE=MyISAM",
  3659. "CREATE TABLE {$PHORUM['pm_messages_table']} ( pm_message_id int(10) unsigned NOT NULL auto_increment, from_user_id int(10) unsigned NOT NULL default '0', from_username varchar(50) NOT NULL default '', subject varchar(100) NOT NULL default '', message text NOT NULL default '', datestamp int(10) unsigned NOT NULL default '0', meta mediumtext NOT NULL default '', PRIMARY KEY(pm_message_id)) TYPE=MyISAM",
  3660. "CREATE TABLE {$PHORUM['pm_folders_table']} ( pm_folder_id int(10) unsigned NOT NULL auto_increment, user_id int(10) unsigned NOT NULL default '0', foldername varchar(20) NOT NULL default '', PRIMARY KEY (pm_folder_id)) TYPE=MyISAM",
  3661. "CREATE TABLE {$PHORUM['pm_xref_table']} ( pm_xref_id int(10) unsigned NOT NULL auto_increment, user_id int(10) unsigned NOT NULL default '0', pm_folder_id int(10) unsigned NOT NULL default '0', special_folder varchar(10), pm_message_id int(10) unsigned NOT NULL default '0', read_flag tinyint(1) NOT NULL default '0', reply_flag tinyint(1) NOT NULL default '0', PRIMARY KEY (pm_xref_id), KEY xref (user_id,pm_folder_id,pm_message_id), KEY read_flag (read_flag)) TYPE=MyISAM",
  3662. "CREATE TABLE {$PHORUM['pm_buddies_table']} ( pm_buddy_id int(10) unsigned NOT NULL auto_increment, user_id int(10) unsigned NOT NULL default '0', buddy_user_id int(10) unsigned NOT NULL default '0', PRIMARY KEY pm_buddy_id (pm_buddy_id), UNIQUE KEY userids (user_id, buddy_user_id), KEY buddy_user_id (buddy_user_id)) TYPE=MyISAM",
  3663. );
  3664. foreach($queries as $sql){
  3665. $res = mysql_query($sql, $conn);
  3666. if ($err = mysql_error()){
  3667. $retmsg = "$err<br />";
  3668. phorum_db_mysql_error("$err: $sql");
  3669. break;
  3670. }
  3671. }
  3672. return $retmsg;
  3673. }
  3674. /**
  3675. * Uses the database-dependant functions to escape a string.
  3676. * @param string $str
  3677. * @return string
  3678. */
  3679. function phorum_db_escape_string($str) {
  3680. $str_tmp=mysql_real_escape_string($str);
  3681. return $str_tmp;
  3682. }
  3683. /**
  3684. * Execute an array of queries.
  3685. *
  3686. * @param array $queries
  3687. *
  3688. * @return string
  3689. */
  3690. function phorum_db_run_queries($queries){
  3691. $PHORUM = $GLOBALS["PHORUM"];
  3692. $conn = phorum_db_mysql_connect();
  3693. $retmsg = "";
  3694. foreach($queries as $sql){
  3695. $res = mysql_query($sql, $conn);
  3696. if ($err = mysql_error()){
  3697. // skip duplicate column name errors
  3698. if(!stristr($err, "duplicate column")){
  3699. $retmsg.= "$err<br />";
  3700. phorum_db_mysql_error("$err: $sql");
  3701. }
  3702. }
  3703. }
  3704. return $retmsg;
  3705. }
  3706. /**
  3707. * Checks that a database connection can be made.
  3708. *
  3709. * @return boolean
  3710. */
  3711. function phorum_db_check_connection(){
  3712. $conn = phorum_db_mysql_connect();
  3713. return ($conn > 0) ? true : false;
  3714. }
  3715. /**
  3716. * Handy little connection function. This allows us to not connect to the
  3717. * server until a query is actually run.
  3718. * NOTE: This is not a required part of abstraction
  3719. *
  3720. * @return resource
  3721. */
  3722. function phorum_db_mysql_connect(){
  3723. $PHORUM = $GLOBALS["PHORUM"];
  3724. static $conn;
  3725. if (empty($conn)){
  3726. $conn = mysql_connect($PHORUM["DBCONFIG"]["server"], $PHORUM["DBCONFIG"]["user"], $PHORUM["DBCONFIG"]["password"], true);
  3727. mysql_select_db($PHORUM["DBCONFIG"]["name"], $conn);
  3728. mysql_query("SET NAMES 'utf8'");
  3729. }
  3730. return $conn;
  3731. }
  3732. /**
  3733. * Error handling function.
  3734. * NOTE: This is not a required part of abstraction
  3735. *
  3736. * @param string $err
  3737. *
  3738. * @return void
  3739. */
  3740. function phorum_db_mysql_error($err){
  3741. if(isset($GLOBALS['PHORUM']['error_logging'])) {
  3742. $logsetting = $GLOBALS['PHORUM']['error_logging'];
  3743. } else {
  3744. $logsetting = "";
  3745. }
  3746. $adminemail = $GLOBALS['PHORUM']['system_email_from_address'];
  3747. $cache_dir = $GLOBALS['PHORUM']['cache'];
  3748. if (!defined("PHORUM_ADMIN")){
  3749. if($logsetting == 'mail') {
  3750. include_once("./include/email_functions.php");
  3751. $data=array('mailmessage'=>"An SQL-error occured in your phorum-installation.\n\nThe error-message was:\n$err\n\n",
  3752. 'mailsubject'=>'Phorum: an SQL-error occured');
  3753. phorum_email_user(array($adminemail),$data);
  3754. } elseif($logsetting == 'file') {
  3755. $fp = fopen($cache_dir."/phorum-sql-errors.log",'a');
  3756. fputs($fp,time().": $err\n");
  3757. fclose($fp);
  3758. } else {
  3759. echo htmlspecialchars($err);
  3760. }
  3761. exit();
  3762. }else{
  3763. echo "<!-- $err -->";
  3764. }
  3765. }
  3766. /**
  3767. * This function is used by the sanity checking system in the
  3768. * admin interface to determine how much data can be transferred
  3769. * in one query. This is used to detect problems with uploads that
  3770. * are larger than the database server can handle.
  3771. * The function returns the size in bytes. For database implementations
  3772. * which do not have this kind of limit, NULL can be returned.
  3773. *
  3774. * @return int
  3775. */
  3776. function phorum_db_maxpacketsize ()
  3777. {
  3778. $conn = phorum_db_mysql_connect();
  3779. $res = mysql_query("SELECT @@global.max_allowed_packet",$conn);
  3780. if (!$res) return NULL;
  3781. if (mysql_num_rows($res)) {
  3782. $row = mysql_fetch_array($res);
  3783. return $row[0];
  3784. }
  3785. return NULL;
  3786. }
  3787. /**
  3788. * This function is used by the sanity checking system to let the
  3789. * database layer do sanity checks of its own. This function can
  3790. * be used by every database layer to implement specific checks.
  3791. *
  3792. * The return value for this function should be exactly the same
  3793. * as the return value expected for regular sanity checking
  3794. * function (see include/admin/sanity_checks.php for information).
  3795. *
  3796. * There's no need to load the sanity_check.php file for the needed
  3797. * constants, because this function should only be called from the
  3798. * sanity checking system.
  3799. *
  3800. * @return array
  3801. */
  3802. function phorum_db_sanitychecks()
  3803. {
  3804. $PHORUM = $GLOBALS["PHORUM"];
  3805. // Retrieve the MySQL server version.
  3806. $conn = phorum_db_mysql_connect();
  3807. $res = mysql_query("SELECT @@global.version",$conn);
  3808. if (!$res) return array(
  3809. PHORUM_SANITY_WARN,
  3810. "The database layer could not retrieve the version of the
  3811. running MySQL server",
  3812. "This probably means that you are running a really old MySQL
  3813. server, which does not support \"SELECT @@global.version\"
  3814. as an SQL command. If you are not running a MySQL server
  3815. with version 4.0.18 or higher, then please upgrade your
  3816. MySQL server. Else, contact the Phorum developers to see
  3817. where this warning is coming from"
  3818. );
  3819. if (mysql_num_rows($res))
  3820. {
  3821. $row = mysql_fetch_array($res);
  3822. $ver = explode(".", $row[0]);
  3823. // Version numbering format which is not recognized.
  3824. if (count($ver) != 3) return array(
  3825. PHORUM_SANITY_WARN,
  3826. "The database layer was unable to recognize the MySQL server's
  3827. version number \"" . htmlspecialchars($row[0]) . "\". Therefore,
  3828. checking if the right version of MySQL is used is not possible.",
  3829. "Contact the Phorum developers and report this specific
  3830. version number, so the checking scripts can be updated."
  3831. );
  3832. settype($ver[0], 'int');
  3833. settype($ver[1], 'int');
  3834. settype($ver[2], 'int');
  3835. // MySQL before version 4.
  3836. if ($ver[0] < 4) return array(
  3837. PHORUM_SANITY_CRIT,
  3838. "The MySQL database server that is used is too old. The
  3839. running version is \"" . htmlspecialchars($row[0]) . "\",
  3840. while MySQL version 4.0.18 or higher is recommended.",
  3841. "Upgrade your MySQL server to a newer version. If your
  3842. website is hosted with a service provider, please contact
  3843. the service provider to upgrade your MySQL database."
  3844. );
  3845. // MySQL before version 4.0.18, with full text search enabled.
  3846. if ($PHORUM["DBCONFIG"]["mysql_use_ft"] &&
  3847. $ver[0] == 4 && $ver[1] == 0 && $ver[2] < 18) return array(
  3848. PHORUM_SANITY_WARN,
  3849. "The MySQL database server that is used does not
  3850. support all Phorum features. The running version is
  3851. \"" . htmlspecialchars($row[0]) . "\", while MySQL version
  3852. 4.0.18 or higher is recommended.",
  3853. "Upgrade your MySQL server to a newer version. If your
  3854. website is hosted with a service provider, please contact
  3855. the service provider to upgrade your MySQL database."
  3856. );
  3857. // All checks are okay.
  3858. return array (PHORUM_SANITY_OK, NULL);
  3859. }
  3860. return array(
  3861. PHORUM_SANITY_CRIT,
  3862. "An unexpected problem was found in running the sanity
  3863. check function phorum_db_sanitychecks().",
  3864. "Contact the Phorum developers to find out what the problem is."
  3865. );
  3866. }
  3867. ?>