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


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