[ Index ]
 

Code source de Phorum 5.1.25

Accédez au Source d'autres logiciels libres

Classes | Fonctions | Variables | Constantes | Tables

title

Body

[fermer]

/include/db/ -> mysql.php (source)

   1  <?php
   2  
   3  ////////////////////////////////////////////////////////////////////////////////
   4  //                                                                            //
   5  //   Copyright (C) 2006  Phorum Development Team                              //
   6  //   http://www.phorum.org                                                    //
   7  //                                                                            //
   8  //   This program is free software. You can redistribute it and/or modify     //
   9  //   it under the terms of either the current Phorum License (viewable at     //
  10  //   phorum.org) or the Phorum License that was distributed with this file    //
  11  //                                                                            //
  12  //   This program is distributed in the hope that it will be useful,          //
  13  //   but WITHOUT ANY WARRANTY, without even the implied warranty of           //
  14  //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                     //
  15  //                                                                            //
  16  //   You should have received a copy of the Phorum License                    //
  17  //   along with this program.                                                 //
  18  ////////////////////////////////////////////////////////////////////////////////
  19  
  20  // cvs-info: $Id: mysql.php 2456 2007-09-12 22:32:38Z brian $
  21  
  22  if (!defined("PHORUM")) return;
  23  
  24  /**
  25   * The other Phorum code does not care how the messages are stored.
  26   *    The only requirement is that they are returned from these functions
  27   *    in the right way.  This means each database can use as many or as
  28   *    few tables as it likes.  It can store the fields anyway it wants.
  29   *    The only thing to worry about is the table_prefix for the tables.
  30   *    all tables for a Phorum install should be prefixed with the
  31   *    table_prefix that will be entered in include/db/config.php.  This
  32   *    will allow multiple Phorum installations to use the same database.
  33   */
  34  
  35  /**
  36   * These are the table names used for this database system.
  37   */
  38  
  39  // tables needed to be "partitioned"
  40  $PHORUM["message_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_messages";
  41  $PHORUM["user_newflags_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_user_newflags";
  42  $PHORUM["subscribers_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_subscribers";
  43  $PHORUM["files_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_files";
  44  $PHORUM["search_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_search";
  45  
  46  // tables common to all "partitions"
  47  $PHORUM["settings_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_settings";
  48  $PHORUM["forums_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_forums";
  49  $PHORUM["user_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_users";
  50  $PHORUM["user_permissions_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_user_permissions";
  51  $PHORUM["groups_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_groups";
  52  $PHORUM["forum_group_xref_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_forum_group_xref";
  53  $PHORUM["user_group_xref_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_user_group_xref";
  54  $PHORUM['user_custom_fields_table'] = "{$PHORUM['DBCONFIG']['table_prefix']}_user_custom_fields";
  55  $PHORUM["banlist_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_banlists";
  56  $PHORUM["pm_messages_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_pm_messages";
  57  $PHORUM["pm_folders_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_pm_folders";
  58  $PHORUM["pm_xref_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_pm_xref";
  59  $PHORUM["pm_buddies_table"] = "{$PHORUM['DBCONFIG']['table_prefix']}_pm_buddies";
  60  /*
  61  * fields which are always strings, even if they contain only numbers
  62  * used in post-message and update-message, otherwise strange things happen
  63  */
  64  $PHORUM['string_fields']= array('author', 'subject', 'body', 'email');
  65  
  66  /* A piece of SQL code that can be used for identifying moved messages. */
  67  define('PHORUM_SQL_MOVEDMESSAGES', "({$PHORUM['message_table']}.parent_id = 0 and {$PHORUM['message_table']}.thread != {$PHORUM['message_table']}.message_id)");
  68  
  69  /**
  70   * This function executes a query to select the visible messages from
  71   * the database for a given page offset. The main Phorum code handles
  72   * actually sorting the threads into a threaded list if needed.
  73   *
  74   * By default, the message body is not included in the fetch queries.
  75   * If the body is needed in the thread list, $PHORUM['TMP']['bodies_in_list']
  76   * must be set to "1" (for example using setting.tpl).
  77   *
  78   * NOTE: ALL dates should be returned as Unix timestamps
  79   *
  80   * @param offset - the index of the page to return, starting with 0
  81   * @param messages - an array containing forum messages
  82   */
  83  
  84  function phorum_db_get_thread_list($offset)
  85  {
  86      $PHORUM = $GLOBALS["PHORUM"];
  87  
  88      settype($offset, "int");
  89  
  90      $conn = phorum_db_mysql_connect();
  91  
  92      $table = $PHORUM["message_table"];
  93  
  94      // The messagefields that we want to fetch from the database.
  95      $messagefields =
  96         "$table.author,
  97          $table.datestamp,
  98          $table.email,
  99          $table.message_id,
 100          $table.meta,
 101          $table.moderator_post,
 102          $table.modifystamp,
 103          $table.parent_id,
 104          $table.msgid,
 105          $table.sort,
 106          $table.status,
 107          $table.subject,
 108          $table.thread,
 109          $table.thread_count,
 110          $table.user_id,
 111          $table.viewcount,
 112          $table.closed";
 113      if(isset($PHORUM['TMP']['bodies_in_list']) && $PHORUM['TMP']['bodies_in_list'] == 1) {
 114          $messagefields .= "\n,$table.body\n,$table.ip";
 115      }
 116  
 117      // The sort mechanism to use.
 118      if($PHORUM["float_to_top"]){
 119              $sortfield = "modifystamp";
 120              $index = "list_page_float";
 121      } else{
 122              $sortfield = "thread";
 123              $index = "list_page_flat";
 124      }
 125  
 126      // Initialize the return array.
 127      $messages = array();
 128  
 129      // The groups of messages we want to fetch from the database.
 130      $groups = array();
 131      if ($offset == 0) $groups[] = "specials";
 132      $groups[] = "threads";
 133      if ($PHORUM["threaded_list"]) $groups[] = "replies";
 134  
 135      // for remembering message ids for which we want to fetch the replies.
 136      $replymsgids = array();
 137  
 138      // Process all groups.
 139      foreach ($groups as $group) {
 140  
 141  
 142          $sql = NULL;
 143  
 144          switch ($group) {
 145  
 146              // Announcements and stickies.
 147              case "specials":
 148  
 149                  $sql = "select $messagefields
 150                         from $table
 151                         where
 152                           status=".PHORUM_STATUS_APPROVED." and
 153                           ((parent_id=0 and sort=".PHORUM_SORT_ANNOUNCEMENT."
 154                             and forum_id={$PHORUM['vroot']})
 155                           or
 156                           (parent_id=0 and sort=".PHORUM_SORT_STICKY."
 157                            and forum_id={$PHORUM['forum_id']}))
 158                         order by
 159                           sort, $sortfield desc";
 160                  break;
 161  
 162              // Threads.
 163              case "threads":
 164  
 165                  if ($PHORUM["threaded_list"]) {
 166                      $limit = $PHORUM['list_length_threaded'];
 167                      $extrasql = '';
 168                  } else {
 169                      $limit = $PHORUM['list_length_flat'];
 170                  }
 171                  $start = $offset * $limit;
 172  
 173                  $sql = "select $messagefields
 174                          from $table use index ($index)
 175                          where
 176                            $sortfield > 0 and
 177                            forum_id = {$PHORUM["forum_id"]} and
 178                            status = ".PHORUM_STATUS_APPROVED." and
 179                            parent_id = 0 and
 180                            sort > 1
 181                          order by
 182                            $sortfield desc
 183                          limit $start, $limit";
 184                  break;
 185  
 186              // Reply messages.
 187              case "replies":
 188  
 189                  // We're done if we did not collect any messages with replies.
 190                  if (! count($replymsgids)) break;
 191  
 192                  $sortorder = "sort, $sortfield desc, message_id";
 193                  if(isset($PHORUM["reverse_threading"]) && $PHORUM["reverse_threading"])
 194                      $sortorder.=" desc";
 195  
 196                  $sql = "select $messagefields
 197                          from $table
 198                          where
 199                            status = ".PHORUM_STATUS_APPROVED." and
 200                            thread in (" . implode(",",$replymsgids) .")
 201                          order by $sortorder";
 202                  break;
 203  
 204          } // End of switch ($group)
 205  
 206          // Continue with the next group if no SQL query was formulated.
 207          if (is_null($sql)) continue;
 208  
 209          // Fetch the messages for the current group.
 210          $res = mysql_query($sql, $conn);
 211          if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
 212          $rows = mysql_num_rows($res);
 213          if($rows > 0){
 214              while ($rec = mysql_fetch_assoc($res)){
 215                  $messages[$rec["message_id"]] = $rec;
 216                  $messages[$rec["message_id"]]["meta"] = array();
 217                  if(!empty($rec["meta"])){
 218                      $messages[$rec["message_id"]]["meta"] = unserialize($rec["meta"]);
 219                  }
 220  
 221                  // We need the message ids for fetching reply messages.
 222                  if ($group == 'threads' && $rec["thread_count"] > 1) {
 223                      $replymsgids[] = $rec["message_id"];
 224                  }
 225              }
 226          }
 227      }
 228  
 229      return $messages;
 230  }
 231  
 232  /**
 233   * This function executes a query to get the recent messages for
 234   * all forums the user can read, a particular forum, or a particular
 235   * thread, and and returns an array of the messages order by message_id.
 236   * You can optionally retrieve only new threads.
 237   *
 238   * The original version of this function came from Jim Winstead of mysql.com
 239   */
 240  function phorum_db_get_recent_messages($count, $forum_id = 0, $thread = 0, $threads_only = 0)
 241  {
 242      $PHORUM = $GLOBALS["PHORUM"];
 243      settype($count, "int");
 244      settype($thread, "int");
 245      settype($threads_only, "bool");
 246      phorum_db_sanitize_mixed($forum_id, "int");
 247  
 248      $arr = array();
 249      $allowed_forums = array();
 250  
 251      $conn = phorum_db_mysql_connect();
 252  
 253      // we need to differentiate on which key to use
 254      if($thread) {
 255          $use_key='thread_message';
 256      } else {
 257          $use_key='forum_max_message';
 258      }
 259  
 260      $sql = "SELECT {$PHORUM['message_table']}.* FROM {$PHORUM['message_table']} USE KEY($use_key) WHERE status=".PHORUM_STATUS_APPROVED;
 261  
 262      // have to check what forums they can read first.
 263      // even if $thread is passed, we have to make sure
 264      // the user can read the forum
 265      if($forum_id <= 0) {
 266          $allowed_forums=phorum_user_access_list(PHORUM_USER_ALLOW_READ);
 267  
 268          // if they are not allowed to see any forums, return the emtpy $arr;
 269          if(empty($allowed_forums))
 270              return $arr;
 271      } elseif(is_array($forum_id)) {
 272          // for an array, check each one and return if none are allowed
 273          foreach($forum_id as $id){
 274              $id = (int)$id;
 275              if(phorum_user_access_allowed(PHORUM_USER_ALLOW_READ,$id)) {
 276                  $allowed_forums[]=$id;
 277              }
 278          }
 279  
 280          // if they are not allowed to see any forums, return the emtpy $arr;
 281          if(empty($allowed_forums))
 282              return $arr;
 283      } else {
 284          // only single forum, *much* fast this way
 285          if(!phorum_user_access_allowed(PHORUM_USER_ALLOW_READ,$forum_id)) {
 286              return $arr;
 287          }
 288          settype($forum_id, "int");
 289      }
 290  
 291      if(count($allowed_forums)){
 292          $sql.=" and forum_id in (".implode(",", $allowed_forums).")";
 293      } else {
 294          $sql.=" and forum_id=$forum_id";
 295      }
 296  
 297      if($thread){
 298          $sql.=" and thread=$thread";
 299      }
 300  
 301      if($threads_only) {
 302          $sql.= " and parent_id = 0";
 303          $sql.= " ORDER BY thread DESC";
 304      } else {
 305          $sql.= " ORDER BY message_id DESC";
 306      }
 307  
 308      if($count){
 309          $sql.= " LIMIT $count";
 310      }
 311  
 312      $res = mysql_query($sql, $conn);
 313      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
 314  
 315      while ($rec = mysql_fetch_assoc($res)){
 316          $arr[$rec["message_id"]] = $rec;
 317  
 318          // convert meta field
 319          if(empty($rec["meta"])){
 320              $arr[$rec["message_id"]]["meta"]=array();
 321          } else {
 322              $arr[$rec["message_id"]]["meta"]=unserialize($rec["meta"]);
 323          }
 324          if(empty($arr['users'])) $arr['users']=array();
 325          if($rec["user_id"]){
 326              $arr['users'][]=$rec["user_id"];
 327          }
 328  
 329      }
 330  
 331      return $arr;
 332  }
 333  
 334  
 335  /**
 336   * This function executes a query to select messages from the database
 337   * and returns an array.  The main Phorum code handles actually sorting
 338   * the threads into a threaded list if needed.
 339   *
 340   * NOTE: ALL dates should be returned as Unix timestamps
 341   * @param forum - the forum id to work with. Omit or NULL for all forums.
 342   *                You can also pass an array of forum_id's.
 343   * @param waiting_only - only take into account messages which have to
 344   *                be approved directly after posting. Do not include
 345   *                messages which are hidden by a moderator.
 346   */
 347  
 348  function phorum_db_get_unapproved_list($forum = NULL, $waiting_only=false,$moddays=0,$countonly=false)
 349  {
 350      $PHORUM = $GLOBALS["PHORUM"];
 351  
 352      settype($waiting_only, "bool");
 353      settype($moddays, "int");
 354      settype($countonly, "bool");
 355      phorum_db_sanitize_mixed($forum, "int");
 356  
 357      $conn = phorum_db_mysql_connect();
 358  
 359      $table = $PHORUM["message_table"];
 360  
 361      $arr = array();
 362      $sum = 0;
 363  
 364      // do we want only a count here?
 365      if($countonly) {
 366          $selecting = "count(*) as msgcnt";
 367  
 368      // or the full messages?
 369      } else {
 370          $selecting = "$table.*";
 371  
 372      }
 373  
 374      $sql = "select
 375              $selecting
 376            from
 377              $table ";
 378  
 379      if (is_array($forum)){
 380          $sql .= "where forum_id in (" . implode(",", $forum) . ") and ";
 381      } elseif (! is_null($forum)){
 382          settype($forum, "int");
 383          $sql .= "where forum_id = $forum and ";
 384      } else {
 385          $sql .= "where ";
 386      }
 387  
 388      if($moddays > 0) {
 389          $checktime=time()-(86400*$moddays);
 390          $sql .=" datestamp > $checktime AND";
 391      }
 392  
 393      if($waiting_only){
 394          $sql.=" status=".PHORUM_STATUS_HOLD;
 395      } else {
 396          $sql="($sql status=".PHORUM_STATUS_HOLD.") " .
 397               "union ($sql status=".PHORUM_STATUS_HIDDEN.")";
 398      }
 399  
 400  
 401      if(!$countonly) {
 402          $sql .=" order by thread, message_id";
 403      }
 404  
 405      $res = mysql_query($sql, $conn);
 406      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
 407  
 408      while ($rec = mysql_fetch_assoc($res)){
 409          if($countonly) {
 410              $sum += $rec['msgcnt'];
 411          } else {
 412              $arr[$rec["message_id"]] = $rec;
 413              $arr[$rec["message_id"]]["meta"] = array();
 414              if(!empty($rec["meta"])){
 415                  $arr[$rec["message_id"]]["meta"] = unserialize($rec["meta"]);
 416              }
 417          }
 418      }
 419  
 420      if($countonly) {
 421          return $sum;
 422      } else {
 423          return $arr;
 424      }
 425  }
 426  
 427  
 428  /**
 429   * This function posts a message to the tables.
 430   * The message is passed by reference and message_id and thread are filled
 431   */
 432  
 433  function phorum_db_post_message(&$message,$convert=false)
 434  {
 435      $PHORUM = $GLOBALS["PHORUM"];
 436      $table = $PHORUM["message_table"];
 437  
 438      settype($convert, "bool");
 439  
 440      $conn = phorum_db_mysql_connect();
 441  
 442      $success = false;
 443  
 444      foreach($message as $key => $value){
 445          if (is_numeric($value) && !in_array($key,$PHORUM['string_fields'])){
 446              $message[$key] = (int)$value;
 447          } elseif(is_array($value)) {
 448              $message[$key] = mysql_escape_string(serialize($value));
 449          } else{
 450              $message[$key] = mysql_escape_string($value);
 451          }
 452      }
 453  
 454      if(!$convert) {
 455          $NOW = time();
 456      } else {
 457          $NOW = $message['datestamp'];
 458      }
 459  
 460      // duplicate-check
 461      if(isset($PHORUM['check_duplicate']) && $PHORUM['check_duplicate'] && !$convert) {
 462          // we check for dupes in that number of minutes
 463          $check_minutes=60;
 464          $check_timestamp =$NOW - ($check_minutes*60);
 465          // check_query
 466          $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";
 467          $res = mysql_query($chk_query, $conn);
 468          if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $chk_query");
 469          if(mysql_num_rows($res))
 470              return 0;
 471      }
 472  
 473      if(isset($message['meta'])){
 474          $metaval=",meta='{$message['meta']}'";
 475      } else {
 476          $metaval="";
 477      }
 478  
 479      $sql = "Insert into $table set
 480              forum_id = {$message['forum_id']},
 481              datestamp=$NOW,
 482              thread={$message['thread']},
 483              parent_id={$message['parent_id']},
 484              author='{$message['author']}',
 485              subject='{$message['subject']}',
 486              email='{$message['email']}',
 487              ip='{$message['ip']}',
 488              user_id={$message['user_id']},
 489              moderator_post={$message['moderator_post']},
 490              status={$message['status']},
 491              sort={$message['sort']},
 492              msgid='{$message['msgid']}',
 493              body='{$message['body']}',
 494              closed={$message['closed']}
 495              $metaval";
 496  
 497      // if in conversion we need the message-id too
 498      if($convert && isset($message['message_id'])) {
 499          $sql.=",message_id=".$message['message_id'];
 500      }
 501  
 502      if(isset($message['modifystamp'])) {
 503          $sql.=",modifystamp=".$message['modifystamp'];
 504      }
 505  
 506      if(isset($message['viewcount'])) {
 507          $sql.=",viewcount=".$message['viewcount'];
 508      }
 509  
 510  
 511      $res = mysql_query($sql, $conn);
 512      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
 513  
 514      if ($res){
 515          $message["message_id"] = mysql_insert_id($conn);
 516  
 517          if(!empty($message["message_id"])){
 518  
 519              $message["datestamp"]=$NOW;
 520  
 521              if ($message["thread"] == 0){
 522                  $message["thread"] = $message["message_id"];
 523                  $sql = "update $table set thread={$message['message_id']} where message_id={$message['message_id']}";
 524                  $res = mysql_query($sql, $conn);
 525                  if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
 526              }
 527  
 528              if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
 529  
 530              // start ft-search stuff
 531              if(isset($PHORUM["DBCONFIG"]["mysql_use_ft"]) && $PHORUM["DBCONFIG"]["mysql_use_ft"]){
 532                  $search_text="$message[author] | $message[subject] | $message[body]";
 533  
 534                  $sql="insert delayed into {$PHORUM['search_table']} set message_id={$message['message_id']}, forum_id={$message['forum_id']}, search_text='$search_text'";
 535                  $res = mysql_query($sql, $conn);
 536                  if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
 537              }
 538              // end ft-search stuff
 539  
 540              $success = true;
 541              // some data for later use, i.e. email-notification
 542              $GLOBALS['PHORUM']['post_returns']['message_id']=$message["message_id"];
 543              $GLOBALS['PHORUM']['post_returns']['thread_id']=$message["thread"];
 544          }
 545      }
 546  
 547      return $success;
 548  }
 549  
 550  /**
 551   * This function deletes messages from the messages table.
 552   *
 553   * @param message $ _id the id of the message which should be deleted
 554   * mode the mode of deletion, PHORUM_DELETE_MESSAGE for reconnecting the children, PHORUM_DELETE_TREE for deleting the children
 555   */
 556  
 557  function phorum_db_delete_message($message_id, $mode = PHORUM_DELETE_MESSAGE)
 558  {
 559      $PHORUM = $GLOBALS["PHORUM"];
 560  
 561      $conn = phorum_db_mysql_connect();
 562  
 563      settype($message_id, "int");
 564      settype($mode, "int");
 565  
 566      $threadset = 0;
 567      // get the parents of the message to delete.
 568      $sql = "select forum_id, message_id, thread, parent_id from {$PHORUM['message_table']} where message_id = $message_id ";
 569      $res = mysql_query($sql, $conn);
 570      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
 571  
 572      $rec = mysql_fetch_assoc($res);
 573      if (empty($rec)) {
 574          phorum_db_mysql_error("No message found for message_id $message_id");
 575      }
 576  
 577      if($mode == PHORUM_DELETE_TREE){
 578          $mids = phorum_db_get_messagetree($message_id, $rec['forum_id']);
 579      }else{
 580          $mids = $message_id;
 581      }
 582  
 583      // unapprove the messages first so replies will not get posted
 584      $sql = "update {$PHORUM['message_table']} set status=".PHORUM_STATUS_HOLD." where message_id in ($mids)";
 585      $res = mysql_query($sql, $conn);
 586      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
 587  
 588      $thread = $rec['thread'];
 589      if($thread == $message_id && $mode == PHORUM_DELETE_TREE){
 590          $threadset = 1;
 591      }else{
 592          $threadset = 0;
 593      }
 594  
 595      if($mode == PHORUM_DELETE_MESSAGE){
 596          $count = 1;
 597          // change the children to point to their parent's parent
 598          // forum_id is in here for speed by using a key only
 599          $sql = "update {$PHORUM['message_table']} set parent_id=$rec[parent_id] where forum_id=$rec[forum_id] and parent_id=$rec[message_id]";
 600          mysql_query($sql, $conn);
 601          if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
 602      }else{
 603          $count = count(explode(",", $mids));
 604      }
 605  
 606      // delete the messages
 607      $sql = "delete from {$PHORUM['message_table']} where message_id in ($mids)";
 608      mysql_query($sql, $conn);
 609      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
 610  
 611      // start ft-search stuff
 612      $sql="delete from {$PHORUM['search_table']} where message_id in ($mids)";
 613      $res = mysql_query($sql, $conn);
 614      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
 615      // end ft-search stuff
 616  
 617      // it kind of sucks to have this here, but it is the best way
 618      // to ensure that it gets done if stuff is deleted.
 619      // leave this include here, it needs to be conditional
 620      include_once ("./include/thread_info.php");
 621      phorum_update_thread_info($thread);
 622  
 623      // we need to delete the subscriptions for that thread too
 624      $sql = "DELETE FROM {$PHORUM['subscribers_table']} WHERE forum_id > 0 AND thread=$thread";
 625      $res = mysql_query($sql, $conn);
 626      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
 627  
 628      // this function will be slow with a lot of messages.
 629      phorum_db_update_forum_stats(true);
 630  
 631      return explode(",", $mids);
 632  }
 633  
 634  /**
 635   * gets all attached messages to a message
 636   *
 637   * @param id $ id of the message
 638   */
 639  function phorum_db_get_messagetree($parent_id, $forum_id){
 640      $PHORUM = $GLOBALS["PHORUM"];
 641  
 642      settype($parent_id, "int");
 643      settype($forum_id, "int");
 644  
 645      $conn = phorum_db_mysql_connect();
 646  
 647      $sql = "Select message_id from {$PHORUM['message_table']} where forum_id=$forum_id and parent_id=$parent_id";
 648  
 649      $res = mysql_query($sql, $conn);
 650      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
 651  
 652      $tree = "$parent_id";
 653  
 654      while($rec = mysql_fetch_row($res)){
 655          $tree .= "," . phorum_db_get_messagetree($rec[0],$forum_id);
 656      }
 657  
 658      return $tree;
 659  }
 660  
 661  /**
 662   * This function updates the message given in the $message array for
 663   * the row with the given message id.  It returns non 0 on success.
 664   */
 665  
 666  function phorum_db_update_message($message_id, $message)
 667  {
 668      $PHORUM = $GLOBALS["PHORUM"];
 669  
 670      settype($message_id, "int");
 671  
 672      if (count($message) > 0){
 673          $conn = phorum_db_mysql_connect();
 674  
 675          foreach($message as $field => $value){
 676              if(phorum_db_validate_field($field)){
 677                  if (is_numeric($value) && !in_array($field,$PHORUM['string_fields'])){
 678                      $fields[] = "$field=$value";
 679                  }elseif (is_array($value)){
 680                      $value = mysql_escape_string(serialize($value));
 681                      $message[$field] = $value;
 682                      $fields[] = "$field='$value'";
 683                  }else{
 684                      $value = mysql_escape_string($value);
 685                      $message[$field] = $value;
 686                      $fields[] = "$field='$value'";
 687                  }
 688              }
 689          }
 690  
 691          $sql = "update {$PHORUM['message_table']} set " . implode(", ", $fields) . " where message_id=$message_id";
 692          $res = mysql_query($sql, $conn);
 693          if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
 694  
 695          if($res){
 696              // start ft-search stuff
 697              if(isset($message["author"]) && isset($message["subject"]) && isset($message["body"])){
 698                  $search_text="$message[author] | $message[subject] | $message[body]";
 699                  $sql="replace delayed into {$PHORUM['search_table']} set message_id={$message_id}, forum_id={$message['forum_id']}, search_text='$search_text'";
 700                  $res = mysql_query($sql, $conn);
 701                  if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
 702              }
 703              // end ft-search stuff
 704          }
 705  
 706          return ($res > 0) ? true : false;
 707  
 708      }else{
 709          trigger_error("\$message cannot be empty in phorum_update_message()", E_USER_ERROR);
 710      }
 711  }
 712  
 713  
 714  /**
 715   * This function executes a query to get the row with the given value
 716   * in the given field and returns the message in an array.
 717   */
 718  
 719  function phorum_db_get_message($value, $field="message_id", $ignore_forum_id=false)
 720  {
 721      $PHORUM = $GLOBALS["PHORUM"];
 722  
 723      if(!phorum_db_validate_field($field)){
 724          return false;
 725      }
 726  
 727      $multiple=false;
 728  
 729      phorum_db_sanitize_mixed($value, "string");
 730      settype($ignore_forum_id, "bool");
 731  
 732      $conn = phorum_db_mysql_connect();
 733  
 734  
 735      $forum_id_check = "";
 736      if (!$ignore_forum_id && !empty($PHORUM["forum_id"])){
 737          $forum_id_check = "(forum_id = {$PHORUM['forum_id']} OR forum_id={$PHORUM['vroot']}) and";
 738      }
 739  
 740      if(is_array($value)) {
 741          $checkvar="$field IN('".implode("','",$value)."')";
 742          $multiple=true;
 743      } else {
 744          $checkvar="$field='$value'";
 745      }
 746  
 747  
 748      $sql = "select {$PHORUM['message_table']}.* from {$PHORUM['message_table']} where $forum_id_check $checkvar";
 749      $res = mysql_query($sql, $conn);
 750      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
 751  
 752      $ret = $multiple ? array() : NULL;
 753  
 754      if(mysql_num_rows($res)){
 755          if($multiple) {
 756              while($rec=mysql_fetch_assoc($res)) {
 757                  // convert meta field
 758                  if(empty($rec["meta"])){
 759                      $rec["meta"]=array();
 760                  } else {
 761                      $rec["meta"]=unserialize($rec["meta"]);
 762                  }
 763                  $ret[$rec['message_id']]=$rec;
 764              }
 765          } else {
 766              $rec = mysql_fetch_assoc($res);
 767  
 768              // convert meta field
 769              if(empty($rec["meta"])){
 770                  $rec["meta"]=array();
 771              } else {
 772                  $rec["meta"]=unserialize($rec["meta"]);
 773              }
 774              $ret=$rec;
 775          }
 776      }
 777  
 778      return $ret;
 779  }
 780  
 781  /**
 782   * This function executes a query to get the rows with the given thread
 783   * id and returns an array of the message.
 784   */
 785  function phorum_db_get_messages($thread,$page=0,$ignore_mod_perms = 0)
 786  {
 787      $PHORUM = $GLOBALS["PHORUM"];
 788  
 789      settype($thread, "int");
 790      settype($page, "int");
 791      settype($ignore_mod_perms, "bool");
 792  
 793      $conn = phorum_db_mysql_connect();
 794  
 795      $forum_id_check = "";
 796      if (!empty($PHORUM["forum_id"])){
 797          $forum_id_check = "(forum_id = {$PHORUM['forum_id']} OR forum_id={$PHORUM['vroot']}) and";
 798      }
 799  
 800      // are we really allowed to show this thread/message?
 801      $approvedval = "";
 802      if(!$ignore_mod_perms && !phorum_user_access_allowed(PHORUM_USER_ALLOW_MODERATE_MESSAGES)) {
 803          $approvedval="AND {$PHORUM['message_table']}.status =".PHORUM_STATUS_APPROVED;
 804      }
 805  
 806      if($page > 0) {
 807             $start=$PHORUM["read_length"]*($page-1);
 808             $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"];
 809      } else {
 810             $sql = "select {$PHORUM['message_table']}.* from {$PHORUM['message_table']} where $forum_id_check thread=$thread $approvedval order by message_id";
 811             if(isset($PHORUM["reverse_threading"]) && $PHORUM["reverse_threading"]) $sql.=" desc";
 812      }
 813  
 814      $res = mysql_query($sql, $conn);
 815      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
 816  
 817      $arr = array();
 818  
 819      while ($rec = mysql_fetch_assoc($res)){
 820          $arr[$rec["message_id"]] = $rec;
 821  
 822          // convert meta field
 823          if(empty($rec["meta"])){
 824              $arr[$rec["message_id"]]["meta"]=array();
 825          } else {
 826              $arr[$rec["message_id"]]["meta"]=unserialize($rec["meta"]);
 827          }
 828          if(empty($arr['users'])) $arr['users']=array();
 829          if($rec["user_id"]){
 830              $arr['users'][]=$rec["user_id"];
 831          }
 832  
 833      }
 834  
 835      if(count($arr) && $page != 0) {
 836          // selecting the thread-starter
 837          $sql = "select {$PHORUM['message_table']}.* from {$PHORUM['message_table']} where $forum_id_check message_id=$thread $approvedval";
 838          $res = mysql_query($sql, $conn);
 839          if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
 840          if(mysql_num_rows($res) > 0) {
 841              $rec = mysql_fetch_assoc($res);
 842              $arr[$rec["message_id"]] = $rec;
 843              $arr[$rec["message_id"]]["meta"]=unserialize($rec["meta"]);
 844          }
 845      }
 846      return $arr;
 847  }
 848  
 849  /**
 850   * this function returns the index of a message in a thread
 851   */
 852  function phorum_db_get_message_index($thread=0,$message_id=0) {
 853      $PHORUM = $GLOBALS["PHORUM"];
 854  
 855      // check for valid values
 856      if(empty($thread) || empty($message_id)) {
 857          return 0;
 858      }
 859  
 860      settype($thread, "int");
 861      settype($message_id, "int");
 862  
 863      $approvedval="";
 864      $forum_id_check="";
 865  
 866      $conn = phorum_db_mysql_connect();
 867  
 868      if (!empty($PHORUM["forum_id"])){
 869          $forum_id_check = "(forum_id = {$PHORUM['forum_id']} OR forum_id={$PHORUM['vroot']}) AND";
 870      }
 871  
 872      if(!phorum_user_access_allowed(PHORUM_USER_ALLOW_MODERATE_MESSAGES)) {
 873          $approvedval="AND {$PHORUM['message_table']}.status =".PHORUM_STATUS_APPROVED;
 874      }
 875  
 876      $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";
 877  
 878      $res = mysql_query($sql, $conn);
 879      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
 880  
 881      $rec = mysql_fetch_assoc($res);
 882  
 883      return $rec['msg_index'];
 884  }
 885  
 886  /**
 887   * This function searches the database for the supplied search
 888   * criteria and returns an array with two elements.  One is the count
 889   * of total messages that matched, the second is an array of the
 890   * messages from the results based on the $start (0 base) given and
 891   * the $length given.
 892   */
 893  
 894  function phorum_db_search($search, $offset, $length, $match_type, $match_date, $match_forum)
 895  {
 896      $PHORUM = $GLOBALS["PHORUM"];
 897  
 898      settype($offset, "int");
 899      settype($length, "int");
 900      settype($match_date, "int");
 901  
 902      $start = $offset * $PHORUM["list_length"];
 903  
 904      $arr = array("count" => 0, "rows" => array());
 905  
 906      $conn = phorum_db_mysql_connect();
 907  
 908      // have to check what forums they can read first.
 909      $allowed_forums=phorum_user_access_list(PHORUM_USER_ALLOW_READ);
 910      // if they are not allowed to search any forums, return the emtpy $arr;
 911      if(empty($allowed_forums) || ($PHORUM['forum_id']>0 && !in_array($PHORUM['forum_id'], $allowed_forums)) ) return $arr;
 912  
 913      // Add forum 0 (for announcements) to the allowed forums.
 914      $allowed_forums[] = 0;
 915  
 916      if($PHORUM['forum_id']!=0 && $match_forum!="ALL"){
 917          $forum_where=" and forum_id={$PHORUM['forum_id']}";
 918      } else {
 919          $forum_where=" and forum_id in (".implode(",", $allowed_forums).")";
 920      }
 921  
 922      // prepare terms
 923      if($match_type=="PHRASE"){
 924  
 925          if(isset($PHORUM["DBCONFIG"]["mysql_use_ft"]) && $PHORUM["DBCONFIG"]["mysql_use_ft"]){
 926              $terms = array('"'.$search.'"');
 927          } else {
 928              $terms = array($search);
 929          }
 930  
 931      } elseif($match_type=="AUTHOR"){
 932  
 933          $terms = mysql_escape_string($search);
 934  
 935      } else {
 936  
 937          $quote_terms=array();
 938          if ( strstr( $search, '"' ) ){
 939              //first pull out all the double quoted strings (e.g. '"iMac DV" or -"iMac DV"')
 940              preg_match_all( '/-*"(.*?)"/', $search, $match );
 941              $search = preg_replace( '/-*".*?"/', '', $search );
 942              $quote_terms = $match[0];
 943          }
 944  
 945          //finally pull out the rest words in the string
 946          $terms = preg_split( "/\s+/", $search, 0, PREG_SPLIT_NO_EMPTY );
 947  
 948          //merge them all together and return
 949          $terms = array_merge($terms, $quote_terms);
 950  
 951      }
 952  
 953  
 954      if(isset($PHORUM["DBCONFIG"]["mysql_use_ft"]) && $PHORUM["DBCONFIG"]["mysql_use_ft"]){
 955  
 956          if($match_type=="AUTHOR"){
 957  
 958              $id_table=$PHORUM['search_table']."_auth_".md5(microtime());
 959  
 960              $sql = "create temporary table $id_table (key(message_id)) ENGINE=HEAP select message_id from {$PHORUM['message_table']} where author='$terms' $forum_where";
 961              if($match_date>0){
 962                  $ts=time()-86400*$match_date;
 963                  $sql.=" and datestamp>=$ts";
 964              }
 965  
 966              $res = mysql_query($sql, $conn);
 967              if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
 968  
 969          } else {
 970  
 971  
 972              if(count($terms)){
 973  
 974                  $use_key="";
 975                  $extra_where="";
 976  
 977                  /* using this code on larger forums has shown to make the search faster.
 978                     However, on smaller forums, it does not appear to help and in fact
 979                     appears to slow down searches.
 980  
 981                  if($match_date){
 982                      $min_time=time()-86400*$match_date;
 983                      $sql="select min(message_id) as min_id from {$PHORUM['message_table']} where datestamp>=$min_time";
 984                      $res=mysql_query($sql, $conn);
 985                      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
 986                      $min_id=mysql_result($res, 0, "min_id");
 987                      $use_key=" use key (primary)";
 988                      $extra_where="and message_id>=$min_id";
 989                  }
 990                  */
 991  
 992                  $id_table=$PHORUM['search_table']."_ft_".md5(microtime());
 993  
 994                  $against = "";
 995  
 996                  if($match_type=="ALL" && count($terms)>1){
 997                      foreach($terms as $term){
 998                          if($term[0] == "+" || $term[0] == "-"){
 999                              $against .= mysql_escape_string($term)." ";
1000                          } else {
1001                              $against .= "+".mysql_escape_string($term)." ";
1002                          }
1003                      }
1004                      $against = trim($against);
1005                  } else {
1006                      $against=mysql_escape_string(implode(" ", $terms));
1007                  }
1008  
1009                  $clause="MATCH (search_text) AGAINST ('$against' IN BOOLEAN MODE)";
1010  
1011                  $sql = "create temporary table $id_table (key(message_id)) ENGINE=HEAP select message_id from {$PHORUM['search_table']} $use_key where $clause $extra_where";
1012                  $res = mysql_unbuffered_query($sql, $conn);
1013                  if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1014  
1015              }
1016          }
1017  
1018  
1019          if(isset($id_table)){
1020  
1021              // create a temporary table of the messages we want
1022              $table=$PHORUM['search_table']."_".md5(microtime());
1023              $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";
1024  
1025              if($match_date>0){
1026                  $ts=time()-86400*$match_date;
1027                  $sql.=" and datestamp>=$ts";
1028              }
1029  
1030              $res=mysql_query($sql, $conn);
1031              if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1032  
1033              $sql="select count(*) as count from $table";
1034              $res = mysql_query($sql, $conn);
1035  
1036              if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1037              $total_count=mysql_result($res, 0, 0);
1038  
1039              $sql="select message_id from $table order by datestamp desc limit $start, $length";
1040              $res = mysql_unbuffered_query($sql, $conn);
1041  
1042              if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1043  
1044              $idstring="";
1045              while ($rec = mysql_fetch_row($res)){
1046                  $idstring.="$rec[0],";
1047              }
1048              $idstring=substr($idstring, 0, -1);
1049  
1050          }
1051  
1052      } else { // not using full text matching
1053  
1054          if($match_type=="AUTHOR"){
1055  
1056              $sql_core = "from {$PHORUM['message_table']} where author='$terms' $forum_where $sql_date";
1057  
1058              if($match_date>0){
1059                  $ts=time()-86400*$match_date;
1060                  $sql_core.=" and datestamp>=$ts";
1061              }
1062  
1063              $sql = "select count(*) $sql_core";
1064              $res = mysql_query($sql, $conn);
1065              if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1066              $total_count=mysql_result($res, 0, 0);
1067  
1068  
1069              $sql = "select message_id $sql_core order by datestamp desc limit $start, $length";
1070  
1071              $res = mysql_unbuffered_query($sql, $conn);
1072              if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1073  
1074              $idstring="";
1075              while ($rec = mysql_fetch_row($res)){
1076                  $idstring.="$rec[0],";
1077              }
1078              $idstring=substr($idstring, 0, -1);
1079  
1080          } else {
1081  
1082              if(count($terms)){
1083  
1084                  if($match_type=="ALL"){
1085                      $conj="and";
1086                  } else {
1087                      $conj="or";
1088                  }
1089  
1090                  // quote strings correctly
1091                  foreach ($terms as $id => $term) {
1092                      $terms[$id] = mysql_escape_string($term);
1093                  }
1094  
1095                  $sql_date = "";
1096                  if($match_date>0){
1097                      $ts=time()-86400*$match_date;
1098                      $sql_date =" and datestamp>=$ts";
1099                  }
1100  
1101                  $clause = "( concat(author, ' | ', subject, ' | ', body) like '%".implode("%' $conj concat(author, ' | ', subject, ' | ', body) like '%", $terms)."%' )";
1102  
1103                  $sql = "select count(*) from {$PHORUM['message_table']} where status=".PHORUM_STATUS_APPROVED." and $clause $forum_where $sql_date";
1104                  $res = mysql_query($sql, $conn);
1105  
1106                  if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1107                  $total_count=mysql_result($res, 0, 0);
1108  
1109                  $sql = "select message_id from {$PHORUM['message_table']} where status=".PHORUM_STATUS_APPROVED." and $clause $forum_where $sql_date order by datestamp desc limit $start, $length";
1110                  $res = mysql_unbuffered_query($sql, $conn);
1111                  if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1112  
1113                  $idstring="";
1114                  while ($rec = mysql_fetch_row($res)){
1115                      $idstring.="$rec[0],";
1116                  }
1117                  $idstring=substr($idstring, 0, -1);
1118  
1119              }
1120  
1121          }
1122  
1123      }
1124  
1125      if($idstring){
1126          $sql="select * from {$PHORUM['message_table']} where message_id in ($idstring) order by datestamp desc";
1127          $res = mysql_unbuffered_query($sql, $conn);
1128  
1129          if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1130  
1131          $rows = array();
1132  
1133          while ($rec = mysql_fetch_assoc($res)){
1134              $rows[$rec["message_id"]] = $rec;
1135          }
1136  
1137          $arr = array("count" => $total_count, "rows" => $rows);
1138      }
1139  
1140      return $arr;
1141  }
1142  
1143  /**
1144   * Returns the closest older or newer neighbour thread.
1145   * @param int $key
1146   * @return mixed
1147   */
1148  function phorum_db_get_older_thread($key) {
1149      return phorum_db_get_neighbour_thread($key, "older");
1150  }
1151  function phorum_db_get_newer_thread($key) {
1152      return phorum_db_get_neighbour_thread($key, "newer");
1153  }
1154  function phorum_db_get_neighbour_thread($key, $direction)
1155  {
1156      $PHORUM = $GLOBALS["PHORUM"];
1157  
1158      settype($key, "int");
1159  
1160      $conn = phorum_db_mysql_connect();
1161  
1162      $keyfield = ($PHORUM["float_to_top"]) ? "modifystamp" : "thread";
1163  
1164      switch ($direction) {
1165          case "newer": $compare = ">"; $orderdir = "ASC";  break;
1166          case "older": $compare = "<"; $orderdir = "DESC"; break;
1167          default:
1168              raise_error(
1169                  "phorum_db_get_neighbour_thread(): " .
1170                  "Illegal direction \"".htmlspecialchars($direction)."\"",
1171                  E_USER_ERROR
1172              );
1173      }
1174  
1175      // If the current user is not a moderator for the forum, then
1176      // the neighbour message should be approved.
1177      $approvedval = "";
1178      if (!phorum_user_access_allowed(PHORUM_USER_ALLOW_MODERATE_MESSAGES)) {
1179          $approvedval = "AND status = ".PHORUM_STATUS_APPROVED;
1180      }
1181  
1182      $sql = "select thread from {$PHORUM['message_table']} where forum_id={$PHORUM['forum_id']} and parent_id = 0 $approvedval and $keyfield $compare $key order by $keyfield $orderdir limit 1";
1183  
1184      $res = mysql_query($sql, $conn);
1185      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1186  
1187      return (mysql_num_rows($res)) ? mysql_result($res, 0, "thread") : 0;
1188  }
1189  
1190  /**
1191   * This function executes a query to get bad items of type $type and
1192   * returns an array of the results.
1193   */
1194  
1195  function phorum_db_load_settings(){
1196      global $PHORUM;
1197  
1198  
1199      $conn = phorum_db_mysql_connect();
1200  
1201      $sql = "select * from {$PHORUM['settings_table']}";
1202  
1203      $res = mysql_query($sql, $conn);
1204      if(!$res && !defined("PHORUM_ADMIN")){
1205          if (mysql_errno($conn)==1146){
1206              // settings table does not exist
1207              return;
1208          } elseif(($err = mysql_error($conn))){
1209              phorum_db_mysql_error("$err: $sql");
1210          }
1211      }
1212  
1213      if (empty($err) && $res){
1214          while ($rec = mysql_fetch_assoc($res)){
1215  
1216              // only load the default forum options in the admin
1217              if($rec["name"]=="default_forum_options" && !defined("PHORUM_ADMIN")) continue;
1218  
1219              if ($rec["type"] == "V"){
1220                  if ($rec["data"] == 'true'){
1221                      $val = true;
1222                  }elseif ($rec["data"] == 'false'){
1223                      $val = false;
1224                  }elseif (is_numeric($rec["data"])){
1225                      $val = $rec["data"];
1226                  }else{
1227                      $val = "$rec[data]";
1228                  }
1229              }else{
1230                  $val = unserialize($rec["data"]);
1231              }
1232  
1233              $PHORUM[$rec['name']]=$val;
1234              $PHORUM['SETTINGS'][$rec['name']]=$val;
1235          }
1236      }
1237  }
1238  
1239  /**
1240   * This function executes a query to get bad items of type $type and
1241   * returns an array of the results.
1242   */
1243  
1244  function phorum_db_update_settings($settings){
1245      global $PHORUM;
1246  
1247      if (count($settings) > 0){
1248          $conn = phorum_db_mysql_connect();
1249  
1250          foreach($settings as $field => $value){
1251              if (is_numeric($value)){
1252                  $type = 'V';
1253              }elseif (is_string($value)){
1254                  $value = mysql_escape_string($value);
1255                  $type = 'V';
1256              }else{
1257                  $value = mysql_escape_string(serialize($value));
1258                  $type = 'S';
1259              }
1260  
1261              $field = mysql_escape_string($field);
1262  
1263              $sql = "replace into {$PHORUM['settings_table']} set data='$value', type='$type', name='$field'";
1264              $res = mysql_query($sql, $conn);
1265              if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1266          }
1267  
1268          return ($res > 0) ? true : false;
1269      }else{
1270          trigger_error("\$settings cannot be empty in phorum_db_update_settings()", E_USER_ERROR);
1271      }
1272  }
1273  
1274  /**
1275   * This function executes a query to select all forum data from
1276   * the database for a flat/collapsed display and returns the data in
1277   * an array.
1278   */
1279  
1280  
1281  function phorum_db_get_forums($forum_ids = 0, $parent_id = -1, $vroot = null, $inherit_id = null){
1282      $PHORUM = $GLOBALS["PHORUM"];
1283  
1284      phorum_db_sanitize_mixed($forum_ids, "int");
1285      settype($parent_id, "int");
1286      if($vroot != null) settype($vroot, "int");
1287      if($inherit_id != null) settype($inherit_id, "int");
1288  
1289      $conn = phorum_db_mysql_connect();
1290  
1291      if (is_array($forum_ids)) {
1292          $int_ids = array();
1293          foreach ($forum_ids as $id) {
1294              settype($id, "int");
1295              $int_ids[] = $id;
1296          }
1297          $forum_ids = implode(",", $int_ids);
1298      } else {
1299          settype($forum_ids, "int");
1300      }
1301  
1302      $sql = "select * from {$PHORUM['forums_table']} ";
1303      if ($forum_ids){
1304          $sql .= " where forum_id in ($forum_ids)";
1305      } elseif ($inherit_id !== null) {
1306          $sql .= " where inherit_id = $inherit_id";
1307          if(!defined("PHORUM_ADMIN")) $sql.=" and active=1";
1308      } elseif ($parent_id >= 0) {
1309          $sql .= " where parent_id = $parent_id";
1310          if(!defined("PHORUM_ADMIN")) $sql.=" and active=1";
1311      }  elseif($vroot !== null) {
1312          $sql .= " where vroot = $vroot";
1313      } else {
1314          $sql .= " where forum_id <> 0";
1315      }
1316  
1317      $sql .= " order by display_order ASC, name";
1318  
1319      $res = mysql_query($sql, $conn);
1320      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1321  
1322      $forums = array();
1323  
1324      while ($row = mysql_fetch_assoc($res)){
1325          $forums[$row["forum_id"]] = $row;
1326      }
1327  
1328      return $forums;
1329  }
1330  
1331  /**
1332   * This function updates the forums stats.  If refresh is true, it pulls the
1333   * numbers from the table.
1334   */
1335  
1336  function phorum_db_update_forum_stats($refresh=false, $msg_count_change=0, $timestamp=0, $thread_count_change=0, $sticky_count_change=0)
1337  {
1338      $PHORUM = $GLOBALS["PHORUM"];
1339  
1340      settype($refresh, "bool");
1341      settype($msg_count_change, "int");
1342      settype($timestamp, "int");
1343      settype($thread_count_change, "int");
1344      settype($sticky_count_change, "int");
1345  
1346      $conn = phorum_db_mysql_connect();
1347  
1348      // always refresh on small forums
1349      if (isset($PHORUM["message_count"]) && $PHORUM["message_count"]<1000) {
1350          $refresh=true;
1351      }
1352  
1353      if($refresh || empty($msg_count_change)){
1354          $sql = "select count(*) as message_count from {$PHORUM['message_table']} where forum_id={$PHORUM['forum_id']} and status=".PHORUM_STATUS_APPROVED;
1355  
1356          $res = mysql_query($sql, $conn);
1357          if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1358  
1359          $message_count = (int)mysql_result($res, 0, "message_count");
1360      } else {
1361          $message_count="message_count+$msg_count_change";
1362      }
1363  
1364      if($refresh || empty($timestamp)){
1365  
1366          $sql = "select max(modifystamp) as last_post_time from {$PHORUM['message_table']} where status=".PHORUM_STATUS_APPROVED." and forum_id={$PHORUM['forum_id']}";
1367  
1368          $res = mysql_query($sql, $conn);
1369          if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1370  
1371          $last_post_time = (int)mysql_result($res, 0, "last_post_time");
1372      } else {
1373  
1374          $last_post_time = $timestamp;
1375      }
1376  
1377      if($refresh || empty($thread_count_change)){
1378  
1379          $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;
1380          $res = mysql_query($sql, $conn);
1381          if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1382          $thread_count = (int)mysql_result($res, 0, "thread_count");
1383  
1384      } else {
1385  
1386          $thread_count="thread_count+$thread_count_change";
1387      }
1388  
1389      if($refresh || empty($sticky_count_change)){
1390  
1391          $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;
1392          $res = mysql_query($sql, $conn);
1393          if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1394          $sticky_count = (int)mysql_result($res, 0, "sticky_count");
1395  
1396      } else {
1397  
1398          $sticky_count="sticky_count+$sticky_count_change";
1399      }
1400  
1401      $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']}";
1402      mysql_query($sql, $conn);
1403      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1404  
1405  }
1406  
1407  /**
1408   * actually moves a thread to the given forum
1409   */
1410  function phorum_db_move_thread($thread_id, $toforum)
1411  {
1412      $PHORUM = $GLOBALS["PHORUM"];
1413  
1414      settype($thread_id, "int");
1415      settype($toforum, "int");
1416  
1417      if($toforum > 0 && $thread_id > 0){
1418          $conn = phorum_db_mysql_connect();
1419          // retrieving the messages for the newflags and search updates below
1420          $thread_messages=phorum_db_get_messages($thread_id);
1421  
1422          // just changing the forum-id, simple isn't it?
1423          $sql = "UPDATE {$PHORUM['message_table']} SET forum_id=$toforum where thread=$thread_id";
1424  
1425          $res = mysql_query($sql, $conn);
1426          if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1427  
1428          // we need to update the number of posts in the current forum
1429          phorum_db_update_forum_stats(true);
1430  
1431          // and of the new forum
1432          $old_id=$GLOBALS["PHORUM"]["forum_id"];
1433          $GLOBALS["PHORUM"]["forum_id"]=$toforum;
1434          phorum_db_update_forum_stats(true);
1435          $GLOBALS["PHORUM"]["forum_id"]=$old_id;
1436  
1437          // move the new-flags and the search records for this thread
1438          // to the new forum too
1439          unset($thread_messages['users']);
1440  
1441          $new_newflags=phorum_db_newflag_get_flags($toforum);
1442          $message_ids = array();
1443          $delete_ids = array();
1444          $search_ids = array();
1445          foreach($thread_messages as $mid => $data) {
1446              // gather information for updating the newflags
1447              if($mid > $new_newflags['min_id']) { // only using it if its higher than min_id
1448                  $message_ids[]=$mid;
1449              } else { // newflags to delete
1450                  $delete_ids[]=$mid;
1451              }
1452  
1453              // gather the information for updating the search table
1454              $search_ids[] = $mid;
1455          }
1456  
1457          if(count($message_ids)) { // we only go in if there are messages ... otherwise an error occured
1458  
1459              phorum_db_newflag_update_forum($message_ids);
1460  
1461              $ids_str=implode(",",$message_ids);
1462  
1463              // then doing the update to subscriptions
1464              $sql="UPDATE {$PHORUM['subscribers_table']} SET forum_id = $toforum where thread IN($ids_str)";
1465              $res = mysql_query($sql, $conn);
1466              if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1467  
1468          }
1469  
1470          if(count($delete_ids)) {
1471              $ids_str=implode(",",$delete_ids);
1472              // then doing the delete
1473              $sql="DELETE FROM {$PHORUM['user_newflags_table']} where message_id IN($ids_str)";
1474              mysql_query($sql, $conn);
1475              if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1476          }
1477  
1478          if (count($search_ids)) {
1479              $ids_str = implode(",",$search_ids);
1480              // then doing the search table update
1481              $sql = "UPDATE {$PHORUM['search_table']} set forum_id = $toforum where message_id in ($ids_str)";
1482              mysql_query($sql, $conn);
1483              if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1484          }
1485  
1486      }
1487  }
1488  
1489  /**
1490   * closes the given thread
1491   */
1492  function phorum_db_close_thread($thread_id){
1493      $PHORUM = $GLOBALS["PHORUM"];
1494  
1495      settype($thread_id, "int");
1496  
1497      if($thread_id > 0){
1498          $conn = phorum_db_mysql_connect();
1499  
1500          $sql = "UPDATE {$PHORUM['message_table']} SET closed=1 where thread=$thread_id";
1501  
1502          $res = mysql_query($sql, $conn);
1503          if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1504      }
1505  }
1506  
1507  /**
1508   * (re)opens the given thread
1509   */
1510  function phorum_db_reopen_thread($thread_id){
1511      $PHORUM = $GLOBALS["PHORUM"];
1512  
1513      settype($thread_id, "int");
1514  
1515      if($thread_id > 0){
1516          $conn = phorum_db_mysql_connect();
1517  
1518          $sql = "UPDATE {$PHORUM['message_table']} SET closed=0 where thread=$thread_id";
1519  
1520          $res = mysql_query($sql, $conn);
1521          if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1522      }
1523  }
1524  
1525  /**
1526   * This function executes a query to insert a forum into the forums
1527   * table and returns the forums id on success or 0 on failure.
1528   */
1529  
1530  function phorum_db_add_forum($forum)
1531  {
1532      $PHORUM = $GLOBALS["PHORUM"];
1533  
1534      $conn = phorum_db_mysql_connect();
1535  
1536      foreach($forum as $key => $value){
1537          if(phorum_db_validate_field($key)){
1538              if (is_numeric($value)){
1539                  $value = (int)$value;
1540                  $fields[] = "$key=$value";
1541              } elseif($value=="NULL") {
1542                  $fields[] = "$key=$value";
1543              }else{
1544                  $value = mysql_escape_string($value);
1545                  $fields[] = "$key='$value'";
1546              }
1547          }
1548      }
1549  
1550      $sql = "insert into {$PHORUM['forums_table']} set " . implode(", ", $fields);
1551  
1552      $res = mysql_query($sql, $conn);
1553      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1554  
1555      $forum_id = 0;
1556  
1557      if ($res){
1558          $forum_id = mysql_insert_id($conn);
1559      }
1560  
1561      return $forum_id;
1562  }
1563  
1564  /**
1565   * This function executes a query to remove a forum from the forums
1566   * table and its messages.
1567   */
1568  
1569  function phorum_db_drop_forum($forum_id)
1570  {
1571      $PHORUM = $GLOBALS["PHORUM"];
1572  
1573      settype($forum_id, "int");
1574  
1575      $conn = phorum_db_mysql_connect();
1576  
1577      $tables = array (
1578          $PHORUM['message_table'],
1579          $PHORUM['user_permissions_table'],
1580          $PHORUM['user_newflags_table'],
1581          $PHORUM['subscribers_table'],
1582          $PHORUM['forum_group_xref_table'],
1583          $PHORUM['forums_table'],
1584          $PHORUM['banlist_table'],
1585          $PHORUM['search_table']
1586      );
1587  
1588      foreach($tables as $table){
1589          $sql = "delete from $table where forum_id=$forum_id";
1590          $res = mysql_query($sql, $conn);
1591          if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1592      }
1593  
1594  $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";
1595      $res = mysql_query($sql, $conn);
1596      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1597      while($rec=mysql_fetch_assoc($res)){
1598          $files[]=$rec["file_id"];
1599      }
1600      if(isset($files)){
1601          $sql = "delete from {$PHORUM['files_table']} where file_id in (".implode(",", $files).")";
1602          $res = mysql_query($sql, $conn);
1603          if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1604      }
1605  
1606  
1607  }
1608  
1609  /**
1610   * This function executes a query to remove a folder from the forums
1611   * table and change the parent of its children.
1612   */
1613  
1614  function phorum_db_drop_folder($forum_id)
1615  {
1616      $PHORUM = $GLOBALS["PHORUM"];
1617  
1618      settype($forum_id, "int");
1619  
1620      $conn = phorum_db_mysql_connect();
1621  
1622      $sql = "select parent_id from {$PHORUM['forums_table']} where forum_id=$forum_id";
1623  
1624      $res = mysql_query($sql, $conn);
1625      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1626  
1627      $new_parent_id = mysql_result($res, 0, "parent_id");
1628  
1629      $sql = "update {$PHORUM['forums_table']} set parent_id=$new_parent_id where parent_id=$forum_id";
1630  
1631      $res = mysql_query($sql, $conn);
1632      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1633  
1634      $sql = "delete from {$PHORUM['forums_table']} where forum_id=$forum_id";
1635  
1636      $res = mysql_query($sql, $conn);
1637      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1638  }
1639  
1640  /**
1641   * This function executes a query to update a forum in the forums
1642   * table and returns non zero on success or 0 on failure.
1643   */
1644  
1645  function phorum_db_update_forum($forum){
1646      $PHORUM = $GLOBALS["PHORUM"];
1647  
1648      $res = 0;
1649  
1650      if (!empty($forum["forum_id"])){
1651  
1652          phorum_db_sanitize_mixed($forum["forum_id"], "int");
1653  
1654          // this way we can also update multiple forums at once
1655          if(is_array($forum["forum_id"])) {
1656              $forumwhere="forum_id IN (".implode(",",$forum["forum_id"]).")";
1657          } else {
1658              $forumwhere="forum_id=".$forum["forum_id"];
1659          }
1660  
1661          unset($forum["forum_id"]);
1662  
1663          $conn = phorum_db_mysql_connect();
1664  
1665          foreach($forum as $key => $value){
1666              if(phorum_db_validate_field($key)){
1667                  if (is_numeric($value)){
1668                      $value = (int)$value;
1669                      $fields[] = "$key=$value";
1670                  } elseif($value=="NULL") {
1671                      $fields[] = "$key=$value";
1672                  } else {
1673                      $value = mysql_escape_string($value);
1674                      $fields[] = "$key='$value'";
1675                  }
1676              }
1677          }
1678  
1679          $sql = "update {$PHORUM['forums_table']} set " . implode(", ", $fields) . " where $forumwhere";
1680  
1681          $res = mysql_query($sql, $conn);
1682          if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1683      }else{
1684          trigger_error("\$forum[forum_id] cannot be empty in phorum_update_forum()", E_USER_ERROR);
1685      }
1686  
1687      return $res;
1688  }
1689  
1690  /**
1691  *
1692  */
1693  
1694  function phorum_db_get_groups($group_id=0)
1695  {
1696      $PHORUM = $GLOBALS["PHORUM"];
1697      $conn = phorum_db_mysql_connect();
1698  
1699      phorum_db_sanitize_mixed($group_id,"int");
1700  
1701  
1702      if(is_array($group_id) && count($group_id)) {
1703          $group_str=implode(',',$group_id);
1704          $where_str=" where group_id IN($group_str)";
1705      } elseif(!is_array($group_id) && $group_id!=0) {
1706          $where_str=" where group_id=$group_id";
1707      } else {
1708          $where_str="";
1709      }
1710  
1711      $sql="select * from {$PHORUM['groups_table']}".$where_str;
1712  
1713  
1714      $res = mysql_query($sql, $conn);
1715      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1716  
1717      $groups=array();
1718      while($rec=mysql_fetch_assoc($res)){
1719  
1720          $groups[$rec["group_id"]]=$rec;
1721          $groups[$rec["group_id"]]["permissions"]=array();
1722      }
1723  
1724      $sql="select * from {$PHORUM['forum_group_xref_table']}".$where_str;
1725  
1726      $res = mysql_query($sql, $conn);
1727      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1728  
1729      while($rec=mysql_fetch_assoc($res)){
1730  
1731          $groups[$rec["group_id"]]["permissions"][$rec["forum_id"]]=$rec["permission"];
1732  
1733      }
1734  
1735      return $groups;
1736  
1737  }
1738  
1739  /**
1740  * Get the members of a group.
1741  * @param group_id - can be an integer (single group), or an array of groups
1742  * @param status - a specific status to look for, defaults to all
1743  * @return array - users (key is userid, value is group membership status)
1744  */
1745  
1746  function phorum_db_get_group_members($group_id, $status = NULL)
1747  {
1748      $PHORUM = $GLOBALS["PHORUM"];
1749      $conn = phorum_db_mysql_connect();
1750  
1751      phorum_db_sanitize_mixed($group_id, "int");
1752      if ($status !== NULL) settype($status, "int");
1753  
1754      if(is_array($group_id)){
1755          $group_id=implode(",", $group_id);
1756      }
1757  
1758      // this join is only here so that the list of users comes out sorted
1759      // if phorum_db_user_get() sorts results itself, this join can go away
1760      $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)";
1761      if ($status !== NULL) $sql.=" and {$PHORUM['user_group_xref_table']}.status = $status";
1762      $sql .=" order by username asc";
1763  
1764      $res = mysql_query($sql, $conn);
1765      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1766      $users=array();
1767      while($rec=mysql_fetch_assoc($res)){
1768          $users[$rec["user_id"]]=$rec["status"];
1769      }
1770  
1771      return $users;
1772  
1773  }
1774  
1775  /**
1776  *
1777  */
1778  
1779  function phorum_db_save_group($group)
1780  {
1781      $PHORUM = $GLOBALS["PHORUM"];
1782      $conn = phorum_db_mysql_connect();
1783  
1784      $ret=false;
1785  
1786      $permissions = $group["permissions"];
1787      phorum_db_sanitize_mixed($group, "string");
1788      $group["permissions"] = $permissions;
1789  
1790      if(isset($group["name"])){
1791          $sql="update {$PHORUM['groups_table']} set name='{$group['name']}', open={$group['open']} where group_id={$group['group_id']}";
1792  
1793          $res=mysql_query($sql, $conn);
1794  
1795          if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1796  
1797      }
1798  
1799      if(!$err){
1800  
1801          if(isset($group["permissions"])){
1802              $sql="delete from {$PHORUM['forum_group_xref_table']} where group_id={$group['group_id']}";
1803  
1804              $res=mysql_query($sql, $conn);
1805  
1806              if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1807  
1808              foreach($group["permissions"] as $forum_id=>$permission){
1809                  settype($forum_id, "int");
1810                  settype($permission, "int");
1811                  $sql="insert into {$PHORUM['forum_group_xref_table']} set group_id={$group['group_id']}, permission=$permission, forum_id=$forum_id";
1812                  $res=mysql_query($sql, $conn);
1813                  if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1814                  if(!$res) break;
1815              }
1816          }
1817      }
1818  
1819      if($res>0) $ret=true;
1820  
1821      return $ret;
1822  
1823  }
1824  
1825  function phorum_db_delete_group($group_id)
1826  {
1827      $PHORUM = $GLOBALS["PHORUM"];
1828      $conn = phorum_db_mysql_connect();
1829  
1830      settype($group_id, "int");
1831  
1832      $sql = "delete from {$PHORUM['groups_table']} where group_id = $group_id";
1833      $res = mysql_query($sql, $conn);
1834      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1835  
1836      // delete things associated with groups
1837      $sql = "delete from {$PHORUM['user_group_xref_table']} where group_id = $group_id";
1838      $res = mysql_query($sql, $conn);
1839      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1840  
1841      $sql = "delete from {$PHORUM['forum_group_xref_table']} where group_id = $group_id";
1842      $res = mysql_query($sql, $conn);
1843      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1844  }
1845  
1846  /**
1847   * phorum_db_add_group()
1848   *
1849   * @param $group_name $group_id
1850   * @return
1851   **/
1852  function phorum_db_add_group($group_name,$group_id=0)
1853  {
1854      $PHORUM = $GLOBALS["PHORUM"];
1855      $conn = phorum_db_mysql_connect();
1856  
1857      settype($group_id, "int");
1858      $group_name = mysql_escape_string($group_name);
1859  
1860      if($group_id > 0) { // only used in conversion
1861          $sql="insert into {$PHORUM['groups_table']} (group_id,name) values ($group_id,'$group_name')";
1862      } else {
1863          $sql="insert into {$PHORUM['groups_table']} (name) values ('$group_name')";
1864      }
1865  
1866      $res = mysql_query($sql, $conn);
1867  
1868      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1869  
1870      $group_id = 0;
1871  
1872      if ($res) {
1873          $group_id = mysql_insert_id($conn);
1874      }
1875  
1876      return $group_id;
1877  }
1878  
1879  /**
1880  * This function returns all moderators for a particular forum
1881  */
1882  function phorum_db_user_get_moderators($forum_id,$ignore_user_perms=false,$for_email=false) {
1883  
1884     $PHORUM = $GLOBALS["PHORUM"];
1885     $userinfo=array();
1886  
1887     $conn = phorum_db_mysql_connect();
1888  
1889     settype($forum_id, "int");
1890     settype($ignore_user_perms, "bool");
1891     settype($for_email, "bool");
1892  
1893     if(!$ignore_user_perms) { // sometimes we just don't need them
1894         if(!$PHORUM['email_ignore_admin']) {
1895              $admincheck=" OR user.admin=1";
1896         } else {
1897              $admincheck="";
1898         }
1899  
1900  
1901         $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";
1902  
1903  
1904         $res = mysql_query($sql, $conn);
1905  
1906         if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1907  
1908         while ($row = mysql_fetch_row($res)){
1909             if(!$for_email || $row[2] == 1)
1910                  $userinfo[$row[0]]=$row[1];
1911         }
1912  
1913     }
1914  
1915     // get users who belong to groups that have moderator access
1916     $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;
1917  
1918     $res = mysql_query($sql, $conn);
1919  
1920     if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1921  
1922     while ($row = mysql_fetch_row($res)){
1923         if(!$for_email || $row[2] == 1)
1924             $userinfo[$row[0]]=$row[1];
1925     }
1926     return $userinfo;
1927  }
1928  
1929  /**
1930   * This function executes a query to select data about a user including
1931   * his permission data and returns that in an array.
1932   */
1933  
1934  function phorum_db_user_get($user_id, $detailed)
1935  {
1936      $PHORUM = $GLOBALS["PHORUM"];
1937  
1938      $conn = phorum_db_mysql_connect();
1939  
1940      phorum_db_sanitize_mixed($user_id, "int");
1941  
1942      if(is_array($user_id)){
1943          if (count($user_id)) {
1944              $user_ids=implode(",", $user_id);
1945          } else {
1946              return array();
1947          }
1948      } else {
1949          $user_ids=(int)$user_id;
1950      }
1951  
1952      $users = array();
1953  
1954      $sql = "select * from {$PHORUM['user_table']} where user_id in ($user_ids)";
1955      $res = mysql_query($sql, $conn);
1956      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1957  
1958      if (mysql_num_rows($res)){
1959          while($rec=mysql_fetch_assoc($res)){
1960              $users[$rec["user_id"]] = $rec;
1961          }
1962  
1963          if ($detailed){
1964              // get the users' permissions
1965              $sql = "select * from {$PHORUM['user_permissions_table']} where user_id in ($user_ids)";
1966  
1967              $res = mysql_query($sql, $conn);
1968              if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1969  
1970              while ($row = mysql_fetch_assoc($res)){
1971                  $users[$row["user_id"]]["forum_permissions"][$row["forum_id"]] = $row["permission"];
1972              }
1973  
1974              // get the users' groups and forum permissions through those groups
1975              $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;
1976  
1977              $res = mysql_query($sql, $conn);
1978              if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1979  
1980              while ($row = mysql_fetch_assoc($res)){
1981                  $users[$row["user_id"]]["groups"][$row["group_id"]] = $row["group_id"];
1982                  if(!empty($row["forum_id"])){
1983                      if(!isset($users[$row["user_id"]]["group_permissions"][$row["forum_id"]])) {
1984                           $users[$row["user_id"]]["group_permissions"][$row["forum_id"]] = 0;
1985                      }
1986                      $users[$row["user_id"]]["group_permissions"][$row["forum_id"]] = $users[$row["user_id"]]["group_permissions"][$row["forum_id"]] | $row["permission"];
1987                  }
1988              }
1989  
1990          }
1991          $sql = "select * from {$PHORUM['user_custom_fields_table']} where user_id in ($user_ids)";
1992          $res = mysql_query($sql, $conn);
1993          if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
1994  
1995          while ($row = mysql_fetch_assoc($res)){
1996              if(isset($PHORUM["PROFILE_FIELDS"][$row['type']])) {
1997                  if($PHORUM["PROFILE_FIELDS"][$row['type']]['html_disabled']) {
1998                      $users[$row["user_id"]][$PHORUM["PROFILE_FIELDS"][$row['type']]['name']] = htmlspecialchars($row["data"]);
1999                  } else { // not html-disabled
2000                      if(substr($row["data"],0,6) == 'P_SER:') {
2001                          // P_SER (PHORUM_SERIALIZED) is our marker telling this field is serialized
2002                          $users[$row["user_id"]][$PHORUM["PROFILE_FIELDS"][$row['type']]['name']] = unserialize(substr($row["data"],6));
2003                      } else {
2004                          $users[$row["user_id"]][$PHORUM["PROFILE_FIELDS"][$row['type']]['name']] = $row["data"];
2005                      }
2006                  }
2007              }
2008          }
2009  
2010      }
2011  
2012      if(is_array($user_id)){
2013          return $users;
2014      } else {
2015          return isset($users[$user_id]) ? $users[$user_id] : NULL;
2016      }
2017  
2018  }
2019  
2020  /*
2021   * Generic function to retrieve a couple of fields from the user-table
2022   * for a couple of users or only one of them
2023   *
2024   * result is always an array with one or more users in it
2025   */
2026  
2027  function phorum_db_user_get_fields($user_id, $fields)
2028  {
2029      $PHORUM = $GLOBALS["PHORUM"];
2030  
2031      $conn = phorum_db_mysql_connect();
2032  
2033      phorum_db_sanitize_mixed($user_id, "int");
2034  
2035      if(is_array($user_id)){
2036          $user_ids=implode(",", $user_id);
2037      } else {
2038          $user_ids=(int)$user_id;
2039      }
2040  
2041      if(!is_array($fields)) {
2042          $fields = array($fields);
2043      }
2044  
2045      $users = array();
2046  
2047      foreach($fields as $key=>$field){
2048          if(!phorum_db_validate_field($field)){
2049              unset($fields[$key]);
2050          }
2051      }
2052  
2053  
2054      $sql = "select user_id, ".implode(",", $fields)." from {$PHORUM['user_table']} where user_id in ($user_ids)";
2055  
2056      $res = mysql_query($sql, $conn);
2057      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
2058  
2059      if (mysql_num_rows($res)){
2060          while($rec=mysql_fetch_assoc($res)){
2061              $users[$rec["user_id"]] = $rec;
2062          }
2063      }
2064  
2065      return $users;
2066  
2067  }
2068  
2069  /**
2070   * Get a list of all users of a certain type.
2071   *
2072   * @param $type - what type of list to retrieve.
2073   *                0 = all users
2074   *                1 = all active users
2075   *                2 = all inactive users
2076   * @return array - key: userid, value: array (username, displayname)
2077   */
2078  function phorum_db_user_get_list($type = 0){
2079     $PHORUM = $GLOBALS["PHORUM"];
2080  
2081     settype($type, "int");
2082  
2083     $conn = phorum_db_mysql_connect();
2084  
2085     $where = '';
2086     if ($type == 1) $where = "where active = 1";
2087     elseif ($type == 2) $where = "where active != 1";
2088  
2089     $users = array();
2090     $sql = "select user_id, username from {$PHORUM['user_table']} $where order by username asc";
2091     $res = mysql_query($sql, $conn);
2092     if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
2093  
2094     while ($row = mysql_fetch_assoc($res)){
2095         $users[$row["user_id"]] = array("username" => $row["username"], "displayname" => $row["username"]);
2096     }
2097  
2098     return $users;
2099  }
2100  
2101  /**
2102   * This function executes a query to select data about a user including
2103   * his permission data and returns that in an array.
2104   */
2105  
2106  function phorum_db_user_check_pass($username, $password, $temp_password=false){
2107      $PHORUM = $GLOBALS["PHORUM"];
2108  
2109      $conn = phorum_db_mysql_connect();
2110  
2111      settype($temp_password, "bool");
2112  
2113      $username = mysql_escape_string($username);
2114  
2115      $password = mysql_escape_string($password);
2116  
2117      $pass_field = ($temp_password) ? "password_temp" : "password";
2118  
2119      $sql = "select user_id from {$PHORUM['user_table']} where username='$username' and $pass_field='$password'";
2120  
2121      $res = mysql_query($sql, $conn);
2122      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
2123  
2124      return ($res && mysql_num_rows($res)) ? mysql_result($res, 0, "user_id") : 0;
2125  }
2126  
2127  /**
2128   * This function executes a query to check for the given field in the
2129   * user tableusername and return the user_id of the user it matches or 0
2130   * if no match is found.
2131   *
2132   * The parameters can be arrays.  If they are, all must be passed and all
2133   * must have the same number of values.
2134   *
2135   * If $return_array is true, an array of all matching rows will be returned.
2136   * Otherwise, only the first user_id from the results will be returned.
2137   */
2138  
2139  function phorum_db_user_check_field($field, $value, $operator="=", $return_array=false)
2140  {
2141      $PHORUM = $GLOBALS["PHORUM"];
2142  
2143      $ret = 0;
2144  
2145      settype($return_array, "bool");
2146  
2147      $conn = phorum_db_mysql_connect();
2148  
2149      if(!is_array($field)){
2150          $field=array($field);
2151      }
2152  
2153      if(!is_array($value)){
2154          $value=array($value);
2155      }
2156  
2157      if(!is_array($operator)){
2158          $operator=array($operator);
2159      }
2160  
2161      if(count($field)!=count($value) || count($field)!=count($operator) || count($operator)!=count($value)){
2162          return $ret;
2163      }
2164  
2165  
2166  
2167      $valid_operators = array("=", "<>", "!=", ">", "<", ">=", "<=");
2168  
2169      foreach($field as $key=>$name){
2170          if(in_array($operator[$key], $valid_operators) && phorum_db_validate_field($name)){
2171              $value[$key] = mysql_escape_string($value[$key]);
2172              $clauses[]="$name $operator[$key] '$value[$key]'";
2173          }
2174      }
2175  
2176      $sql = "select user_id from {$PHORUM['user_table']} where ".implode(" and ", $clauses);
2177  
2178      $res = mysql_query($sql, $conn);
2179      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
2180  
2181      if ($res && mysql_num_rows($res)){
2182          if($return_array){
2183              $ret=array();
2184              while($row=mysql_fetch_assoc($res)){
2185                  $ret[$row["user_id"]]=$row["user_id"];
2186              }
2187          } else {
2188              $ret = mysql_result($res, 0, "user_id");
2189          }
2190      }
2191  
2192      return $ret;
2193  }
2194  
2195  
2196  /**
2197   * This function executes a query to add the given user data to the
2198   * database and returns the userid or 0
2199   */
2200  
2201  function phorum_db_user_add($userdata){
2202      $PHORUM = $GLOBALS["PHORUM"];
2203  
2204      $conn = phorum_db_mysql_connect();
2205  
2206      if (isset($userdata["forum_permissions"]) && !empty($userdata["forum_permissions"])){
2207          $forum_perms = $userdata["forum_permissions"];
2208          unset($userdata["forum_permissions"]);
2209      }
2210  
2211      if (isset($userdata["user_data"]) && !empty($userdata["user_data"])){
2212          $user_data = $userdata["user_data"];
2213          unset($userdata["user_data"]);
2214      }
2215  
2216  
2217      $sql = "insert into {$PHORUM['user_table']} set ";
2218  
2219      $values = array();
2220  
2221      foreach($userdata as $key => $value){
2222          if (phorum_db_validate_field($key)){
2223              if (!is_numeric($value)){
2224                  $value = mysql_escape_string($value);
2225                  $values[] = "$key='$value'";
2226              }else{
2227                  $values[] = "$key=$value";
2228              }
2229          }
2230      }
2231  
2232      $sql .= implode(", ", $values);
2233  
2234      $res = mysql_query($sql, $conn);
2235      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
2236  
2237      $user_id = 0;
2238      if ($res){
2239          $user_id = mysql_insert_id($conn);
2240      }
2241  
2242      if ($res){
2243          if(isset($forum_perms)) {
2244              // storing forum-permissions
2245              foreach($forum_perms as $fid => $p){
2246                  $sql = "insert into {$PHORUM['user_permissions_table']} set user_id=$user_id, forum_id=$fid, permission=$p";
2247                  $res = mysql_query($sql, $conn);
2248                  if ($err = mysql_error($conn)){
2249                      phorum_db_mysql_error("$err: $sql");
2250                      break;
2251                  }
2252              }
2253          }
2254          if(isset($user_data)) {
2255              /* storing custom-fields */
2256              foreach($user_data as $key => $val){
2257                  if(is_array($val)) { /* arrays need to be serialized */
2258                      $val = 'P_SER:'.serialize($val);
2259                      /* P_SER: (PHORUM_SERIALIZED is our marker telling this Field is serialized */
2260                  } else { /* other vars need to be escaped */
2261                      $val = mysql_escape_string($val);
2262                  }
2263                  $sql = "insert into {$PHORUM['user_custom_fields_table']} (user_id,type,data) VALUES($user_id,$key,'$val')";
2264                  $res = mysql_query($sql, $conn);
2265                  if ($err = mysql_error($conn)){
2266                      phorum_db_mysql_error("$err: $sql");
2267                      break;
2268                  }
2269              }
2270          }
2271      }
2272  
2273      return $user_id;
2274  }
2275  
2276  
2277  /**
2278   * This function executes a query to update the given user data in the
2279   * database and returns the true or false
2280   */
2281  function phorum_db_user_save($userdata){
2282      $PHORUM = $GLOBALS["PHORUM"];
2283  
2284      $conn = phorum_db_mysql_connect();
2285  
2286      if(isset($userdata["permissions"])){
2287          unset($userdata["permissions"]);
2288      }
2289  
2290      if (isset($userdata["forum_permissions"])){
2291          $forum_perms = $userdata["forum_permissions"];
2292          unset($userdata["forum_permissions"]);
2293      }
2294  
2295      if (isset($userdata["groups"])){
2296          $groups = $userdata["groups"];
2297          unset($userdata["groups"]);
2298          unset($userdata["group_permissions"]);
2299      }
2300      if (isset($userdata["user_data"])){
2301          $user_data = $userdata["user_data"];
2302          unset($userdata["user_data"]);
2303      }
2304  
2305      $user_id = $userdata["user_id"];
2306      unset($userdata["user_id"]);
2307  
2308      if(count($userdata)){
2309  
2310          $sql = "update {$PHORUM['user_table']} set ";
2311  
2312          $values = array();
2313  
2314          foreach($userdata as $key => $value){
2315              $values[] = "$key='".mysql_escape_string($value)."'";
2316          }
2317  
2318          $sql .= implode(", ", $values);
2319  
2320          $sql .= " where user_id=$user_id";
2321  
2322          $res = mysql_query($sql, $conn);
2323          if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
2324      }
2325  
2326      if (isset($forum_perms)){
2327  
2328          $sql = "delete from {$PHORUM['user_permissions_table']} where user_id = $user_id";
2329          $res=mysql_query($sql, $conn);
2330          if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
2331  
2332          foreach($forum_perms as $fid=>$perms){
2333              $sql = "insert into {$PHORUM['user_permissions_table']} set user_id=$user_id, forum_id=$fid, permission=$perms";
2334              $res = mysql_query($sql, $conn);
2335              if ($err = mysql_error($conn)){
2336                  phorum_db_mysql_error("$err: $sql");
2337              }
2338          }
2339      }
2340      if(isset($user_data)) {
2341          // storing custom-fields
2342          $sql = "delete from {$PHORUM['user_custom_fields_table']} where user_id = $user_id";
2343          $res=mysql_query($sql, $conn);
2344          if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
2345  
2346          if(is_array($user_data)) {
2347              foreach($user_data as $key => $val){
2348                  if(is_array($val)) { /* arrays need to be serialized */
2349                      $val = 'P_SER:'.serialize($val);
2350                      /* P_SER: (PHORUM_SERIALIZED is our marker telling this Field is serialized */
2351                  } else { /* other vars need to be escaped */
2352                      $val = mysql_escape_string($val);
2353                  }
2354  
2355                  $sql = "insert into {$PHORUM['user_custom_fields_table']} (user_id,type,data) VALUES($user_id,$key,'$val')";
2356                  $res = mysql_query($sql, $conn);
2357                  if ($err = mysql_error($conn)){
2358                      phorum_db_mysql_error("$err: $sql");
2359                      break;
2360                  }
2361              }
2362          }
2363      }
2364  
2365      return (bool)$res;
2366  }
2367  
2368  /**
2369   * This function saves a users group permissions.
2370   */
2371  function phorum_db_user_save_groups($user_id, $groups)
2372  {
2373      $PHORUM = $GLOBALS["PHORUM"];
2374  
2375      settype($user_id, "int");
2376  
2377      if (!$user_id > 0){
2378          return false;
2379      }
2380  
2381      // erase the group memberships they have now
2382      $conn = phorum_db_mysql_connect();
2383      $sql = "delete from {$PHORUM['user_group_xref_table']} where user_id = $user_id";
2384      $res=mysql_query($sql, $conn);
2385      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
2386  
2387      foreach($groups as $group_id => $group_perm){
2388          $group_id = (int)$group_id;
2389          $group_perm = (int)$group_perm;
2390          $sql = "insert into {$PHORUM['user_group_xref_table']} set user_id=$user_id, group_id=$group_id, status=$group_perm";
2391          mysql_query($sql, $conn);
2392          if ($err = mysql_error($conn)){
2393              phorum_db_mysql_error("$err: $sql");
2394              break;
2395          }
2396      }
2397      return (bool)$res;
2398  }
2399  
2400  /**
2401   * This function executes a query to subscribe a user to a forum/thread.
2402   */
2403  
2404  function phorum_db_user_subscribe($user_id, $forum_id, $thread, $type)
2405  {
2406      $PHORUM = $GLOBALS["PHORUM"];
2407  
2408      settype($user_id, "int");
2409      settype($forum_id, "int");
2410      settype($thread, "int");
2411      settype($type, "int");
2412  
2413      $conn = phorum_db_mysql_connect();
2414  
2415      $sql = "replace into {$PHORUM['subscribers_table']} set user_id=$user_id, forum_id=$forum_id, sub_type=$type, thread=$thread";
2416  
2417      $res = mysql_query($sql, $conn);
2418  
2419      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
2420  
2421      return (bool)$res;
2422  }
2423  
2424  /**
2425    * This function increases the post-counter for a user by one
2426    */
2427  function phorum_db_user_addpost() {
2428  
2429          $conn = phorum_db_mysql_connect();
2430  
2431          $sql="UPDATE ".$GLOBALS['PHORUM']['user_table']." SET posts=posts+1 WHERE user_id = ".$GLOBALS['PHORUM']['user']['user_id'];
2432          $res=mysql_query($sql,$conn);
2433  
2434          if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
2435  
2436          return (bool)$res;
2437  }
2438  
2439  /**
2440   * This function executes a query to unsubscribe a user to a forum/thread.
2441   */
2442  
2443  function phorum_db_user_unsubscribe($user_id, $thread, $forum_id=0)
2444  {
2445      $PHORUM = $GLOBALS["PHORUM"];
2446  
2447      settype($user_id, "int");
2448      settype($forum_id, "int");
2449      settype($thread, "int");
2450  
2451      $conn = phorum_db_mysql_connect();
2452  
2453      $sql = "DELETE FROM {$PHORUM['subscribers_table']} WHERE user_id=$user_id AND thread=$thread";
2454      if($forum_id) $sql.=" and forum_id=$forum_id";
2455  
2456      $res = mysql_query($sql, $conn);
2457  
2458      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
2459  
2460      return (bool)$res;
2461  }
2462  
2463  /**
2464   * This function will return a list of groups the user
2465   * is a member of, as well as the users permissions.
2466   */
2467  function phorum_db_user_get_groups($user_id)
2468  {
2469      $PHORUM = $GLOBALS["PHORUM"];
2470      $groups = array();
2471  
2472      settype($user_id, "int");
2473  
2474      if (!$user_id > 0){
2475         return $groups;
2476      }
2477  
2478      $conn = phorum_db_mysql_connect();
2479      $sql = "SELECT group_id, status FROM {$PHORUM['user_group_xref_table']} WHERE user_id = $user_id ORDER BY status DESC";
2480  
2481      $res = mysql_query($sql, $conn);
2482  
2483      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
2484  
2485      while($row = mysql_fetch_assoc($res)){
2486          $groups[$row["group_id"]] = $row["status"];
2487      }
2488  
2489      return $groups;
2490  }
2491  
2492  /**
2493   * This function executes a query to select data about a user including
2494   * his permission data and returns that in an array.
2495   * If $search is empty, all users should be returned.
2496   */
2497  
2498  function phorum_db_search_users($search)
2499  {
2500      $PHORUM = $GLOBALS["PHORUM"];
2501  
2502      $conn = phorum_db_mysql_connect();
2503  
2504      $users = array();
2505  
2506      $search = mysql_escape_string(trim($search));
2507  
2508      $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";
2509  
2510      $res = mysql_query($sql, $conn);
2511      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
2512  
2513      if (mysql_num_rows($res)){
2514          while ($user = mysql_fetch_assoc($res)){
2515              $users[$user["user_id"]] = $user;
2516          }
2517      }
2518  
2519      return $users;
2520  }
2521  
2522  
2523  /**
2524   * This function gets the users that await approval
2525   */
2526  
2527  function phorum_db_user_get_unapproved()
2528  {
2529      $PHORUM = $GLOBALS["PHORUM"];
2530  
2531      $conn = phorum_db_mysql_connect();
2532  
2533      $sql="select user_id, username, email from {$PHORUM['user_table']} where active in(".PHORUM_USER_PENDING_BOTH.", ".PHORUM_USER_PENDING_MOD.") order by username";
2534      $res=mysql_query($sql, $conn);
2535  
2536      if ($err = mysql_error($conn)){
2537          phorum_db_mysql_error("$err: $sql");
2538      }
2539  
2540      $users=array();
2541      if($res){
2542          while($rec=mysql_fetch_assoc($res)){
2543              $users[$rec["user_id"]]=$rec;
2544          }
2545      }
2546  
2547      return $users;
2548  
2549  }
2550  /**
2551   * This function deletes a user completely
2552   * - entry in the users-table
2553   * - entries in the permissions-table
2554   * - entries in the newflags-table
2555   * - entries in the subscribers-table
2556   * - entries in the group_xref-table
2557   * - entries in the private-messages-table
2558   * - entries in the files-table
2559   * - sets entries in the messages-table to anonymous
2560   *
2561   */
2562  function phorum_db_user_delete($user_id) {
2563      $PHORUM = $GLOBALS["PHORUM"];
2564  
2565      // how would we check success???
2566      $ret = true;
2567  
2568      settype($user_id, "int");
2569  
2570      $conn = phorum_db_mysql_connect();
2571      // user-table
2572      $sql = "delete from {$PHORUM['user_table']} where user_id=$user_id";
2573      $res = mysql_query($sql, $conn);
2574      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
2575  
2576      // permissions-table
2577      $sql = "delete from {$PHORUM['user_permissions_table']} where user_id=$user_id";
2578      $res = mysql_query($sql, $conn);
2579      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
2580  
2581      // newflags-table
2582      $sql = "delete from {$PHORUM['user_newflags_table']} where user_id=$user_id";
2583      $res = mysql_query($sql, $conn);
2584      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
2585  
2586      // subscribers-table
2587      $sql = "delete from {$PHORUM['subscribers_table']} where user_id=$user_id";
2588      $res = mysql_query($sql, $conn);
2589      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
2590  
2591      // group-xref-table
2592      $sql = "delete from {$PHORUM['user_group_xref_table']} where user_id=$user_id";
2593      $res = mysql_query($sql, $conn);
2594      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
2595  
2596      // private messages
2597      $sql = "select * from {$PHORUM["pm_xref_table"]} where user_id=$user_id";
2598      $res = mysql_query($sql, $conn);
2599      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
2600      while ($row = mysql_fetch_assoc($res)) {
2601          $folder = $row["pm_folder_id"] == 0 ? $row["special_folder"] : $row["pm_folder_id"];
2602          phorum_db_pm_delete($row["pm_message_id"], $folder, $user_id);
2603      }
2604  
2605      // pm_buddies
2606      $sql = "delete from {$PHORUM["pm_buddies_table"]} where user_id=$user_id or buddy_user_id=$user_id";
2607      $res = mysql_query($sql, $conn);
2608      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
2609  
2610      // private message folders
2611      $sql = "delete from {$PHORUM["pm_folders_table"]} where user_id=$user_id";
2612      $res = mysql_query($sql, $conn);
2613      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
2614  
2615      // files-table
2616      $sql = "delete from {$PHORUM['files_table']} where user_id=$user_id and message_id=0 and link='" . PHORUM_LINK_USER . "'";
2617      $res = mysql_query($sql, $conn);
2618      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
2619  
2620      // custom-fields-table
2621      $sql = "delete from {$PHORUM['user_custom_fields_table']} where user_id=$user_id";
2622      $res = mysql_query($sql, $conn);
2623      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
2624  
2625      // messages-table
2626      if(PHORUM_DELETE_CHANGE_AUTHOR) {
2627        $sql = "update {$PHORUM['message_table']} set user_id=0,email='',author='".mysql_escape_string($PHORUM['DATA']['LANG']['AnonymousUser'])."' where user_id=$user_id";
2628      } else {
2629        $sql = "update {$PHORUM['message_table']} set user_id=0,email='' where user_id=$user_id";
2630      }
2631      $res = mysql_query($sql, $conn);
2632      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
2633  
2634      return $ret;
2635  }
2636  
2637  
2638  /**
2639   * This function gets the users file list
2640   */
2641  
2642  function phorum_db_get_user_file_list($user_id)
2643  {
2644      $PHORUM = $GLOBALS["PHORUM"];
2645  
2646      $conn = phorum_db_mysql_connect();
2647  
2648      settype($user_id, "int");
2649  
2650      $files=array();
2651  
2652      $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 . "'";
2653  
2654      $res = mysql_query($sql, $conn);
2655  
2656      if ($err = mysql_error($conn)){
2657          phorum_db_mysql_error("$err: $sql");
2658      }
2659  
2660      if($res){
2661          while($rec=mysql_fetch_assoc($res)){
2662              $files[$rec["file_id"]]=$rec;
2663          }
2664      }
2665  
2666      return $files;
2667  }
2668  
2669  
2670  /**
2671   * This function gets the message's file list
2672   */
2673  
2674  function phorum_db_get_message_file_list($message_id)
2675  {
2676      $PHORUM = $GLOBALS["PHORUM"];
2677  
2678      settype($message_id, "int");
2679  
2680      $conn = phorum_db_mysql_connect();
2681  
2682      $files=array();
2683  
2684      $sql="select file_id, filename, filesize, add_datetime from {$PHORUM['files_table']} where message_id=$message_id and link='" . PHORUM_LINK_MESSAGE . "'";
2685  
2686      $res = mysql_query($sql, $conn);
2687  
2688      if ($err = mysql_error($conn)){
2689          phorum_db_mysql_error("$err: $sql");
2690      }
2691  
2692      if($res){
2693          while($rec=mysql_fetch_assoc($res)){
2694              $files[$rec["file_id"]]=$rec;
2695          }
2696      }
2697  
2698      return $files;
2699  }
2700  
2701  
2702  /**
2703   * This function retrieves a file from the db
2704   */
2705  
2706  function phorum_db_file_get($file_id)
2707  {
2708      $PHORUM = $GLOBALS["PHORUM"];
2709  
2710      $conn = phorum_db_mysql_connect();
2711  
2712      settype($file_id, "int");
2713  
2714      $file=array();
2715  
2716      $sql="select * from {$PHORUM['files_table']} where file_id=$file_id";
2717  
2718      $res = mysql_query($sql, $conn);
2719  
2720      if ($err = mysql_error($conn)){
2721          phorum_db_mysql_error("$err: $sql");
2722      }
2723  
2724      if($res){
2725          $file=mysql_fetch_assoc($res);
2726      }
2727  
2728      return $file;
2729  }
2730  
2731  
2732  /**
2733   * This function saves a file to the db
2734   */
2735  
2736  function phorum_db_file_save($user_id, $filename, $filesize, $buffer, $message_id=0, $link=null)
2737  {
2738      $PHORUM = $GLOBALS["PHORUM"];
2739  
2740      $conn = phorum_db_mysql_connect();
2741  
2742      $file_id=0;
2743  
2744      settype($user_id, "int");
2745      settype($message_id, "int");
2746      settype($filesize, "int");
2747  
2748      if (is_null($link)) {
2749          $link = $message_id ? PHORUM_LINK_MESSAGE : PHORUM_LINK_USER;
2750      } else {
2751          $link = mysql_escape_string($link);
2752      }
2753  
2754      $filename=mysql_escape_string($filename);
2755      $buffer=mysql_escape_string($buffer);
2756  
2757      $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();
2758  
2759      $res = mysql_query($sql, $conn);
2760  
2761      if ($err = mysql_error($conn)){
2762          phorum_db_mysql_error("$err: $sql");
2763      }
2764  
2765      if($res){
2766          $file_id=mysql_insert_id($conn);
2767      }
2768  
2769      return $file_id;
2770  }
2771  
2772  
2773  /**
2774   * This function saves a file to the db
2775   */
2776  
2777  function phorum_db_file_delete($file_id)
2778  {
2779      $PHORUM = $GLOBALS["PHORUM"];
2780  
2781      $conn = phorum_db_mysql_connect();
2782  
2783      settype($file_id, "int");
2784  
2785      $sql="delete from {$PHORUM['files_table']} where file_id=$file_id";
2786  
2787      $res = mysql_query($sql, $conn);
2788  
2789      if ($err = mysql_error($conn)){
2790          phorum_db_mysql_error("$err: $sql");
2791      }
2792  
2793      return $res;
2794  }
2795  
2796  /**
2797   * This function links a file to a specific message
2798   */
2799  
2800  function phorum_db_file_link($file_id, $message_id, $link = null)
2801  {
2802      $PHORUM = $GLOBALS["PHORUM"];
2803  
2804      $conn = phorum_db_mysql_connect();
2805  
2806      settype($file_id, "int");
2807      settype($message_id, "int");
2808  
2809      if (is_null($link)) {
2810          $link = $message_id ? PHORUM_LINK_MESSAGE : PHORUM_LINK_USER;
2811      } else {
2812          $link = mysql_escape_string($link);
2813      }
2814  
2815      $sql="update {$PHORUM['files_table']} " .
2816           "set message_id=$message_id, link='$link' " .
2817           "where file_id=$file_id";
2818  
2819      $res = mysql_query($sql, $conn);
2820  
2821      if ($err = mysql_error($conn)){
2822          phorum_db_mysql_error("$err: $sql");
2823      }
2824  
2825      return $res;
2826  }
2827  
2828  /**
2829   * This function reads the current total size of all files for a user
2830   */
2831  
2832  function phorum_db_get_user_filesize_total($user_id)
2833  {
2834      $PHORUM = $GLOBALS["PHORUM"];
2835  
2836      $conn = phorum_db_mysql_connect();
2837  
2838      settype($user_id, "int");
2839  
2840      $total=0;
2841  
2842      $sql="select sum(filesize) as total from {$PHORUM['files_table']} where user_id=$user_id and message_id=0 and link='" . PHORUM_LINK_USER . "'";
2843  
2844      $res = mysql_query($sql, $conn);
2845  
2846      if ($err = mysql_error($conn)){
2847          phorum_db_mysql_error("$err: $sql");
2848      }
2849  
2850      if($res){
2851          $total=mysql_result($res, 0,"total");
2852      }
2853  
2854      return $total;
2855  
2856  }
2857  
2858  /**
2859   * This function is used for cleaning up stale files from the
2860   * database. Stale files are files that are not linked to
2861   * anything. These can for example be caused by users that
2862   * are writing a message with attachments, but never post
2863   * it.
2864   * @param live_run - If set to false (default), the function
2865   *                  will return a list of files that will
2866   *                  be purged. If set to true, files will
2867   *                  be purged.
2868   */
2869  function phorum_db_file_purge_stale_files($live_run = false)
2870  {
2871      $PHORUM = $GLOBALS["PHORUM"];
2872  
2873      settype($live_run, "bool");
2874  
2875      $conn = phorum_db_mysql_connect();
2876  
2877      $where = "link='" . PHORUM_LINK_EDITOR. "' " .
2878               "and add_datetime<". (time()-PHORUM_MAX_EDIT_TIME);
2879  
2880      // Purge files.
2881      if ($live_run) {
2882  
2883          // Delete files that are linked to the editor and are
2884          // added a while ago. These are from abandoned posts.
2885          $sql = "delete from {$PHORUM['files_table']} " .
2886                 "where $where";
2887          $res = mysql_query($sql, $conn);
2888          if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
2889  
2890          return true;
2891  
2892      // Only select a list of files that can be purged.
2893      } else {
2894  
2895          // Select files that are linked to the editor and are
2896          // added a while ago. These are from abandoned posts.
2897          $sql = "select file_id, filename, filesize, add_datetime " .
2898                 "from {$PHORUM['files_table']} " .
2899                 "where $where";
2900  
2901          $res = mysql_query($sql, $conn);
2902          if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
2903  
2904          $purge_files = array();
2905          if (mysql_num_rows($res) > 0) {
2906              while ($row = mysql_fetch_assoc($res)) {
2907                  $row["reason"] = "Stale editor file";
2908                  $purge_files[$row["file_id"]] = $row;
2909              }
2910          }
2911  
2912          return $purge_files;
2913      }
2914  }
2915  
2916  /**
2917   * This function returns the newinfo-array for markallread
2918   */
2919  
2920  function phorum_db_newflag_allread($forum_id=0)
2921  {
2922      $PHORUM = $GLOBALS['PHORUM'];
2923      $conn = phorum_db_mysql_connect();
2924  
2925      settype($forum_id, "int");
2926  
2927      if(empty($forum_id)) $forum_id=$PHORUM["forum_id"];
2928  
2929      // delete all newflags for this user and forum
2930      phorum_db_newflag_delete(0,$forum_id);
2931  
2932      // get the maximum message-id in this forum
2933      $sql = "select max(message_id) from {$PHORUM['message_table']} where forum_id in ($forum_id, {$PHORUM['vroot']})";
2934      $res = mysql_query($sql, $conn);
2935      if ($err = mysql_error($conn)){
2936          phorum_db_mysql_error("$err: $sql");
2937      }elseif (mysql_num_rows($res) > 0){
2938          $row = mysql_fetch_row($res);
2939          if($row[0] > 0) {
2940              // set this message as min-id
2941              phorum_db_newflag_add_read(array(0=>array('id'=>$row[0],'forum'=>$forum_id)));
2942          }
2943      }
2944  
2945  }
2946  
2947  
2948  /**
2949  * This function returns the read messages for the current user and forum
2950  * optionally for a given forum (for the index)
2951  */
2952  function phorum_db_newflag_get_flags($forum_id=0)
2953  {
2954      $PHORUM = $GLOBALS["PHORUM"];
2955  
2956      settype($forum_id, "int");
2957  
2958      $read_msgs=array('min_id'=>0);
2959  
2960      if(empty($forum_id)) $forum_id=$PHORUM["forum_id"];
2961  
2962      $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']})";
2963  
2964      $conn = phorum_db_mysql_connect();
2965      $res = mysql_query($sql, $conn);
2966  
2967      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
2968  
2969      while($row=mysql_fetch_row($res)) {
2970          // set the min-id if given flag is set
2971          if($row[1] != $PHORUM['vroot'] && ($read_msgs['min_id']==0 || $row[0] < $read_msgs['min_id'])) {
2972              $read_msgs['min_id']=$row[0];
2973          } else {
2974              $read_msgs[$row[0]]=$row[0];
2975          }
2976      }
2977  
2978      return $read_msgs;
2979  }
2980  
2981  
2982  /**
2983  * This function returns the count of unread messages the current user and forum
2984  * optionally for a given forum (for the index)
2985  */
2986  function phorum_db_newflag_get_unread_count($forum_id=0)
2987  {
2988      $PHORUM = $GLOBALS["PHORUM"];
2989  
2990      settype($forum_id, "int");
2991  
2992      if(empty($forum_id)) $forum_id=$PHORUM["forum_id"];
2993  
2994      // get the read message array
2995      $read_msgs = phorum_db_newflag_get_flags($forum_id);
2996  
2997      if($read_msgs["min_id"]==0) return array(0,0);
2998  
2999      $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},{$PHORUM['vroot']}) and status=".PHORUM_STATUS_APPROVED." and not ".PHORUM_SQL_MOVEDMESSAGES;
3000  
3001      $conn = phorum_db_mysql_connect();
3002      $res = mysql_query($sql, $conn);
3003  
3004      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
3005  
3006      $counts[] = mysql_result($res, 0, "count");
3007  
3008      $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},{$PHORUM['vroot']}) and parent_id=0 and status=".PHORUM_STATUS_APPROVED." and not ".PHORUM_SQL_MOVEDMESSAGES;
3009  
3010      $conn = phorum_db_mysql_connect();
3011      $res = mysql_query($sql, $conn);
3012  
3013      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
3014  
3015      $counts[] = mysql_result($res, 0, "count");
3016  
3017      return $counts;
3018  }
3019  
3020  
3021  /**
3022   * This function marks a message as read
3023   */
3024  function phorum_db_newflag_add_read($message_ids) {
3025      $PHORUM = $GLOBALS["PHORUM"];
3026  
3027      $num_newflags=phorum_db_newflag_get_count();
3028  
3029      // maybe got just one message
3030      if(!is_array($message_ids)) {
3031          $message_ids=array(0=>(int)$message_ids);
3032      }
3033  
3034      // deleting messages which are too much
3035      $num_end=$num_newflags+count($message_ids);
3036      if($num_end > PHORUM_MAX_NEW_INFO) {
3037          phorum_db_newflag_delete($num_end - PHORUM_MAX_NEW_INFO);
3038      }
3039      // building the query
3040      $values=array();
3041      $cnt=0;
3042  
3043      foreach($message_ids as $id=>$data) {
3044          if(is_array($data)) {
3045              $data["forum"] = (int)$data["forum"];
3046              $data["id"] = (int)$data["id"];
3047              $values[]="({$PHORUM['user']['user_id']},{$data['forum']},{$data['id']})";
3048          } else {
3049              $data = (int)$data;
3050              $values[]="({$PHORUM['user']['user_id']},{$PHORUM['forum_id']},$data)";
3051          }
3052          $cnt++;
3053      }
3054      if($cnt) {
3055          $insert_sql="INSERT IGNORE INTO ".$PHORUM['user_newflags_table']." (user_id,forum_id,message_id) VALUES".join(",",$values);
3056  
3057          // fire away
3058          $conn = phorum_db_mysql_connect();
3059          $res = mysql_query($insert_sql, $conn);
3060  
3061          if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $insert_sql");
3062      }
3063  }
3064  
3065  /**
3066  * This function returns the number of newflags for this user and forum
3067  */
3068  function phorum_db_newflag_get_count($forum_id=0)
3069  {
3070      $PHORUM = $GLOBALS["PHORUM"];
3071  
3072      settype($forum_id, "int");
3073  
3074      if(empty($forum_id)) $forum_id=$PHORUM["forum_id"];
3075  
3076      $sql="SELECT count(*) FROM ".$PHORUM['user_newflags_table']." WHERE user_id={$PHORUM['user']['user_id']} AND forum_id={$forum_id}";
3077  
3078      // fire away
3079      $conn = phorum_db_mysql_connect();
3080      $res = mysql_query($sql, $conn);
3081  
3082      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
3083  
3084      $row=mysql_fetch_row($res);
3085  
3086      return $row[0];
3087  }
3088  
3089  /**
3090  * This function removes a number of newflags for this user and forum
3091  */
3092  function phorum_db_newflag_delete($numdelete=0,$forum_id=0)
3093  {
3094      $PHORUM = $GLOBALS["PHORUM"];
3095  
3096      settype($forum_id, "int");
3097      settype($numdelete, "int");
3098  
3099      if(empty($forum_id)) $forum_id=$PHORUM["forum_id"];
3100  
3101      if($numdelete>0) {
3102          $lvar=" ORDER BY message_id ASC LIMIT $numdelete";
3103      } else {
3104          $lvar="";
3105      }
3106      // delete the number of newflags given
3107      $del_sql="DELETE FROM ".$PHORUM['user_newflags_table']." WHERE user_id={$PHORUM['user']['user_id']} AND forum_id={$forum_id}".$lvar;
3108      // fire away
3109      $conn = phorum_db_mysql_connect();
3110      $res = mysql_query($del_sql, $conn);
3111      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $del_sql");
3112  }
3113  
3114  
3115  /**
3116   * This function executes a query to fix any newflags that are assigned to the wrong forum
3117   */
3118  
3119  function phorum_db_newflag_update_forum($message_ids) {
3120  
3121      if(!is_array($message_ids)) {
3122          return;
3123      }
3124  
3125      phorum_db_sanitize_mixed($message_ids, "int");
3126  
3127      $ids_str=implode(",",$message_ids);
3128  
3129      // then doing the update to newflags
3130      $sql="UPDATE IGNORE {$GLOBALS['PHORUM']['user_newflags_table']} as flags, {$GLOBALS['PHORUM']['message_table']} as msg SET flags.forum_id=msg.forum_id where flags.message_id=msg.message_id and flags.message_id IN ($ids_str)";
3131      $conn = phorum_db_mysql_connect();
3132      $res = mysql_query($sql, $conn);
3133      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
3134  
3135  }
3136  
3137  /**
3138   * This function executes a query to get the user ids of the users
3139   * subscribed to a forum/thread.
3140   */
3141  
3142  function phorum_db_get_subscribed_users($forum_id, $thread, $type){
3143      $PHORUM = $GLOBALS["PHORUM"];
3144  
3145      settype($forum_id, "int");
3146      settype($thread, "int");
3147      settype($type, "int");
3148  
3149      $conn = phorum_db_mysql_connect();
3150  
3151      $userignore="";
3152      if ($PHORUM["DATA"]["LOGGEDIN"])
3153         $userignore="and b.user_id != {$PHORUM['user']['user_id']}";
3154  
3155      $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";
3156  
3157      $res = mysql_query($sql, $conn);
3158  
3159      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
3160  
3161          $arr=array();
3162  
3163      while ($rec = mysql_fetch_row($res)){
3164          if(!empty($rec[1])) // user-language is set
3165              $arr[$rec[1]][] = $rec[0];
3166          else // no user-language is set
3167              $arr[$PHORUM['language']][]= $rec[0];
3168      }
3169  
3170      return $arr;
3171  }
3172  
3173  /**
3174   * This function executes a query to get the subscriptions of a user-id,
3175   * together with the forum-id and subjects of the threads
3176   */
3177  
3178  function phorum_db_get_message_subscriptions($user_id,$days=2)
3179  {
3180      $PHORUM = $GLOBALS["PHORUM"];
3181  
3182      settype($user_id, "int");
3183      settype($days, "int");
3184  
3185      $conn = phorum_db_mysql_connect();
3186  
3187      $userignore="";
3188      if ($PHORUM["DATA"]["LOGGEDIN"])
3189         $userignore="and b.user_id != {$PHORUM['user']['user_id']}";
3190  
3191      if($days > 0) {
3192           $timestr=" AND (".time()." - b.modifystamp) <= ($days * 86400)";
3193      } else {
3194          $timestr="";
3195      }
3196  
3197      $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";
3198  
3199      $res = mysql_query($sql, $conn);
3200  
3201      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
3202  
3203      $arr=array();
3204      $forum_ids=array();
3205  
3206      while ($rec = mysql_fetch_assoc($res)){
3207          $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']);
3208          $rec['unsubscribe_url']=$unsub_url;
3209          $arr[] = $rec;
3210          $forum_ids[]=$rec['forum_id'];
3211      }
3212      $arr['forum_ids']=$forum_ids;
3213  
3214      return $arr;
3215  }
3216  
3217  /**
3218   * This function executes a query to find out if a user is subscribed to a thread
3219   */
3220  
3221  function phorum_db_get_if_subscribed($forum_id, $thread, $user_id, $type=PHORUM_SUBSCRIPTION_MESSAGE)
3222  {
3223      $PHORUM = $GLOBALS["PHORUM"];
3224  
3225      settype($forum_id, "int");
3226      settype($thread, "int");
3227      settype($user_id, "int");
3228      settype($type, "int");
3229  
3230      $conn = phorum_db_mysql_connect();
3231  
3232      $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";
3233  
3234      $res = mysql_query($sql, $conn);
3235  
3236      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
3237  
3238      if (mysql_num_rows($res) > 0){
3239          $retval = true;
3240      }else{
3241          $retval = false;
3242      }
3243  
3244      return $retval;
3245  }
3246  
3247  
3248  /**
3249   * This function retrieves the banlists for the current forum
3250   */
3251  
3252  function phorum_db_get_banlists($ordered=false) {
3253      $PHORUM = $GLOBALS["PHORUM"];
3254  
3255      settype($ordered, "bool");
3256  
3257      $retarr = array();
3258      $forumstr = "";
3259  
3260      $conn = phorum_db_mysql_connect();
3261  
3262      if(isset($PHORUM['forum_id']) && !empty($PHORUM['forum_id']))
3263          $forumstr = "WHERE forum_id = {$PHORUM['forum_id']} OR forum_id = 0";
3264  
3265      if(isset($PHORUM['vroot']) && !empty($PHORUM['vroot']))
3266          $forumstr .= " OR forum_id = {$PHORUM['vroot']}";
3267  
3268  
3269  
3270      $sql = "SELECT * FROM {$PHORUM['banlist_table']} $forumstr";
3271  
3272      if($ordered) {
3273          $sql.= " ORDER BY type, string";
3274      }
3275  
3276      $res = mysql_query($sql, $conn);
3277  
3278      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
3279  
3280      if (mysql_num_rows($res) > 0){
3281          while($row = mysql_fetch_assoc($res)) {
3282              $retarr[$row['type']][$row['id']]=array('pcre'=>$row['pcre'],'string'=>$row['string'],'forum_id'=>$row['forum_id']);
3283          }
3284      }
3285      return $retarr;
3286  }
3287  
3288  
3289  /**
3290   * This function retrieves one item from the banlists
3291   */
3292  
3293  function phorum_db_get_banitem($banid) {
3294      $PHORUM = $GLOBALS["PHORUM"];
3295  
3296      $retarr = array();
3297  
3298      $conn = phorum_db_mysql_connect();
3299  
3300      settype($banid, "int");
3301  
3302      $sql = "SELECT * FROM {$PHORUM['banlist_table']} WHERE id = $banid";
3303  
3304      $res = mysql_query($sql, $conn);
3305  
3306      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
3307  
3308      if (mysql_num_rows($res) > 0){
3309          while($row = mysql_fetch_assoc($res)) {
3310              $retarr=array('pcre'=>$row['pcre'],'string'=>$row['string'],'forum_id'=>$row['forum_id'],'type'=>$row['type']);
3311          }
3312      }
3313      return $retarr;
3314  }
3315  
3316  
3317  /**
3318   * This function deletes one item from the banlists
3319   */
3320  
3321  function phorum_db_del_banitem($banid) {
3322      $PHORUM = $GLOBALS["PHORUM"];
3323  
3324      settype($banid, "int");
3325  
3326      $conn = phorum_db_mysql_connect();
3327  
3328      $sql = "DELETE FROM {$PHORUM['banlist_table']} WHERE id = $banid";
3329  
3330      $res = mysql_query($sql, $conn);
3331  
3332      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
3333  
3334      if(mysql_affected_rows($conn) > 0) {
3335          return true;
3336      } else {
3337          return false;
3338      }
3339  }
3340  
3341  
3342  /**
3343   * This function adds or modifies a banlist-entry
3344   */
3345  
3346  function phorum_db_mod_banlists($type,$pcre,$string,$forum_id,$id=0) {
3347      $PHORUM = $GLOBALS["PHORUM"];
3348  
3349      $retarr = array();
3350  
3351      $conn = phorum_db_mysql_connect();
3352  
3353      settype($type, "int");
3354      settype($pcre, "int");
3355      settype($forum_id, "int");
3356      settype($id, "int");
3357  
3358      if($id > 0) { // modifying an entry
3359          $sql = "UPDATE {$PHORUM['banlist_table']} SET forum_id = $forum_id, type = $type, pcre = $pcre, string = '".mysql_escape_string($string)."' where id = $id";
3360      } else { // adding an entry
3361          $sql = "INSERT INTO {$PHORUM['banlist_table']} (forum_id,type,pcre,string) VALUES($forum_id,$type,$pcre,'".mysql_escape_string($string)."')";
3362      }
3363  
3364      $res = mysql_query($sql, $conn);
3365  
3366      if ($err = mysql_error($conn)) {
3367          phorum_db_mysql_error("$err: $sql");
3368          return false;
3369      } else {
3370          return true;
3371      }
3372  }
3373  
3374  
3375  
3376  /**
3377   * This function lists all private messages in a folder.
3378   * @param folder - The folder to use. Either a special folder
3379   *                 (PHORUM_PM_INBOX or PHORUM_PM_OUTBOX) or the
3380   *                 id of a user's custom folder.
3381   * @param user_id - The user to retrieve messages for or NULL
3382   *                 to use the current user (default).
3383   * @param reverse - If set to a true value (default), sorting
3384   *                 of messages is done in reverse (newest first).
3385   */
3386  
3387  function phorum_db_pm_list($folder, $user_id = NULL, $reverse = true)
3388  {
3389      $PHORUM = $GLOBALS["PHORUM"];
3390  
3391      settype($reverse, "bool");
3392  
3393      $conn = phorum_db_mysql_connect();
3394  
3395      if ($user_id == NULL) $user_id = $PHORUM['user']['user_id'];
3396      settype($user_id, "int");
3397  
3398      $folder_sql = "user_id = $user_id AND ";
3399      if (is_numeric($folder)) {
3400          $folder_sql .= "pm_folder_id=$folder";
3401      } elseif ($folder == PHORUM_PM_INBOX || $folder == PHORUM_PM_OUTBOX) {
3402          $folder_sql .= "pm_folder_id=0 AND special_folder='$folder'";
3403      } else {
3404          die ("Illegal folder '$folder' requested for user id '$user_id'");
3405      }
3406  
3407      $sql = "SELECT m.pm_message_id, from_user_id, from_username, subject, " .
3408             "datestamp, meta, pm_xref_id, user_id, pm_folder_id, " .
3409             "special_folder, read_flag, reply_flag " .
3410             "FROM {$PHORUM['pm_messages_table']} as m, {$PHORUM['pm_xref_table']} as x " .
3411             "WHERE $folder_sql " .
3412             "AND x.pm_message_id = m.pm_message_id " .
3413             "ORDER BY x.pm_message_id " . ($reverse ? "DESC" : "ASC");
3414      $res = mysql_query($sql, $conn);
3415      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
3416  
3417      $list = array();
3418      if (mysql_num_rows($res) > 0){
3419          while($row = mysql_fetch_assoc($res)) {
3420  
3421              // Add the recipient information unserialized to the message..
3422              $meta = unserialize($row['meta']);
3423              $row['recipients'] = $meta['recipients'];
3424  
3425              $list[$row["pm_message_id"]]=$row;
3426          }
3427      }
3428  
3429      return $list;
3430  }
3431  
3432  /**
3433   * This function retrieves a private message from the database.
3434   * @param pm_id - The id for the private message to retrieve.
3435   * @param user_id - The user to retrieve messages for or NULL
3436   *                 to use the current user (default).
3437   * @param folder_id - The folder to retrieve the message from or
3438   *                    NULL if the folder does not matter.
3439   */
3440  
3441  function phorum_db_pm_get($pm_id, $folder = NULL, $user_id = NULL)
3442  {
3443      $PHORUM = $GLOBALS["PHORUM"];
3444  
3445      $conn = phorum_db_mysql_connect();
3446  
3447      if ($user_id == NULL) $user_id = $PHORUM['user']['user_id'];
3448      settype($user_id, "int");
3449      settype($pm_id, "int");
3450  
3451      if (is_null($folder)) {
3452          $folder_sql = '';
3453      } elseif (is_numeric($folder)) {
3454          $folder_sql = "pm_folder_id=$folder AND ";
3455      } elseif ($folder == PHORUM_PM_INBOX || $folder == PHORUM_PM_OUTBOX) {
3456          $folder_sql = "pm_folder_id=0 AND special_folder='$folder' AND ";
3457      } else {
3458          die ("Illegal folder '$folder' requested for message id '$pm_id'");
3459      }
3460  
3461      $sql = "SELECT * " .
3462             "FROM {$PHORUM['pm_messages_table']} as m, {$PHORUM['pm_xref_table']} as x " .
3463             "WHERE $folder_sql x.pm_message_id = $pm_id AND x.user_id = $user_id " .
3464             "AND x.pm_message_id = m.pm_message_id";
3465  
3466      $res = mysql_query($sql, $conn);
3467      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
3468  
3469      if (mysql_num_rows($res) > 0){
3470          $row = mysql_fetch_assoc($res);
3471  
3472          // Add the recipient information unserialized to the message..
3473          $meta = unserialize($row['meta']);
3474          $row['recipients'] = $meta['recipients'];
3475  
3476          return $row;
3477      } else {
3478          return NULL;
3479      }
3480  }
3481  
3482  /**
3483   * This function creates a new folder for a user.
3484   * @param foldername - The name of the folder to create.
3485   * @param user_id - The user to create the folder for or
3486   *                  NULL to use the current user (default).
3487   */
3488  function phorum_db_pm_create_folder($foldername, $user_id = NULL)
3489  {
3490      $PHORUM = $GLOBALS["PHORUM"];
3491  
3492      $conn = phorum_db_mysql_connect();
3493  
3494      if ($user_id == NULL) $user_id = $PHORUM['user']['user_id'];
3495      settype($user_id, "int");
3496  
3497      $sql = "INSERT INTO {$PHORUM['pm_folders_table']} SET " .
3498             "user_id=$user_id, " .
3499             "foldername='".mysql_escape_string($foldername)."'";
3500  
3501      $res = mysql_query($sql, $conn);
3502      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
3503  
3504      $folder_id = 0;
3505      if ($res){
3506          $folder_id = mysql_insert_id($conn);
3507      }
3508  
3509      return $folder_id;
3510  }
3511  
3512  /**
3513   * This function renames a folder for a user.
3514   * @param folder_id - The id of the folder to rename.
3515   * @param newname - The new name for the folder.
3516   * @param user_id - The user to rename the folder for or
3517   *                  NULL to use the current user (default).
3518   */
3519  function phorum_db_pm_rename_folder($folder_id, $newname, $user_id = NULL)
3520  {
3521      $PHORUM = $GLOBALS["PHORUM"];
3522  
3523      $conn = phorum_db_mysql_connect();
3524  
3525      if ($user_id == NULL) $user_id = $PHORUM['user']['user_id'];
3526      settype($user_id, "int");
3527      settype($folder_id, "int");
3528  
3529      $sql = "UPDATE {$PHORUM['pm_folders_table']} " .
3530             "SET foldername = '".mysql_escape_string($newname)."' " .
3531             "WHERE pm_folder_id = $folder_id AND user_id = $user_id";
3532  
3533      $res = mysql_query($sql, $conn);
3534      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
3535      return $res;
3536  }
3537  
3538  
3539  
3540  /**
3541   * This function deletes a folder for a user. Along with the
3542   * folder, all contained messages are deleted as well.
3543   * @param folder_id - The id of the folder to delete.
3544   * @param user_id - The user to delete the folder for or
3545   *                  NULL to use the current user (default).
3546   */
3547  function phorum_db_pm_delete_folder($folder_id, $user_id = NULL)
3548  {
3549      $PHORUM = $GLOBALS["PHORUM"];
3550  
3551      $conn = phorum_db_mysql_connect();
3552  
3553      if ($user_id == NULL) $user_id = $PHORUM['user']['user_id'];
3554      settype($user_id, "int");
3555      settype($folder_id, "int");
3556  
3557      // Get messages in this folder and delete them.
3558      $list = phorum_db_pm_list($folder_id, $user_id);
3559      foreach ($list as $id => $data) {
3560          phorum_db_pm_delete($id, $folder_id, $user_id);
3561      }
3562  
3563      // Delete the folder itself.
3564      $sql = "DELETE FROM {$PHORUM['pm_folders_table']} " .
3565             "WHERE pm_folder_id = $folder_id AND user_id = $user_id";
3566      $res = mysql_query($sql, $conn);
3567      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
3568      return $res;
3569  }
3570  
3571  /**
3572   * This function retrieves the list of folders for a user.
3573   * @param user_id - The user to retrieve folders for or NULL
3574   *                 to use the current user (default).
3575   * @param count_messages - Count the number of messages for the
3576   *                 folders. Default, this is not done.
3577   */
3578  function phorum_db_pm_getfolders($user_id = NULL, $count_messages = false)
3579  {
3580      $PHORUM = $GLOBALS["PHORUM"];
3581  
3582      $conn = phorum_db_mysql_connect();
3583  
3584      if ($user_id == NULL) $user_id = $PHORUM['user']['user_id'];
3585      settype($user_id, "int");
3586  
3587      settype($count_messages, "bool");
3588  
3589      // Setup the list of folders. Our special folders are
3590      // not in the database, so these are added here.
3591      $folders = array(
3592          PHORUM_PM_INBOX => array(
3593              'id'   => PHORUM_PM_INBOX,
3594              'name' => $PHORUM["DATA"]["LANG"]["INBOX"],
3595          ),
3596      );
3597  
3598      // Select all custom folders for the user.
3599      $sql = "SELECT * FROM {$PHORUM['pm_folders_table']} " .
3600             "WHERE user_id = $user_id ORDER BY foldername";
3601      $res = mysql_query($sql, $conn);
3602      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
3603  
3604      // Add them to the folderlist.
3605      if (mysql_num_rows($res) > 0){
3606          while (($row = mysql_fetch_assoc($res))) {
3607              $folders[$row["pm_folder_id"]] = array(
3608                  'id' => $row["pm_folder_id"],
3609                  'name' => $row["foldername"],
3610              );
3611          }
3612      }
3613  
3614      // Add the outgoing box.
3615      $folders[PHORUM_PM_OUTBOX] = array(
3616          'id'   => PHORUM_PM_OUTBOX,
3617          'name' => $PHORUM["DATA"]["LANG"]["SentItems"],
3618      );
3619  
3620      // Count messages if requested.
3621      if ($count_messages)
3622      {
3623          // Initialize counters.
3624          foreach ($folders as $id => $data) {
3625              $folders[$id]["total"] = $folders[$id]["new"] = 0;
3626          }
3627  
3628          // Collect count information.
3629          $sql = "SELECT pm_folder_id, special_folder, " .
3630                 "count(*) as total, (count(*) - sum(read_flag)) as new " .
3631                 "FROM {$PHORUM['pm_xref_table']}  " .
3632                 "WHERE user_id = $user_id " .
3633                 "GROUP BY pm_folder_id, special_folder";
3634          $res = mysql_query($sql, $conn);
3635          if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
3636  
3637          // Add counters to the folderlist.
3638          if (mysql_num_rows($res) > 0){
3639              while (($row = mysql_fetch_assoc($res))) {
3640                  $folder_id = $row["pm_folder_id"] ? $row["pm_folder_id"] : $row["special_folder"];
3641                  // If there are stale messages, we do not want them
3642                  // to create non-existant mailboxes in the list.
3643                  if (isset($folders[$folder_id])) {
3644                      $folders[$folder_id]["total"] = $row["total"];
3645                      $folders[$folder_id]["new"] = $row["new"];
3646                  }
3647              }
3648          }
3649      }
3650  
3651      return $folders;
3652  }
3653  
3654  /**
3655   * This function computes the number of private messages a user has
3656   * and returns both the total and the number unread.
3657   * @param folder - The folder to use. Either a special folder
3658   *                 (PHORUM_PM_INBOX or PHORUM_PM_OUTBOX), the
3659   *                 id of a user's custom folder or
3660   *                 PHORUM_PM_ALLFOLDERS for all folders.
3661   * @param user_id - The user to retrieve messages for or NULL
3662   *                 to use the current user (default).
3663   */
3664  
3665  function phorum_db_pm_messagecount($folder, $user_id = NULL)
3666  {
3667      $PHORUM = $GLOBALS["PHORUM"];
3668  
3669      $conn = phorum_db_mysql_connect();
3670  
3671      if ($user_id == NULL) $user_id = $PHORUM['user']['user_id'];
3672      settype($user_id, "int");
3673  
3674      if (is_numeric($folder)) {
3675          $folder_sql = "pm_folder_id=$folder AND";
3676      } elseif ($folder == PHORUM_PM_INBOX || $folder == PHORUM_PM_OUTBOX) {
3677          $folder_sql = "pm_folder_id=0 AND special_folder='$folder' AND";
3678      } elseif ($folder == PHORUM_PM_ALLFOLDERS) {
3679          $folder_sql = '';
3680      } else {
3681          die ("Illegal folder '$folder' requested for user id '$user_id'");
3682      }
3683  
3684      $sql = "SELECT count(*) as total, (count(*) - sum(read_flag)) as new " .
3685             "FROM {$PHORUM['pm_xref_table']}  " .
3686             "WHERE $folder_sql user_id = $user_id";
3687  
3688      $messagecount=array("total" => 0, "new" => 0);
3689  
3690      $res = mysql_query($sql, $conn);
3691      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
3692  
3693      if (mysql_num_rows($res) > 0){
3694          $row = mysql_fetch_assoc($res);
3695          $messagecount["total"] = $row["total"];
3696          $messagecount["new"] = ($row["new"] >= 1) ? $row["new"] : 0;
3697      }
3698  
3699      return $messagecount;
3700  }
3701  
3702  /**
3703   * This function does a quick check if the user has new private messages.
3704   * This is useful in case you only want to know whether the user has
3705   * new messages or not and when you are not interested in the exact amount
3706   * of new messages.
3707   *
3708   * @param user_id - The user to retrieve messages for or NULL
3709   *                 to use the current user (default).
3710   * @return A true value, in case there are new messages available.
3711   */
3712  function phorum_db_pm_checknew($user_id = NULL)
3713  {
3714      $PHORUM = $GLOBALS["PHORUM"];
3715  
3716      $conn = phorum_db_mysql_connect();
3717  
3718      if ($user_id == NULL) $user_id = $PHORUM['user']['user_id'];
3719      settype($user_id, "int");
3720  
3721      $sql = "SELECT user_id " .
3722             "FROM {$PHORUM['pm_xref_table']} " .
3723             "WHERE user_id = $user_id AND read_flag = 0 LIMIT 1";
3724      $res = mysql_query($sql, $conn);
3725      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
3726  
3727      return mysql_num_rows($res);
3728  }
3729  
3730  /**
3731   * This function inserts a private message in the database. The return value
3732   * is the pm_message_id of the created message.
3733   * @param subject - The subject for the private message.
3734   * @param message - The message text for the private message.
3735   * @param to - A single user_id or an array of user_ids for the recipients.
3736   * @param from - The user_id of the sender. The current user is used in case
3737   *               the parameter is set to NULL (default).
3738   * @param keepcopy - If set to a true value, a copy of the mail will be put in
3739   *                   the outbox of the user. Default value is false.
3740   */
3741  function phorum_db_pm_send($subject, $message, $to, $from=NULL, $keepcopy=false)
3742  {
3743      $PHORUM = $GLOBALS["PHORUM"];
3744  
3745      $conn = phorum_db_mysql_connect();
3746  
3747      // Prepare the sender.
3748      if ($from == NULL) $from = $PHORUM['user']['user_id'];
3749      settype($from, "int");
3750      $fromuser = phorum_db_user_get($from, false);
3751      if (! $fromuser) die("Unknown sender user_id '$from'");
3752  
3753      // This array will be filled with xref database entries.
3754      $xref_entries = array();
3755  
3756      // Prepare the list of recipients.
3757      $rcpts = array();
3758      if (! is_array($to)) $to = array($to);
3759      foreach ($to as $user_id) {
3760          settype($user_id, "int");
3761          $user = phorum_db_user_get($user_id, false);
3762          if (! $user) die("Unknown recipient user_id '$user_id'");
3763          $rcpts[$user_id] = array(
3764              'user_id' => $user_id,
3765              'username' => $user["username"],
3766              'read_flag' => 0,
3767          );
3768          $xref_entries[] = array(
3769              'user_id' => $user_id,
3770              'pm_folder_id' => 0,
3771              'special_folder' => PHORUM_PM_INBOX,
3772              'read_flag' => 0,
3773          );
3774      }
3775  
3776      // Keep copy of this message in outbox?
3777      if ($keepcopy) {
3778          $xref_entries[] = array(
3779              'user_id' => $from,
3780              'pm_folder_id' => 0,
3781              'special_folder' => PHORUM_PM_OUTBOX,
3782              'read_flag' => 1,
3783          );
3784      }
3785  
3786      // Prepare message meta data.
3787      $meta = mysql_escape_string(serialize(array(
3788          'recipients' => $rcpts
3789      )));
3790  
3791      // Create the message.
3792      $sql = "INSERT INTO {$PHORUM["pm_messages_table"]} SET " .
3793             "from_user_id = $from, " .
3794             "from_username = '".mysql_escape_string($fromuser["username"])."', " .
3795             "subject = '".mysql_escape_string($subject)."', " .
3796             "message = '".mysql_escape_string($message)."', " .
3797             "datestamp = '".time()."', " .
3798             "meta = '$meta'";
3799      mysql_query($sql, $conn);
3800      if ($err = mysql_error($conn)) {
3801          phorum_db_mysql_error("$err: $sql");
3802          return;
3803      }
3804  
3805      // Get the message id.
3806      $pm_message_id = mysql_insert_id($conn);
3807  
3808      // Put the message in the recipient inboxes.
3809      foreach ($xref_entries as $xref) {
3810          $sql = "INSERT INTO {$PHORUM["pm_xref_table"]} SET " .
3811                 "user_id = {$xref["user_id"]}, " .
3812                 "pm_folder_id={$xref["pm_folder_id"]}, " .
3813                 "special_folder='{$xref["special_folder"]}', " .
3814                 "pm_message_id=$pm_message_id, " .
3815                 "read_flag = {$xref["read_flag"]}, " .
3816                 "reply_flag = 0";
3817          mysql_query($sql, $conn);
3818          if ($err = mysql_error($conn)) {
3819              phorum_db_mysql_error("$err: $sql");
3820              return;
3821          }
3822  
3823      }
3824  
3825      return $pm_message_id;
3826  }
3827  
3828  /**
3829   * This function updates a flag for a private message.
3830   * @param pm_id - The id of the message to update.
3831   * @param flag - The flag to update. Options are PHORUM_PM_READ_FLAG
3832   *               and PHORUM_PM_REPLY_FLAG.
3833   * @param value - The value for the flag (true or false).
3834   * @param user_id - The user to set a flag for or NULL
3835   *                 to use the current user (default).
3836   */
3837  function phorum_db_pm_setflag($pm_id, $flag, $value, $user_id = NULL)
3838  {
3839      $PHORUM = $GLOBALS["PHORUM"];
3840  
3841      $conn = phorum_db_mysql_connect();
3842  
3843      settype($pm_id, "int");
3844  
3845      if ($flag != PHORUM_PM_READ_FLAG && $flag != PHORUM_PM_REPLY_FLAG) {
3846          trigger_error("Invalid value for \$flag in function phorum_db_pm_setflag(): $flag", E_USER_WARNING);
3847          return 0;
3848      }
3849  
3850      $value = $value ? 1 : 0;
3851  
3852      if ($user_id == NULL) $user_id = $PHORUM['user']['user_id'];
3853      settype($user_id, "int");
3854  
3855      // Update the flag in the database.
3856      $sql = "UPDATE {$PHORUM["pm_xref_table"]} " .
3857             "SET $flag = $value " .
3858             "WHERE pm_message_id = $pm_id AND user_id = $user_id";
3859      $res = mysql_query($sql, $conn);
3860      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
3861  
3862      // Update message counters.
3863      if ($flag == PHORUM_PM_READ_FLAG) {
3864          phorum_db_pm_update_message_info($pm_id);
3865      }
3866  
3867      return $res;
3868  }
3869  
3870  /**
3871   * This function deletes a private message from a folder.
3872   * @param folder - The folder from which to delete the message
3873   * @param pm_id - The id of the private message to delete
3874   * @param user_id - The user to delete the message for or NULL
3875   *                 to use the current user (default).
3876   */
3877  function phorum_db_pm_delete($pm_id, $folder, $user_id = NULL)
3878  {
3879      $PHORUM = $GLOBALS["PHORUM"];
3880  
3881      $conn = phorum_db_mysql_connect();
3882  
3883      settype($pm_id, "int");
3884  
3885      if ($user_id == NULL) $user_id = $PHORUM['user']['user_id'];
3886      settype($user_id, "int");
3887  
3888      if (is_numeric($folder)) {
3889          $folder_sql = "pm_folder_id=$folder AND";
3890      } elseif ($folder == PHORUM_PM_INBOX || $folder == PHORUM_PM_OUTBOX) {
3891          $folder_sql = "pm_folder_id=0 AND special_folder='$folder' AND";
3892      } else {
3893          die ("Illegal folder '$folder' requested for user id '$user_id'");
3894      }
3895  
3896      $sql = "DELETE FROM {$PHORUM["pm_xref_table"]} " .
3897             "WHERE $folder_sql " .
3898             "user_id = $user_id AND pm_message_id = $pm_id";
3899  
3900      $res = mysql_query($sql, $conn);
3901      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
3902  
3903      // Update message counters.
3904      phorum_db_pm_update_message_info($pm_id);
3905  
3906      return $res;
3907  }
3908  
3909  /**
3910   * This function moves a private message to a different folder.
3911   * @param pm_id - The id of the private message to move.
3912   * @param from - The folder to move the message from.
3913   * @param to - The folder to move the message to.
3914   * @param user_id - The user to move the message for or NULL
3915   *                 to use the current user (default).
3916   */
3917  function phorum_db_pm_move($pm_id, $from, $to, $user_id = NULL)
3918  {
3919      $PHORUM = $GLOBALS["PHORUM"];
3920  
3921      $conn = phorum_db_mysql_connect();
3922  
3923      settype($pm_id, "int");
3924  
3925      if ($user_id == NULL) $user_id = $PHORUM['user']['user_id'];
3926      settype($user_id, "int");
3927  
3928      if (is_numeric($from)) {
3929          $folder_sql = "pm_folder_id=$from AND";
3930      } elseif ($from == PHORUM_PM_INBOX || $from == PHORUM_PM_OUTBOX) {
3931          $folder_sql = "pm_folder_id=0 AND special_folder='$from' AND";
3932      } else {
3933          die ("Illegal source folder '$from' specified");
3934      }
3935  
3936      if (is_numeric($to)) {
3937          $pm_folder_id = $to;
3938          $special_folder = 'NULL';
3939      } elseif ($to == PHORUM_PM_INBOX || $to == PHORUM_PM_OUTBOX) {
3940          $pm_folder_id = 0;
3941          $special_folder = "'$to'";
3942      } else {
3943          die ("Illegal target folder '$to' specified");
3944      }
3945  
3946      $sql = "UPDATE {$PHORUM["pm_xref_table"]} SET " .
3947             "pm_folder_id = $pm_folder_id, " .
3948             "special_folder = $special_folder " .
3949             "WHERE $folder_sql user_id = $user_id AND pm_message_id = $pm_id";
3950  
3951      $res = mysql_query($sql, $conn);
3952      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
3953      return $res;
3954  }
3955  
3956  /**
3957   * This function updates the meta information for a message. If it
3958   * detects that no xrefs are available for the message anymore,
3959   * the message will be deleted from the database. So this function
3960   * has to be called after setting the read_flag and after deleting
3961   * a message.
3962   * PMTODO maybe we need some locking here to prevent concurrent
3963   * updates of the message info.
3964   */
3965  function phorum_db_pm_update_message_info($pm_id)
3966  {
3967      $PHORUM = $GLOBALS['PHORUM'];
3968  
3969      $conn = phorum_db_mysql_connect();
3970  
3971      settype($pm_id, "int");
3972  
3973      // Find the message record. Return immediately if no message is found.
3974      $sql = "SELECT * " .
3975             "FROM {$PHORUM['pm_messages_table']} " .
3976             "WHERE pm_message_id = $pm_id";
3977      $res = mysql_query($sql, $conn);
3978      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
3979      if (mysql_num_rows($res) == 0) return $res;
3980      $pm = mysql_fetch_assoc($res);
3981  
3982      // Find the xrefs for this message.
3983      $sql = "SELECT * " .
3984             "FROM {$PHORUM["pm_xref_table"]} " .
3985             "WHERE pm_message_id = $pm_id";
3986      $res = mysql_query($sql, $conn);
3987      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
3988  
3989      // No xrefs left? Then the message can be fully deleted.
3990      if (mysql_num_rows($res) == 0) {
3991          $sql = "DELETE FROM {$PHORUM['pm_messages_table']} " .
3992                 "WHERE pm_message_id = $pm_id";
3993          $res = mysql_query($sql, $conn);
3994          if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
3995          return $res;
3996      }
3997  
3998      // Update the read flags for the recipients in the meta data.
3999      $meta = unserialize($pm["meta"]);
4000      $rcpts = $meta["recipients"];
4001      while ($row = mysql_fetch_assoc($res)) {
4002          // Only update if available. A kept copy in the outbox will
4003          // not be in the meta list, so if the copy is read, the
4004          // meta data does not have to be updated here.
4005          if (isset($rcpts[$row["user_id"]])) {
4006              $rcpts[$row["user_id"]]["read_flag"] = $row["read_flag"];
4007          }
4008      }
4009      $meta["recipients"] = $rcpts;
4010  
4011      // Store the new meta data.
4012      $meta = mysql_escape_string(serialize($meta));
4013      $sql = "UPDATE {$PHORUM['pm_messages_table']} " .
4014             "SET meta = '$meta' " .
4015             "WHERE pm_message_id = $pm_id";
4016      $res = mysql_query($sql, $conn);
4017      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
4018      return $res;
4019  }
4020  
4021  /* Take care of warning about deprecation of the old PM API functions. */
4022  function phorum_db_get_private_messages($arg1, $arg2) {
4023      phorum_db_pm_deprecated('phorum_db_get_private_messages'); }
4024  function phorum_db_get_private_message($arg1) {
4025      phorum_db_pm_deprecated('phorum_db_get_private_message'); }
4026  function phorum_db_get_private_message_count($arg1) {
4027      phorum_db_pm_deprecated('phorum_db_get_private_message_count'); }
4028  function phorum_db_put_private_messages($arg1, $arg2, $arg3, $arg4, $arg5) {
4029      phorum_db_pm_deprecated('phorum_db_put_private_messages'); }
4030  function phorum_db_update_private_message($arg1, $arg2, $arg3){
4031      phorum_db_pm_deprecated('phorum_db_update_private_message'); }
4032  function phorum_db_pm_deprecated($func) {
4033      die("$func}() has been deprecated. Please use the new private message API.");
4034  }
4035  
4036  /**
4037   * This function checks if a certain user is buddy of another user.
4038   * The function return the pm_buddy_id in case the user is a buddy
4039   * or NULL in case the user isn't.
4040   * @param buddy_user_id - The user_id to check for if it's a buddy.
4041   * @param user_id - The user_id for which the buddy list must be
4042   *                  checked or NULL to use the current user (default).
4043   */
4044  function phorum_db_pm_is_buddy($buddy_user_id, $user_id = NULL)
4045  {
4046      $PHORUM = $GLOBALS['PHORUM'];
4047      $conn = phorum_db_mysql_connect();
4048      settype($buddy_user_id, "int");
4049      if (is_null($user_id)) $user_id = $PHORUM["user"]["user_id"];
4050      settype($user_id, "int");
4051  
4052      $sql = "SELECT pm_buddy_id FROM {$PHORUM["pm_buddies_table"]} " .
4053             "WHERE user_id = $user_id AND buddy_user_id = $buddy_user_id";
4054  
4055      $res = mysql_query($sql, $conn);
4056      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
4057      if (mysql_num_rows($res)) {
4058          $row = mysql_fetch_array($res);
4059          return $row[0];
4060      } else {
4061          return NULL;
4062      }
4063  }
4064  
4065  /**
4066   * This function adds a buddy for a user. It will return the
4067   * pm_buddy_id for the new buddy. If the buddy already exists,
4068   * it will return the existing pm_buddy_id. If a non existant
4069   * user_id is used for the buddy_user_id, the function will
4070   * return NULL.
4071   * @param buddy_user_id - The user_id that has to be added as a buddy.
4072   * @param user_id - The user_id the buddy has to be added for or
4073   *                  NULL to use the current user (default).
4074   */
4075  function phorum_db_pm_buddy_add($buddy_user_id, $user_id = NULL)
4076  {
4077      $PHORUM = $GLOBALS['PHORUM'];
4078      $conn = phorum_db_mysql_connect();
4079      settype($buddy_user_id, "int");
4080      if (is_null($user_id)) $user_id = $PHORUM["user"]["user_id"];
4081      settype($user_id, "int");
4082  
4083      // Check if the buddy_user_id is a valid user_id.
4084      $valid = phorum_db_user_get($buddy_user_id, false);
4085      if (! $valid) return NULL;
4086  
4087      $pm_buddy_id = phorum_db_pm_is_buddy($buddy_user_id);
4088      if (is_null($pm_buddy_id)) {
4089          $sql = "INSERT INTO {$PHORUM["pm_buddies_table"]} SET " .
4090                 "user_id = $user_id, " .
4091                 "buddy_user_id = $buddy_user_id";
4092          $res = mysql_query($sql, $conn);
4093          if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
4094          $pm_buddy_id = mysql_insert_id($conn);
4095      }
4096  
4097      return $pm_buddy_id;
4098  }
4099  
4100  /**
4101   * This function deletes a buddy for a user.
4102   * @param buddy_user_id - The user_id that has to be deleted as a buddy.
4103   * @param user_id - The user_id the buddy has to be delete for or
4104   *                  NULL to use the current user (default).
4105   */
4106  function phorum_db_pm_buddy_delete($buddy_user_id, $user_id = NULL)
4107  {
4108      $PHORUM = $GLOBALS['PHORUM'];
4109      $conn = phorum_db_mysql_connect();
4110      settype($buddy_user_id, "int");
4111      if (is_null($user_id)) $user_id = $PHORUM["user"]["user_id"];
4112      settype($user_id, "int");
4113  
4114      $sql = "DELETE FROM {$PHORUM["pm_buddies_table"]} WHERE " .
4115             "buddy_user_id = $buddy_user_id AND user_id = $user_id";
4116      $res = mysql_query($sql, $conn);
4117      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
4118      return $res;
4119  }
4120  
4121  /**
4122   * This function retrieves a list of buddies for a user.
4123   * @param user_id - The user_id for which to retrieve the buddies
4124   *                  or NULL to user the current user (default).
4125   * @param find_mutual - Wheter to find mutual buddies or not (default not).
4126   */
4127  function phorum_db_pm_buddy_list($user_id = NULL, $find_mutual = false)
4128  {
4129      $PHORUM = $GLOBALS['PHORUM'];
4130      $conn = phorum_db_mysql_connect();
4131      if (is_null($user_id)) $user_id = $PHORUM["user"]["user_id"];
4132      settype($user_id, "int");
4133  
4134      // Get all buddies for this user.
4135      $sql = "SELECT buddy_user_id FROM {$PHORUM["pm_buddies_table"]} " .
4136             "WHERE user_id = $user_id";
4137      $res = mysql_query($sql, $conn);
4138      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
4139  
4140      $buddies = array();
4141      if (mysql_num_rows($res)) {
4142          while ($row = mysql_fetch_array($res)) {
4143              $buddies[$row[0]] = array (
4144                  'user_id' => $row[0]
4145              );
4146          }
4147      }
4148  
4149      // If we do not have to lookup mutual buddies, we're done.
4150      if (! $find_mutual) return $buddies;
4151  
4152      // Initialize mutual buddy value.
4153      foreach ($buddies as $id => $data) {
4154          $buddies[$id]["mutual"] = false;
4155      }
4156  
4157      // Get all mutual buddies.
4158      $sql = "SELECT DISTINCT a.buddy_user_id " .
4159             "FROM {$PHORUM["pm_buddies_table"]} as a, {$PHORUM["pm_buddies_table"]} as b " .
4160             "WHERE a.user_id=$user_id " .
4161             "AND b.user_id=a.buddy_user_id " .
4162             "AND b.buddy_user_id=$user_id";
4163      $res = mysql_query($sql, $conn);
4164      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
4165  
4166      if (mysql_num_rows($res)) {
4167          while ($row = mysql_fetch_array($res)) {
4168              $buddies[$row[0]]["mutual"] = true;
4169          }
4170      }
4171  
4172      return $buddies;
4173  }
4174  
4175  /**
4176  * This function returns messages or threads which are newer or older
4177  * than the given timestamp
4178  *
4179  * $time  - holds the timestamp the comparison is done against
4180  * $forum - get Threads from this forum
4181  * $mode  - should we compare against datestamp (1) or modifystamp (2)
4182  *
4183  */
4184  function phorum_db_prune_oldThreads($time,$forum=0,$mode=1) {
4185  
4186      $PHORUM = $GLOBALS['PHORUM'];
4187  
4188      settype($time, "int");
4189      settype($forum, "int");
4190      settype($mode, "int");
4191  
4192      $conn = phorum_db_mysql_connect();
4193      $numdeleted=0;
4194  
4195      $compare_field = "datestamp";
4196      if($mode == 2) {
4197        $compare_field = "modifystamp";
4198      }
4199  
4200      $forummode="";
4201      if($forum > 0) {
4202        $forummode=" AND forum_id = $forum";
4203      }
4204  
4205      // retrieving which threads to delete
4206      $sql = "select thread from {$PHORUM['message_table']} where $compare_field < $time AND parent_id=0 $forummode";
4207  
4208      $res = mysql_query($sql, $conn);
4209      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
4210  
4211      $ret=array();
4212      while($row=mysql_fetch_row($res)) {
4213          $ret[]=$row[0];
4214      }
4215  
4216      $thread_ids=implode(",",$ret);
4217  
4218      if(count($ret)) {
4219        // deleting the messages/threads
4220        $sql="delete from {$PHORUM['message_table']} where thread IN ($thread_ids)";
4221        $res = mysql_query($sql, $conn);
4222        if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
4223  
4224        $numdeleted = mysql_affected_rows($conn);
4225        if($numdeleted < 0) {
4226          $numdeleted=0;
4227        }
4228  
4229        // deleting the associated notification-entries
4230        $sql="delete from {$PHORUM['subscribers_table']} where thread IN ($thread_ids)";
4231        $res = mysql_query($sql, $conn);
4232        if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
4233  
4234  
4235        // optimizing the message-table
4236        $sql="optimize table {$PHORUM['message_table']}";
4237        $res = mysql_query($sql, $conn);
4238        if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
4239      }
4240  
4241      return $numdeleted;
4242  }
4243  
4244  /**
4245   * split thread
4246   */
4247  function phorum_db_split_thread($message, $forum_id)
4248  {
4249      settype($message, "int");
4250      settype($forum_id, "int");
4251  
4252      if($message > 0 && $forum_id > 0){
4253          // get message tree for update thread id
4254          $tree =phorum_db_get_messagetree($message, $forum_id);
4255          $queries =array();
4256          $queries[0]="UPDATE {$GLOBALS['PHORUM']['message_table']} SET thread='$message', parent_id='0' WHERE message_id ='$message'";
4257          $queries[1]="UPDATE {$GLOBALS['PHORUM']['message_table']} SET thread='$message' WHERE message_id IN ($tree)";
4258          phorum_db_run_queries($queries);
4259      }
4260  }
4261  
4262  /**
4263   * This function returns the maximum message-id in the database
4264   */
4265  function phorum_db_get_max_messageid() {
4266      $PHORUM = $GLOBALS["PHORUM"];
4267  
4268      $conn = phorum_db_mysql_connect();
4269      $maxid = 0;
4270  
4271      $sql="SELECT max(message_id) from ".$PHORUM["message_table"];
4272      $res = mysql_query($sql, $conn);
4273  
4274      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
4275  
4276      if (mysql_num_rows($res) > 0){
4277          $row = mysql_fetch_row($res);
4278          $maxid = $row[0];
4279      }
4280  
4281      return $maxid;
4282  }
4283  
4284  /**
4285   * This function increments the viewcount for a post
4286   */
4287  
4288  function phorum_db_viewcount_inc($message_id) {
4289      if($message_id < 1 || !is_numeric($message_id)) {
4290          return false;
4291      }
4292  
4293      $conn = phorum_db_mysql_connect();
4294      $sql="UPDATE ".$GLOBALS['PHORUM']['message_table']." SET viewcount=viewcount+1 WHERE message_id=$message_id";
4295      $res = mysql_query($sql, $conn);
4296  
4297      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
4298  
4299  
4300      return true;
4301  
4302  }
4303  
4304  
4305  function phorum_db_get_custom_field_users($field_id,$field_content,$match) {
4306  
4307  
4308      $field_id=(int)$field_id;
4309      $field_content=mysql_escape_string($field_content);
4310  
4311      $conn = phorum_db_mysql_connect();
4312  
4313      if($match) {
4314          $compval="LIKE";
4315      } else {
4316          $compval="=";
4317      }
4318  
4319      $sql = "select user_id from {$GLOBALS['PHORUM']['user_custom_fields_table']} where type=$field_id and data $compval '$field_content'";
4320      $res = mysql_query($sql, $conn);
4321  
4322      if ($err = mysql_error($conn)) phorum_db_mysql_error("$err: $sql");
4323  
4324      if(mysql_num_rows($res)) {
4325          $retval=array();
4326          while ($row = mysql_fetch_row($res)){
4327              $retval[$row[0]]=$row[0];
4328          }
4329      } else {
4330          $retval=NULL;
4331      }
4332  
4333      return $retval;
4334  
4335  }
4336  
4337  /**
4338   * Translates a message searching meta query into a real SQL WHERE
4339   * statement for this database backend. The meta query can be used to
4340   * define extended SQL queries, based on a meta description of the
4341   * search that has to be performed on the database.
4342   *
4343   * The meta query is an array, containing:
4344   * - query conditions
4345   * - grouping using "(" and ")"
4346   * - AND/OR specifications using "AND" and "OR".
4347   *
4348   * The query conditions are arrays, containing the following elements:
4349   *
4350   * - condition
4351   *
4352   *   A description of a condition. The syntax for this is:
4353   *   <field name to query> <operator> <match specification>
4354   *
4355   *   The <field name to query> is a field in the message query that
4356   *   we are running in this function.
4357   *
4358   *   The <operator> can be one of "=", "!=", "<", "<=", ">", ">=".
4359   *   Note that there is nothing like "LIKE" or "NOT LIKE". If a "LIKE"
4360   *   query has to be done, then that is setup through the
4361   *   <match specification> (see below).
4362   *
4363   *   The <match specification> tells us with what the field should be
4364   *   matched. The string "QUERY" inside the specification is preserved to
4365   *   specify at which spot in the query the "query" element from the
4366   *   condition array should be inserted. If "QUERY" is not available in
4367   *   the specification, then a match is made on the exact value in the
4368   *   specification. To perform "LIKE" searches (case insensitive wildcard
4369   *   searches), you can use the "*" wildcard character in the specification
4370   *   to do so.
4371   *
4372   * - query
4373   *
4374   *   The data to use in the query, in case the condition element has a
4375   *   <match specification> that uses "QUERY" in it.
4376   *
4377   * Example:
4378   *
4379   * $metaquery = array(
4380   *     array(
4381   *         "condition"  =>  "field1 = *QUERY*",
4382   *         "query"      =>  "test data"
4383   *     ),
4384   *     "AND",
4385   *     "(",
4386   *     array("condition"  => "field2 = whatever"),
4387   *     "OR",
4388   *     array("condition"  => "field2 = something else"),
4389   *     ")"
4390   * );
4391   *
4392   * For MySQL, this would be turned into the MySQL WHERE statement:
4393   * ... WHERE field1 LIKE '%test data%'
4394   *     AND (field2 = 'whatever' OR field2 = 'something else')
4395   *
4396   * @param $metaquery - A meta query description array.
4397   * @return $return - An array containing two elements. The first element
4398   *                   is either true or false, based on the success state
4399   *                   of the function call (false means that there was an
4400   *                   error). The second argument contains either a
4401   *                   WHERE statement or an error message.
4402   */
4403  function phorum_db_metaquery_compile($metaquery)
4404  {
4405      $where = '';
4406  
4407      $expect_condition  = true;
4408      $expect_groupstart = true;
4409      $expect_groupend   = false;
4410      $expect_combine    = false;
4411      $in_group          = 0;
4412  
4413      foreach ($metaquery as $part)
4414      {
4415          // Found a new condition.
4416          if ($expect_condition && is_array($part))
4417          {
4418              $cond = trim($part["condition"]);
4419              if (preg_match('/^([\w_\.]+)\s+(!?=|<=?|>=?)\s+(\S*)$/', $cond, $m))
4420              {
4421                  $field = $m[1];
4422                  $comp  = $m[2];
4423                  $match = $m[3];
4424  
4425                  $matchtokens = preg_split(
4426                      '/(\*|QUERY|NULL)/',
4427                      $match, -1,
4428                      PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY
4429                  );
4430  
4431                  $matchsql = "'";
4432                  $is_like_query = false;
4433                  foreach ($matchtokens as $m) {
4434                      if ($m == '*') {
4435                          $is_like_query = true;
4436                          $matchsql .= '%';
4437                      } elseif ($m == 'QUERY') {
4438                          $matchsql .= mysql_escape_string($part["query"]);
4439                      } else {
4440                          $matchsql .= mysql_escape_string($m);
4441                      }
4442                  }
4443                  $matchsql .= "'";
4444  
4445                  if ($is_like_query)
4446                  {
4447                      if ($comp == '=') { $comp = ' LIKE '; }
4448                      elseif ($comp == '!=') { $comp = ' NOT LIKE '; }
4449                      else return array(
4450                          false,
4451                          "Illegal metaquery token " . htmlspecialchars($cond) .
4452                          ": wildcard match does not combine with $comp operator"
4453                      );
4454                  }
4455  
4456                  $where .= "$field $comp $matchsql ";
4457              } else {
4458                  return array(
4459                      false,
4460                      "Illegal metaquery token " . htmlspecialchars($cond) .
4461                      ": condition does not match the required format"
4462                  );
4463              }
4464  
4465              $expect_condition   = false;
4466              $expect_groupstart  = false;
4467              $expect_groupend    = $in_group;
4468              $expect_combine     = true;
4469          }
4470          // Found a new group start.
4471          elseif ($expect_groupstart && $part == '(')
4472          {
4473              $where .= "(";
4474              $in_group ++;
4475  
4476              $expect_condition   = true;
4477              $expect_groupstart  = false;
4478              $expect_groupend    = false;
4479              $expect_combine     = false;
4480          }
4481          // Found a new group end.
4482          elseif ($expect_groupend && $part == ')')
4483          {
4484              $where .= ") ";
4485              $in_group --;
4486  
4487              $expect_condition   = false;
4488              $expect_groupstart  = false;
4489              $expect_groupend    = $in_group;
4490              $expect_combine     = true;
4491          }
4492          // Found a combine token (AND or OR).
4493          elseif ($expect_combine && preg_match('/^(OR|AND)$/i', $part, $m))
4494          {
4495              $where .= strtoupper($m[1]) . " ";
4496  
4497              $expect_condition   = true;
4498              $expect_groupstart  = true;
4499              $expect_groupend    = false;
4500              $expect_combine     = false;
4501          }
4502          // Unexpected or illegal token.
4503          else
4504          {
4505              die("Internal error: unexpected token in metaquery description: " .
4506                  (is_array($part) ? "condition" : htmlspecialchars($part)));
4507          }
4508      }
4509  
4510      if ($expect_groupend) die ("Internal error: unclosed group in metaquery");
4511  
4512      // If the metaquery is empty, then provide a safe true WHERE statement.
4513      if ($where == '') { $where = "1 = 1"; }
4514  
4515      return array(true, $where);
4516  }
4517  
4518  /**
4519   * Run a search on the messages, using a metaquery. See the documentation
4520   * for the phorum_db_metaquery_compile() function for more info on the
4521   * metaquery syntax.
4522   *
4523   * The query that is run here, does create a view on the messages, which
4524   * includes some thread and user info. This is used so these can also
4525   * be taken into account when selecting messages. For the condition elements
4526   * in the meta query, you can use fully qualified field names for the
4527   * <field name to query>. You can use message.*, user.* and thread.* for this.
4528   *
4529   * The primary goal for this function is to provide a backend for the
4530   * message pruning interface.
4531   *
4532   * @param $metaquery - A metaquery array.
4533   * @return $messages - An array of message records.
4534   */
4535  function phorum_db_metaquery_messagesearch($metaquery)
4536  {
4537      $PHORUM = $GLOBALS["PHORUM"];
4538  
4539      // Compile the metaquery into a where statement.
4540      list($success, $where) = phorum_db_metaquery_compile($metaquery);
4541      if (!$success) die($where);
4542  
4543      // Build the SQL query.
4544      $sql = "
4545        SELECT message.message_id,
4546               message.thread,
4547               message.parent_id,
4548               message.forum_id,
4549               message.subject,
4550               message.author,
4551               message.datestamp,
4552               message.body,
4553               message.ip,
4554               message.status,
4555               message.user_id,
4556               user.username       user_username,
4557               thread.closed       thread_closed,
4558               thread.modifystamp  thread_modifystamp,
4559               thread.thread_count thread_count
4560        FROM   {$PHORUM["message_table"]} as thread,
4561               {$PHORUM["message_table"]} as message
4562                   LEFT JOIN {$PHORUM["user_table"]} user
4563                   ON message.user_id = user.user_id
4564        WHERE  message.thread  = thread.message_id AND
4565               ($where)
4566        ORDER BY message_id ASC
4567      ";
4568  
4569      $conn = phorum_db_mysql_connect();
4570      $res = mysql_query($sql, $conn);
4571      if ($err = mysql_error($conn)) {
4572          phorum_db_mysql_error("$err: $sql");
4573          return NULL;
4574      } else {
4575          $messages = array();
4576          if(mysql_num_rows($res)) {
4577              while ($row = mysql_fetch_assoc($res)) {
4578                  $messages[$row["message_id"]] = $row;
4579              }
4580          }
4581          return $messages;
4582      }
4583  }
4584  
4585  
4586  /**
4587   * This function creates the tables needed in the database.
4588   */
4589  
4590  function phorum_db_create_tables()
4591  {
4592      $PHORUM = $GLOBALS["PHORUM"];
4593  
4594      $conn = phorum_db_mysql_connect();
4595  
4596      $retmsg = "";
4597  
4598      $queries = array(
4599  
4600          // create tables
4601          "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 NULL, 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 NULL, 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",
4602          "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 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",
4603          "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",
4604          "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",
4605          "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",
4606          "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 NULL, signature text NULL, 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 NULL, 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",
4607          "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",
4608          "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",
4609          "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), KEY group_id (group_id) ) TYPE=MyISAM",
4610          "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",
4611          "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, 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",
4612          "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",
4613          "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, PRIMARY KEY  (message_id), KEY forum_id (forum_id), FULLTEXT KEY search_text (search_text) ) TYPE=MyISAM",
4614          "CREATE TABLE {$PHORUM['user_custom_fields_table']} ( user_id INT DEFAULT '0' NOT NULL , type INT DEFAULT '0' NOT NULL , data TEXT NULL, PRIMARY KEY ( user_id , type )) TYPE=MyISAM",
4615          "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, datestamp int(10) unsigned NOT NULL default '0', meta mediumtext NULL, PRIMARY KEY(pm_message_id)) TYPE=MyISAM",
4616          "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",
4617          "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",
4618          "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",
4619  
4620      );
4621      foreach($queries as $sql){
4622          $res = mysql_query($sql, $conn);
4623          if ($err = mysql_error($conn)){
4624              $retmsg = "$err<br />";
4625              phorum_db_mysql_error("$err: $sql");
4626              break;
4627          }
4628      }
4629  
4630      return $retmsg;
4631  }
4632  
4633  // uses the database-dependant functions to escape a string
4634  function phorum_db_escape_string($str) {
4635      $str_tmp=mysql_real_escape_string($str);
4636  
4637      return $str_tmp;
4638  }
4639  
4640  /**
4641   * This function goes through an array of queries and executes them
4642   */
4643  
4644  function phorum_db_run_queries($queries){
4645      $PHORUM = $GLOBALS["PHORUM"];
4646  
4647      $conn = phorum_db_mysql_connect();
4648  
4649      $retmsg = "";
4650  
4651      foreach($queries as $sql){
4652          $res = mysql_query($sql, $conn);
4653          if ($err = mysql_error($conn)){
4654              // skip duplicate column name errors
4655              if(!stristr($err, "duplicate column")){
4656                  $retmsg.= "$err<br />";
4657                  phorum_db_mysql_error("$err: $sql");
4658              }
4659          }
4660      }
4661  
4662      return $retmsg;
4663  }
4664  
4665  /**
4666   * This function checks that a database connection can be made.
4667   */
4668  
4669  function phorum_db_check_connection(){
4670      $conn = @phorum_db_mysql_connect();
4671  
4672      return ($conn) ? true : false;
4673  }
4674  
4675  /**
4676   * handy little connection function.  This allows us to not connect to the
4677   * server until a query is actually run.
4678   * NOTE: This is not a required part of abstraction
4679   */
4680  
4681  function phorum_db_mysql_connect(){
4682      $PHORUM = $GLOBALS["PHORUM"];
4683  
4684      static $conn;
4685      if (empty($conn)){
4686          $conn = mysql_connect($PHORUM["DBCONFIG"]["server"], $PHORUM["DBCONFIG"]["user"], $PHORUM["DBCONFIG"]["password"], true);
4687          mysql_select_db($PHORUM["DBCONFIG"]["name"], $conn);
4688      }
4689      return $conn;
4690  }
4691  
4692  /**
4693   * error handling function
4694   * NOTE: This is not a required part of abstraction
4695   */
4696  
4697  function phorum_db_mysql_error($err){
4698  
4699      if(isset($GLOBALS['PHORUM']['error_logging'])) {
4700          $logsetting = $GLOBALS['PHORUM']['error_logging'];
4701      } else {
4702          $logsetting = "";
4703      }
4704      $adminemail = $GLOBALS['PHORUM']['system_email_from_address'];
4705      $cache_dir  = $GLOBALS['PHORUM']['cache'];
4706  
4707      if (!defined("PHORUM_ADMIN")){
4708          if($logsetting == 'mail') {
4709              include_once ("./include/email_functions.php");
4710  
4711              $data=array('mailmessage'=>"An SQL-error occured in your phorum-installation.\n\nThe error-message was:\n$err\n\n",
4712                          'mailsubject'=>'Phorum: an SQL-error occured');
4713              phorum_email_user(array($adminemail),$data);
4714  
4715          } elseif($logsetting == 'file') {
4716              $fp = fopen($cache_dir."/phorum-sql-errors.log",'a');
4717              fputs($fp,time().": $err\n");
4718              fclose($fp);
4719  
4720          } else {
4721              echo htmlspecialchars($err);
4722          }
4723          exit();
4724      }else{
4725          echo "<!-- $err -->";
4726      }
4727  }
4728  
4729  /**
4730   * This function will sanitize a mixed variable of data based on type
4731   *
4732   * @param   $var    The variable to be sanitized.  Passed by reference.
4733   * @param   $type   Either int or not int.
4734   * @return  null
4735   *
4736   */
4737  function phorum_db_sanitize_mixed(&$var, $type){
4738      if(is_array($var)){
4739          foreach($var as $id => $val){
4740              if($type=="int"){
4741                  $var[$id] = (int)$val;
4742              } else {
4743                  $var[$id] = mysql_escape_string($val);
4744              }
4745          }
4746      } else {
4747          if($type=="int"){
4748              $var = (int)$var;
4749          } else {
4750              $var = mysql_escape_string($var);
4751          }
4752      }
4753  }
4754  
4755  /**
4756   * Checks that a value to be used as a field name contains only characters
4757   * that would appear in a field name.
4758   *
4759   * @param   $field_name     string to be checked
4760   * @return  bool
4761   *
4762   */
4763  function phorum_db_validate_field($field_name){
4764      return (bool)preg_match('!^[a-zA-Z0-9_]+$!', $field_name);
4765  }
4766  
4767  /**
4768   * This function is used by the sanity checking system in the
4769   * admin interface to determine how much data can be transferred
4770   * in one query. This is used to detect problems with uploads that
4771   * are larger than the database server can handle.
4772   * The function returns the size in bytes. For database implementations
4773   * which do not have this kind of limit, NULL can be returned.
4774   */
4775  function phorum_db_maxpacketsize ()
4776  {
4777      $conn = phorum_db_mysql_connect();
4778      $res = mysql_query("SELECT @@global.max_allowed_packet",$conn);
4779      if (!$res) return NULL;
4780      if (mysql_num_rows($res)) {
4781          $row = mysql_fetch_array($res);
4782          return $row[0];
4783      }
4784      return NULL;
4785  }
4786  
4787  /**
4788   * This function is used by the sanity checking system to let the
4789   * database layer do sanity checks of its own. This function can
4790   * be used by every database layer to implement specific checks.
4791   *
4792   * The return value for this function should be exactly the same
4793   * as the return value expected for regular sanity checking
4794   * function (see include/admin/sanity_checks.php for information).
4795   *
4796   * There's no need to load the sanity_check.php file for the needed
4797   * constants, because this function should only be called from the
4798   * sanity checking system.
4799   */
4800  function phorum_db_sanitychecks()
4801  {
4802      $PHORUM = $GLOBALS["PHORUM"];
4803  
4804      // Retrieve the MySQL server version.
4805      $conn = phorum_db_mysql_connect();
4806      $res = mysql_query("SELECT @@global.version",$conn);
4807      if (!$res) return array(
4808          PHORUM_SANITY_WARN,
4809          "The database layer could not retrieve the version of the
4810           running MySQL server",
4811          "This probably means that you are running a really old MySQL
4812           server, which does not support \"SELECT @@global.version\"
4813           as an SQL command. If you are not running a MySQL server
4814           with version 4.0.18 or higher, then please upgrade your
4815           MySQL server. Else, contact the Phorum developers to see
4816           where this warning is coming from"
4817      );
4818  
4819      if (mysql_num_rows($res))
4820      {
4821          $row = mysql_fetch_array($res);
4822          $verstr = preg_replace('/-.*$/', '', $row[0]);
4823          $ver = explode(".", $verstr);
4824  
4825          // Version numbering format which is not recognized.
4826          if (count($ver) != 3) return array(
4827              PHORUM_SANITY_WARN,
4828              "The database layer was unable to recognize the MySQL server's
4829               version number \"" . htmlspecialchars($row[0]) . "\". Therefore,
4830               checking if the right version of MySQL is used is not possible.",
4831              "Contact the Phorum developers and report this specific
4832               version number, so the checking scripts can be updated."
4833          );
4834  
4835          settype($ver[0], 'int');
4836          settype($ver[1], 'int');
4837          settype($ver[2], 'int');
4838  
4839          // MySQL before version 4.
4840          if ($ver[0] < 4) return array(
4841              PHORUM_SANITY_CRIT,
4842              "The MySQL database server that is used is too old. The
4843               running version is \"" . htmlspecialchars($row[0]) . "\",
4844               while MySQL version 4.0.18 or higher is recommended.",
4845              "Upgrade your MySQL server to a newer version. If your
4846               website is hosted with a service provider, please contact
4847               the service provider to upgrade your MySQL database."
4848          );
4849  
4850          // MySQL before version 4.0.18, with full text search enabled.
4851          if (isset($PHORUM["DBCONFIG"]["mysql_use_ft"]) &&
4852              $PHORUM["DBCONFIG"]["mysql_use_ft"] &&
4853              $ver[0] == 4 && $ver[1] == 0 && $ver[2] < 18) return array(
4854              PHORUM_SANITY_WARN,
4855              "The MySQL database server that is used does not
4856               support all Phorum features. The running version is
4857               \"" . htmlspecialchars($row[0]) . "\", while MySQL version
4858               4.0.18 or higher is recommended.",
4859              "Upgrade your MySQL server to a newer version. If your
4860               website is hosted with a service provider, please contact
4861               the service provider to upgrade your MySQL database."
4862          );
4863  
4864          // All checks are okay.
4865          return array (PHORUM_SANITY_OK, NULL);
4866      }
4867  
4868      return array(
4869          PHORUM_SANITY_CRIT,
4870          "An unexpected problem was found in running the sanity
4871           check function phorum_db_sanitychecks().",
4872          "Contact the Phorum developers to find out what the problem is."
4873      );
4874  }
4875  
4876  ?>


Généré le : Thu Nov 29 12:22:27 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics