Subversion Repositories Applications.papyrus

Rev

Details | Last modification | View Log | RSS feed

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