phpBB
Statistics
| Revision:

root / trunk / phpBB / includes / functions_posting.php

History | View | Annotate | Download (79.8 kB)

1
<?php
2
/**
3
*
4
* @package phpBB3
5
* @copyright (c) 2005 phpBB Group
6
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
7
*
8
*/
9
10
/**
11
* @ignore
12
*/
13
if (!defined('IN_PHPBB'))
14
{
15
        exit;
16
}
17
18
/**
19
* Fill smiley templates (or just the variables) with smilies, either in a window or inline
20
*/
21
function generate_smilies($mode, $forum_id)
22
{
23
        global $db, $user, $config, $template;
24
        global $phpEx, $phpbb_root_path;
25
26
        $start = request_var('start', 0);
27
28
        if ($mode == 'window')
29
        {
30
                if ($forum_id)
31
                {
32
                        $sql = 'SELECT forum_style
33
                                FROM ' . FORUMS_TABLE . "
34
                                WHERE forum_id = $forum_id";
35
                        $result = $db->sql_query_limit($sql, 1);
36
                        $row = $db->sql_fetchrow($result);
37
                        $db->sql_freeresult($result);
38
39
                        $user->setup('posting', (int) $row['forum_style']);
40
                }
41
                else
42
                {
43
                        $user->setup('posting');
44
                }
45
46
                page_header($user->lang['SMILIES']);
47
48
                $sql = 'SELECT COUNT(smiley_id) AS item_count
49
                        FROM ' . SMILIES_TABLE . '
50
                        GROUP BY smiley_url';
51
                $result = $db->sql_query($sql, 3600);
52
53
                $smiley_count = 0;
54
                while ($row = $db->sql_fetchrow($result))
55
                {
56
                        ++$smiley_count;
57
                }
58
                $db->sql_freeresult($result);
59
60
                $template->set_filenames(array(
61
                        'body' => 'posting_smilies.html')
62
                );
63
64
                $template->assign_var('PAGINATION',
65
                        generate_pagination(append_sid("{$phpbb_root_path}posting.$phpEx", 'mode=smilies&amp;f=' . $forum_id),
66
                                $smiley_count, $config['smilies_per_page'], $start, true)
67
                );
68
        }
69
70
        $display_link = false;
71
        if ($mode == 'inline')
72
        {
73
                $sql = 'SELECT smiley_id
74
                        FROM ' . SMILIES_TABLE . '
75
                        WHERE display_on_posting = 0';
76
                $result = $db->sql_query_limit($sql, 1, 0, 3600);
77
78
                if ($row = $db->sql_fetchrow($result))
79
                {
80
                        $display_link = true;
81
                }
82
                $db->sql_freeresult($result);
83
        }
84
85
        if ($mode == 'window')
86
        {
87
                $sql = 'SELECT smiley_url, MIN(emotion) as emotion, MIN(code) AS code, smiley_width, smiley_height, MIN(smiley_order) AS min_smiley_order
88
                        FROM ' . SMILIES_TABLE . '
89
                        GROUP BY smiley_url, smiley_width, smiley_height
90
                        ORDER BY min_smiley_order';
91
                $result = $db->sql_query_limit($sql, $config['smilies_per_page'], $start, 3600);
92
        }
93
        else
94
        {
95
                $sql = 'SELECT *
96
                        FROM ' . SMILIES_TABLE . '
97
                        WHERE display_on_posting = 1
98
                        ORDER BY smiley_order';
99
                $result = $db->sql_query($sql, 3600);
100
        }
101
102
        $smilies = array();
103
        while ($row = $db->sql_fetchrow($result))
104
        {
105
                if (empty($smilies[$row['smiley_url']]))
106
                {
107
                        $smilies[$row['smiley_url']] = $row;
108
                }
109
        }
110
        $db->sql_freeresult($result);
111
112
        if (sizeof($smilies))
113
        {
114
                $root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $phpbb_root_path;
115
116
                foreach ($smilies as $row)
117
                {
118
                        $template->assign_block_vars('smiley', array(
119
                                'SMILEY_CODE'        => $row['code'],
120
                                'A_SMILEY_CODE'        => addslashes($row['code']),
121
                                'SMILEY_IMG'        => $root_path . $config['smilies_path'] . '/' . $row['smiley_url'],
122
                                'SMILEY_WIDTH'        => $row['smiley_width'],
123
                                'SMILEY_HEIGHT'        => $row['smiley_height'],
124
                                'SMILEY_DESC'        => $row['emotion'])
125
                        );
126
                }
127
        }
128
129
        if ($mode == 'inline' && $display_link)
130
        {
131
                $template->assign_vars(array(
132
                        'S_SHOW_SMILEY_LINK'         => true,
133
                        'U_MORE_SMILIES'                 => append_sid("{$phpbb_root_path}posting.$phpEx", 'mode=smilies&amp;f=' . $forum_id))
134
                );
135
        }
136
137
        if ($mode == 'window')
138
        {
139
                page_footer();
140
        }
141
}
142
143
/**
144
* Update last post information
145
* Should be used instead of sync() if only the last post information are out of sync... faster
146
*
147
* @param        string        $type                                Can be forum|topic
148
* @param        mixed        $ids                                topic/forum ids
149
* @param        bool        $return_update_sql        true: SQL query shall be returned, false: execute SQL
150
*/
151
function update_post_information($type, $ids, $return_update_sql = false)
152
{
153
        global $db;
154
155
        if (empty($ids))
156
        {
157
                return;
158
        }
159
        if (!is_array($ids))
160
        {
161
                $ids = array($ids);
162
        }
163
164
165
        $update_sql = $empty_forums = $not_empty_forums = array();
166
167
        if ($type != 'topic')
168
        {
169
                $topic_join = ', ' . TOPICS_TABLE . ' t';
170
                $topic_condition = 'AND t.topic_id = p.topic_id AND t.topic_approved = 1';
171
        }
172
        else
173
        {
174
                $topic_join = '';
175
                $topic_condition = '';
176
        }
177
178
        if (sizeof($ids) == 1)
179
        {
180
                $sql = 'SELECT MAX(p.post_id) as last_post_id
181
                        FROM ' . POSTS_TABLE . " p $topic_join
182
                        WHERE " . $db->sql_in_set('p.' . $type . '_id', $ids) . "
183
                                $topic_condition
184
                                AND p.post_approved = 1";
185
        }
186
        else
187
        {
188
                $sql = 'SELECT p.' . $type . '_id, MAX(p.post_id) as last_post_id
189
                        FROM ' . POSTS_TABLE . " p $topic_join
190
                        WHERE " . $db->sql_in_set('p.' . $type . '_id', $ids) . "
191
                                $topic_condition
192
                                AND p.post_approved = 1
193
                        GROUP BY p.{$type}_id";
194
        }
195
        $result = $db->sql_query($sql);
196
197
        $last_post_ids = array();
198
        while ($row = $db->sql_fetchrow($result))
199
        {
200
                if (sizeof($ids) == 1)
201
                {
202
                        $row[$type . '_id'] = $ids[0];
203
                }
204
205
                if ($type == 'forum')
206
                {
207
                        $not_empty_forums[] = $row['forum_id'];
208
209
                        if (empty($row['last_post_id']))
210
                        {
211
                                $empty_forums[] = $row['forum_id'];
212
                        }
213
                }
214
215
                $last_post_ids[] = $row['last_post_id'];
216
        }
217
        $db->sql_freeresult($result);
218
219
        if ($type == 'forum')
220
        {
221
                $empty_forums = array_merge($empty_forums, array_diff($ids, $not_empty_forums));
222
223
                foreach ($empty_forums as $void => $forum_id)
224
                {
225
                        $update_sql[$forum_id][] = 'forum_last_post_id = 0';
226
                        $update_sql[$forum_id][] = "forum_last_post_subject = ''";
227
                        $update_sql[$forum_id][] = 'forum_last_post_time = 0';
228
                        $update_sql[$forum_id][] = 'forum_last_poster_id = 0';
229
                        $update_sql[$forum_id][] = "forum_last_poster_name = ''";
230
                        $update_sql[$forum_id][] = "forum_last_poster_colour = ''";
231
                }
232
        }
233
234
        if (sizeof($last_post_ids))
235
        {
236
                $sql = 'SELECT p.' . $type . '_id, p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.user_id, u.username, u.user_colour
237
                        FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u
238
                        WHERE p.poster_id = u.user_id
239
                                AND ' . $db->sql_in_set('p.post_id', $last_post_ids);
240
                $result = $db->sql_query($sql);
241
242
                while ($row = $db->sql_fetchrow($result))
243
                {
244
                        $update_sql[$row["{$type}_id"]][] = $type . '_last_post_id = ' . (int) $row['post_id'];
245
                        $update_sql[$row["{$type}_id"]][] = "{$type}_last_post_subject = '" . $db->sql_escape($row['post_subject']) . "'";
246
                        $update_sql[$row["{$type}_id"]][] = $type . '_last_post_time = ' . (int) $row['post_time'];
247
                        $update_sql[$row["{$type}_id"]][] = $type . '_last_poster_id = ' . (int) $row['poster_id'];
248
                        $update_sql[$row["{$type}_id"]][] = "{$type}_last_poster_colour = '" . $db->sql_escape($row['user_colour']) . "'";
249
                        $update_sql[$row["{$type}_id"]][] = "{$type}_last_poster_name = '" . (($row['poster_id'] == ANONYMOUS) ? $db->sql_escape($row['post_username']) : $db->sql_escape($row['username'])) . "'";
250
                }
251
                $db->sql_freeresult($result);
252
        }
253
        unset($empty_forums, $ids, $last_post_ids);
254
255
        if ($return_update_sql || !sizeof($update_sql))
256
        {
257
                return $update_sql;
258
        }
259
260
        $table = ($type == 'forum') ? FORUMS_TABLE : TOPICS_TABLE;
261
262
        foreach ($update_sql as $update_id => $update_sql_ary)
263
        {
264
                $sql = "UPDATE $table
265
                        SET " . implode(', ', $update_sql_ary) . "
266
                        WHERE {$type}_id = $update_id";
267
                $db->sql_query($sql);
268
        }
269
270
        return;
271
}
272
273
/**
274
* Generate Topic Icons for display
275
*/
276
function posting_gen_topic_icons($mode, $icon_id)
277
{
278
        global $phpbb_root_path, $config, $template, $cache;
279
280
        // Grab icons
281
        $icons = $cache->obtain_icons();
282
283
        if (!$icon_id)
284
        {
285
                $template->assign_var('S_NO_ICON_CHECKED', ' checked="checked"');
286
        }
287
288
        if (sizeof($icons))
289
        {
290
                foreach ($icons as $id => $data)
291
                {
292
                        if ($data['display'])
293
                        {
294
                                $template->assign_block_vars('topic_icon', array(
295
                                        'ICON_ID'                => $id,
296
                                        'ICON_IMG'                => $phpbb_root_path . $config['icons_path'] . '/' . $data['img'],
297
                                        'ICON_WIDTH'        => $data['width'],
298
                                        'ICON_HEIGHT'        => $data['height'],
299
300
                                        'S_CHECKED'                        => ($id == $icon_id) ? true : false,
301
                                        'S_ICON_CHECKED'        => ($id == $icon_id) ? ' checked="checked"' : '')
302
                                );
303
                        }
304
                }
305
306
                return true;
307
        }
308
309
        return false;
310
}
311
312
/**
313
* Build topic types able to be selected
314
*/
315
function posting_gen_topic_types($forum_id, $cur_topic_type = POST_NORMAL)
316
{
317
        global $auth, $user, $template, $topic_type;
318
319
        $toggle = false;
320
321
        $topic_types = array(
322
                'sticky'        => array('const' => POST_STICKY, 'lang' => 'POST_STICKY'),
323
                'announce'        => array('const' => POST_ANNOUNCE, 'lang' => 'POST_ANNOUNCEMENT'),
324
                'global'        => array('const' => POST_GLOBAL, 'lang' => 'POST_GLOBAL')
325
        );
326
327
        $topic_type_array = array();
328
329
        foreach ($topic_types as $auth_key => $topic_value)
330
        {
331
                // We do not have a special post global announcement permission
332
                $auth_key = ($auth_key == 'global') ? 'announce' : $auth_key;
333
334
                if ($auth->acl_get('f_' . $auth_key, $forum_id))
335
                {
336
                        $toggle = true;
337
338
                        $topic_type_array[] = array(
339
                                'VALUE'                        => $topic_value['const'],
340
                                'S_CHECKED'                => ($cur_topic_type == $topic_value['const']) ? ' checked="checked"' : '',
341
                                'L_TOPIC_TYPE'        => $user->lang[$topic_value['lang']]
342
                        );
343
                }
344
        }
345
346
        if ($toggle)
347
        {
348
                $topic_type_array = array_merge(array(0 => array(
349
                        'VALUE'                        => POST_NORMAL,
350
                        'S_CHECKED'                => ($cur_topic_type == POST_NORMAL) ? ' checked="checked"' : '',
351
                        'L_TOPIC_TYPE'        => $user->lang['POST_NORMAL'])),
352
353
                        $topic_type_array
354
                );
355
356
                foreach ($topic_type_array as $array)
357
                {
358
                        $template->assign_block_vars('topic_type', $array);
359
                }
360
361
                $template->assign_vars(array(
362
                        'S_TOPIC_TYPE_STICKY'        => ($auth->acl_get('f_sticky', $forum_id)),
363
                        'S_TOPIC_TYPE_ANNOUNCE'        => ($auth->acl_get('f_announce', $forum_id)))
364
                );
365
        }
366
367
        return $toggle;
368
}
369
370
//
371
// Attachment related functions
372
//
373
374
/**
375
* Upload Attachment - filedata is generated here
376
* Uses upload class
377
*/
378
function upload_attachment($form_name, $forum_id, $local = false, $local_storage = '', $is_message = false, $local_filedata = false)
379
{
380
        global $auth, $user, $config, $db, $cache;
381
        global $phpbb_root_path, $phpEx;
382
383
        $filedata = array(
384
                'error'        => array()
385
        );
386
387
        include_once($phpbb_root_path . 'includes/functions_upload.' . $phpEx);
388
        $upload = new fileupload();
389
390
        if ($config['check_attachment_content'] && isset($config['mime_triggers']))
391
        {
392
                $upload->set_disallowed_content(explode('|', $config['mime_triggers']));
393
        }
394
395
        if (!$local)
396
        {
397
                $filedata['post_attach'] = ($upload->is_valid($form_name)) ? true : false;
398
        }
399
        else
400
        {
401
                $filedata['post_attach'] = true;
402
        }
403
404
        if (!$filedata['post_attach'])
405
        {
406
                $filedata['error'][] = $user->lang['NO_UPLOAD_FORM_FOUND'];
407
                return $filedata;
408
        }
409
410
        $extensions = $cache->obtain_attach_extensions((($is_message) ? false : (int) $forum_id));
411
        $upload->set_allowed_extensions(array_keys($extensions['_allowed_']));
412
413
        $file = ($local) ? $upload->local_upload($local_storage, $local_filedata) : $upload->form_upload($form_name);
414
415
        if ($file->init_error)
416
        {
417
                $filedata['post_attach'] = false;
418
                return $filedata;
419
        }
420
421
        $cat_id = (isset($extensions[$file->get('extension')]['display_cat'])) ? $extensions[$file->get('extension')]['display_cat'] : ATTACHMENT_CATEGORY_NONE;
422
423
        // Make sure the image category only holds valid images...
424
        if ($cat_id == ATTACHMENT_CATEGORY_IMAGE && !$file->is_image())
425
        {
426
                $file->remove();
427
428
                // If this error occurs a user tried to exploit an IE Bug by renaming extensions
429
                // Since the image category is displaying content inline we need to catch this.
430
                trigger_error($user->lang['ATTACHED_IMAGE_NOT_IMAGE']);
431
        }
432
433
        // Do we have to create a thumbnail?
434
        $filedata['thumbnail'] = ($cat_id == ATTACHMENT_CATEGORY_IMAGE && $config['img_create_thumbnail']) ? 1 : 0;
435
436
        // Check Image Size, if it is an image
437
        if (!$auth->acl_get('a_') && !$auth->acl_get('m_', $forum_id) && $cat_id == ATTACHMENT_CATEGORY_IMAGE)
438
        {
439
                $file->upload->set_allowed_dimensions(0, 0, $config['img_max_width'], $config['img_max_height']);
440
        }
441
442
        // Admins and mods are allowed to exceed the allowed filesize
443
        if (!$auth->acl_get('a_') && !$auth->acl_get('m_', $forum_id))
444
        {
445
                if (!empty($extensions[$file->get('extension')]['max_filesize']))
446
                {
447
                        $allowed_filesize = $extensions[$file->get('extension')]['max_filesize'];
448
                }
449
                else
450
                {
451
                        $allowed_filesize = ($is_message) ? $config['max_filesize_pm'] : $config['max_filesize'];
452
                }
453
454
                $file->upload->set_max_filesize($allowed_filesize);
455
        }
456
457
        $file->clean_filename('unique', $user->data['user_id'] . '_');
458
459
        // Are we uploading an image *and* this image being within the image category? Only then perform additional image checks.
460
        $no_image = ($cat_id == ATTACHMENT_CATEGORY_IMAGE) ? false : true;
461
462
        $file->move_file($config['upload_path'], false, $no_image);
463
464
        if (sizeof($file->error))
465
        {
466
                $file->remove();
467
                $filedata['error'] = array_merge($filedata['error'], $file->error);
468
                $filedata['post_attach'] = false;
469
470
                return $filedata;
471
        }
472
473
        $filedata['filesize'] = $file->get('filesize');
474
        $filedata['mimetype'] = $file->get('mimetype');
475
        $filedata['extension'] = $file->get('extension');
476
        $filedata['physical_filename'] = $file->get('realname');
477
        $filedata['real_filename'] = $file->get('uploadname');
478
        $filedata['filetime'] = time();
479
480
        // Check our complete quota
481
        if ($config['attachment_quota'])
482
        {
483
                if ($config['upload_dir_size'] + $file->get('filesize') > $config['attachment_quota'])
484
                {
485
                        $filedata['error'][] = $user->lang['ATTACH_QUOTA_REACHED'];
486
                        $filedata['post_attach'] = false;
487
488
                        $file->remove();
489
490
                        return $filedata;
491
                }
492
        }
493
494
        // Check free disk space
495
        if ($free_space = @disk_free_space($phpbb_root_path . $config['upload_path']))
496
        {
497
                if ($free_space <= $file->get('filesize'))
498
                {
499
                        $filedata['error'][] = $user->lang['ATTACH_QUOTA_REACHED'];
500
                        $filedata['post_attach'] = false;
501
502
                        $file->remove();
503
504
                        return $filedata;
505
                }
506
        }
507
508
        // Create Thumbnail
509
        if ($filedata['thumbnail'])
510
        {
511
                $source = $file->get('destination_file');
512
                $destination = $file->get('destination_path') . '/thumb_' . $file->get('realname');
513
514
                if (!create_thumbnail($source, $destination, $file->get('mimetype')))
515
                {
516
                        $filedata['thumbnail'] = 0;
517
                }
518
        }
519
520
        return $filedata;
521
}
522
523
/**
524
* Calculate the needed size for Thumbnail
525
*/
526
function get_img_size_format($width, $height)
527
{
528
        global $config;
529
530
        // Maximum Width the Image can take
531
        $max_width = ($config['img_max_thumb_width']) ? $config['img_max_thumb_width'] : 400;
532
533
        if ($width > $height)
534
        {
535
                return array(
536
                        round($width * ($max_width / $width)),
537
                        round($height * ($max_width / $width))
538
                );
539
        }
540
        else
541
        {
542
                return array(
543
                        round($width * ($max_width / $height)),
544
                        round($height * ($max_width / $height))
545
                );
546
        }
547
}
548
549
/**
550
* Return supported image types
551
*/
552
function get_supported_image_types($type = false)
553
{
554
        if (@extension_loaded('gd'))
555
        {
556
                $format = imagetypes();
557
                $new_type = 0;
558
559
                if ($type !== false)
560
                {
561
                        // Type is one of the IMAGETYPE constants - it is fetched from getimagesize()
562
                        switch ($type)
563
                        {
564
                                // GIF
565
                                case IMAGETYPE_GIF:
566
                                        $new_type = ($format & IMG_GIF) ? IMG_GIF : false;
567
                                break;
568
569
                                // JPG, JPC, JP2
570
                                case IMAGETYPE_JPEG:
571
                                case IMAGETYPE_JPC:
572
                                case IMAGETYPE_JPEG2000:
573
                                case IMAGETYPE_JP2:
574
                                case IMAGETYPE_JPX:
575
                                case IMAGETYPE_JB2:
576
                                        $new_type = ($format & IMG_JPG) ? IMG_JPG : false;
577
                                break;
578
579
                                // PNG
580
                                case IMAGETYPE_PNG:
581
                                        $new_type = ($format & IMG_PNG) ? IMG_PNG : false;
582
                                break;
583
584
                                // WBMP
585
                                case IMAGETYPE_WBMP:
586
                                        $new_type = ($format & IMG_WBMP) ? IMG_WBMP : false;
587
                                break;
588
                        }
589
                }
590
                else
591
                {
592
                        $new_type = array();
593
                        $go_through_types = array(IMG_GIF, IMG_JPG, IMG_PNG, IMG_WBMP);
594
595
                        foreach ($go_through_types as $check_type)
596
                        {
597
                                if ($format & $check_type)
598
                                {
599
                                        $new_type[] = $check_type;
600
                                }
601
                        }
602
                }
603
604
                return array(
605
                        'gd'                => ($new_type) ? true : false,
606
                        'format'        => $new_type,
607
                        'version'        => (function_exists('imagecreatetruecolor')) ? 2 : 1
608
                );
609
        }
610
611
        return array('gd' => false);
612
}
613
614
/**
615
* Create Thumbnail
616
*/
617
function create_thumbnail($source, $destination, $mimetype)
618
{
619
        global $config;
620
621
        $min_filesize = (int) $config['img_min_thumb_filesize'];
622
        $img_filesize = (file_exists($source)) ? @filesize($source) : false;
623
624
        if (!$img_filesize || $img_filesize <= $min_filesize)
625
        {
626
                return false;
627
        }
628
629
        $dimension = @getimagesize($source);
630
631
        if ($dimension === false)
632
        {
633
                return false;
634
        }
635
636
        list($width, $height, $type, ) = $dimension;
637
638
        if (empty($width) || empty($height))
639
        {
640
                return false;
641
        }
642
643
        list($new_width, $new_height) = get_img_size_format($width, $height);
644
645
        // Do not create a thumbnail if the resulting width/height is bigger than the original one
646
        if ($new_width >= $width && $new_height >= $height)
647
        {
648
                return false;
649
        }
650
651
        $used_imagick = false;
652
653
        // Only use imagemagick if defined and the passthru function not disabled
654
        if ($config['img_imagick'] && function_exists('passthru'))
655
        {
656
                if (substr($config['img_imagick'], -1) !== '/')
657
                {
658
                        $config['img_imagick'] .= '/';
659
                }
660
661
                @passthru(escapeshellcmd($config['img_imagick']) . 'convert' . ((defined('PHP_OS') && preg_match('#^win#i', PHP_OS)) ? '.exe' : '') . ' -quality 85 -geometry ' . $new_width . 'x' . $new_height . ' "' . str_replace('\\', '/', $source) . '" "' . str_replace('\\', '/', $destination) . '"');
662
663
                if (file_exists($destination))
664
                {
665
                        $used_imagick = true;
666
                }
667
        }
668
669
        if (!$used_imagick)
670
        {
671
                $type = get_supported_image_types($type);
672
673
                if ($type['gd'])
674
                {
675
                        // If the type is not supported, we are not able to create a thumbnail
676
                        if ($type['format'] === false)
677
                        {
678
                                return false;
679
                        }
680
681
                        switch ($type['format'])
682
                        {
683
                                case IMG_GIF:
684
                                        $image = @imagecreatefromgif($source);
685
                                break;
686
687
                                case IMG_JPG:
688
                                        @ini_set('gd.jpeg_ignore_warning', 1);
689
                                        $image = @imagecreatefromjpeg($source);
690
                                break;
691
692
                                case IMG_PNG:
693
                                        $image = @imagecreatefrompng($source);
694
                                break;
695
696
                                case IMG_WBMP:
697
                                        $image = @imagecreatefromwbmp($source);
698
                                break;
699
                        }
700
701
                        if (empty($image))
702
                        {
703
                                return false;
704
                        }
705
706
                        if ($type['version'] == 1)
707
                        {
708
                                $new_image = imagecreate($new_width, $new_height);
709
710
                                if ($new_image === false)
711
                                {
712
                                        return false;
713
                                }
714
715
                                imagecopyresized($new_image, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
716
                        }
717
                        else
718
                        {
719
                                $new_image = imagecreatetruecolor($new_width, $new_height);
720
721
                                if ($new_image === false)
722
                                {
723
                                        return false;
724
                                }
725
726
                                // Preserve alpha transparency (png for example)
727
                                @imagealphablending($new_image, false);
728
                                @imagesavealpha($new_image, true);
729
730
                                imagecopyresampled($new_image, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
731
                        }
732
733
                        // If we are in safe mode create the destination file prior to using the gd functions to circumvent a PHP bug
734
                        if (@ini_get('safe_mode') || @strtolower(ini_get('safe_mode')) == 'on')
735
                        {
736
                                @touch($destination);
737
                        }
738
739
                        switch ($type['format'])
740
                        {
741
                                case IMG_GIF:
742
                                        imagegif($new_image, $destination);
743
                                break;
744
745
                                case IMG_JPG:
746
                                        imagejpeg($new_image, $destination, 90);
747
                                break;
748
749
                                case IMG_PNG:
750
                                        imagepng($new_image, $destination);
751
                                break;
752
753
                                case IMG_WBMP:
754
                                        imagewbmp($new_image, $destination);
755
                                break;
756
                        }
757
758
                        imagedestroy($new_image);
759
                }
760
                else
761
                {
762
                        return false;
763
                }
764
        }
765
766
        if (!file_exists($destination))
767
        {
768
                return false;
769
        }
770
771
        phpbb_chmod($destination, CHMOD_READ | CHMOD_WRITE);
772
773
        return true;
774
}
775
776
/**
777
* Assign Inline attachments (build option fields)
778
*/
779
function posting_gen_inline_attachments(&$attachment_data)
780
{
781
        global $template;
782
783
        if (sizeof($attachment_data))
784
        {
785
                $s_inline_attachment_options = '';
786
787
                foreach ($attachment_data as $i => $attachment)
788
                {
789
                        $s_inline_attachment_options .= '<option value="' . $i . '">' . utf8_basename($attachment['real_filename']) . '</option>';
790
                }
791
792
                $template->assign_var('S_INLINE_ATTACHMENT_OPTIONS', $s_inline_attachment_options);
793
794
                return true;
795
        }
796
797
        return false;
798
}
799
800
/**
801
* Generate inline attachment entry
802
*/
803
function posting_gen_attachment_entry($attachment_data, &$filename_data, $show_attach_box = true)
804
{
805
        global $template, $config, $phpbb_root_path, $phpEx, $user;
806
807
        // Some default template variables
808
        $template->assign_vars(array(
809
                'S_SHOW_ATTACH_BOX'        => $show_attach_box,
810
                'S_HAS_ATTACHMENTS'        => sizeof($attachment_data),
811
                'FILESIZE'                        => $config['max_filesize'],
812
                'FILE_COMMENT'                => (isset($filename_data['filecomment'])) ? $filename_data['filecomment'] : '',
813
        ));
814
815
        if (sizeof($attachment_data))
816
        {
817
                // We display the posted attachments within the desired order.
818
                ($config['display_order']) ? krsort($attachment_data) : ksort($attachment_data);
819
820
                foreach ($attachment_data as $count => $attach_row)
821
                {
822
                        $hidden = '';
823
                        $attach_row['real_filename'] = utf8_basename($attach_row['real_filename']);
824
825
                        foreach ($attach_row as $key => $value)
826
                        {
827
                                $hidden .= '<input type="hidden" name="attachment_data[' . $count . '][' . $key . ']" value="' . $value . '" />';
828
                        }
829
830
                        $download_link = append_sid("{$phpbb_root_path}download/file.$phpEx", 'mode=view&amp;id=' . (int) $attach_row['attach_id'], true, ($attach_row['is_orphan']) ? $user->session_id : false);
831
832
                        $template->assign_block_vars('attach_row', array(
833
                                'FILENAME'                        => utf8_basename($attach_row['real_filename']),
834
                                'A_FILENAME'                => addslashes(utf8_basename($attach_row['real_filename'])),
835
                                'FILE_COMMENT'                => $attach_row['attach_comment'],
836
                                'ATTACH_ID'                        => $attach_row['attach_id'],
837
                                'S_IS_ORPHAN'                => $attach_row['is_orphan'],
838
                                'ASSOC_INDEX'                => $count,
839
840
                                'U_VIEW_ATTACHMENT'        => $download_link,
841
                                'S_HIDDEN'                        => $hidden)
842
                        );
843
                }
844
        }
845
846
        return sizeof($attachment_data);
847
}
848
849
//
850
// General Post functions
851
//
852
853
/**
854
* Load Drafts
855
*/
856
function load_drafts($topic_id = 0, $forum_id = 0, $id = 0, $pm_action = '', $msg_id = 0)
857
{
858
        global $user, $db, $template, $auth;
859
        global $phpbb_root_path, $phpEx;
860
861
        $topic_ids = $forum_ids = $draft_rows = array();
862
863
        // Load those drafts not connected to forums/topics
864
        // If forum_id == 0 AND topic_id == 0 then this is a PM draft
865
        if (!$topic_id && !$forum_id)
866
        {
867
                $sql_and = ' AND d.forum_id = 0 AND d.topic_id = 0';
868
        }
869
        else
870
        {
871
                $sql_and = '';
872
                $sql_and .= ($forum_id) ? ' AND d.forum_id = ' . (int) $forum_id : '';
873
                $sql_and .= ($topic_id) ? ' AND d.topic_id = ' . (int) $topic_id : '';
874
        }
875
876
        $sql = 'SELECT d.*, f.forum_id, f.forum_name
877
                FROM ' . DRAFTS_TABLE . ' d
878
                LEFT JOIN ' . FORUMS_TABLE . ' f ON (f.forum_id = d.forum_id)
879
                        WHERE d.user_id = ' . $user->data['user_id'] . "
880
                        $sql_and
881
                ORDER BY d.save_time DESC";
882
        $result = $db->sql_query($sql);
883
884
        while ($row = $db->sql_fetchrow($result))
885
        {
886
                if ($row['topic_id'])
887
                {
888
                        $topic_ids[] = (int) $row['topic_id'];
889
                }
890
                $draft_rows[] = $row;
891
        }
892
        $db->sql_freeresult($result);
893
894
        if (!sizeof($draft_rows))
895
        {
896
                return;
897
        }
898
899
        $topic_rows = array();
900
        if (sizeof($topic_ids))
901
        {
902
                $sql = 'SELECT topic_id, forum_id, topic_title
903
                        FROM ' . TOPICS_TABLE . '
904
                        WHERE ' . $db->sql_in_set('topic_id', array_unique($topic_ids));
905
                $result = $db->sql_query($sql);
906
907
                while ($row = $db->sql_fetchrow($result))
908
                {
909
                        $topic_rows[$row['topic_id']] = $row;
910
                }
911
                $db->sql_freeresult($result);
912
        }
913
        unset($topic_ids);
914
915
        $template->assign_var('S_SHOW_DRAFTS', true);
916
917
        foreach ($draft_rows as $draft)
918
        {
919
                $link_topic = $link_forum = $link_pm = false;
920
                $insert_url = $view_url = $title = '';
921
922
                if (isset($topic_rows[$draft['topic_id']])
923
                        && (
924
                                ($topic_rows[$draft['topic_id']]['forum_id'] && $auth->acl_get('f_read', $topic_rows[$draft['topic_id']]['forum_id']))
925
                                ||
926
                                (!$topic_rows[$draft['topic_id']]['forum_id'] && $auth->acl_getf_global('f_read'))
927
                        ))
928
                {
929
                        $topic_forum_id = ($topic_rows[$draft['topic_id']]['forum_id']) ? $topic_rows[$draft['topic_id']]['forum_id'] : $forum_id;
930
931
                        $link_topic = true;
932
                        $view_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $topic_forum_id . '&amp;t=' . $draft['topic_id']);
933
                        $title = $topic_rows[$draft['topic_id']]['topic_title'];
934
935
                        $insert_url = append_sid("{$phpbb_root_path}posting.$phpEx", 'f=' . $topic_forum_id . '&amp;t=' . $draft['topic_id'] . '&amp;mode=reply&amp;d=' . $draft['draft_id']);
936
                }
937
                else if ($draft['forum_id'] && $auth->acl_get('f_read', $draft['forum_id']))
938
                {
939
                        $link_forum = true;
940
                        $view_url = append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $draft['forum_id']);
941
                        $title = $draft['forum_name'];
942
943
                        $insert_url = append_sid("{$phpbb_root_path}posting.$phpEx", 'f=' . $draft['forum_id'] . '&amp;mode=post&amp;d=' . $draft['draft_id']);
944
                }
945
                else
946
                {
947
                        // Either display as PM draft if forum_id and topic_id are empty or if access to the forums has been denied afterwards...
948
                        $link_pm = true;
949
                        $insert_url = append_sid("{$phpbb_root_path}ucp.$phpEx", "i=$id&amp;mode=compose&amp;d={$draft['draft_id']}" . (($pm_action) ? "&amp;action=$pm_action" : '') . (($msg_id) ? "&amp;p=$msg_id" : ''));
950
                }
951
952
                $template->assign_block_vars('draftrow', array(
953
                        'DRAFT_ID'                => $draft['draft_id'],
954
                        'DATE'                        => $user->format_date($draft['save_time']),
955
                        'DRAFT_SUBJECT'        => $draft['draft_subject'],
956
957
                        'TITLE'                        => $title,
958
                        'U_VIEW'                => $view_url,
959
                        'U_INSERT'                => $insert_url,
960
961
                        'S_LINK_PM'                => $link_pm,
962
                        'S_LINK_TOPIC'        => $link_topic,
963
                        'S_LINK_FORUM'        => $link_forum)
964
                );
965
        }
966
}
967
968
/**
969
* Topic Review
970
*/
971
function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id = 0, $show_quote_button = true)
972
{
973
        global $user, $auth, $db, $template, $bbcode, $cache;
974
        global $config, $phpbb_root_path, $phpEx;
975
976
        // Go ahead and pull all data for this topic
977
        $sql = 'SELECT p.post_id
978
                FROM ' . POSTS_TABLE . ' p' . "
979
                WHERE p.topic_id = $topic_id
980
                        " . ((!$auth->acl_get('m_approve', $forum_id)) ? 'AND p.post_approved = 1' : '') . '
981
                        ' . (($mode == 'post_review') ? " AND p.post_id > $cur_post_id" : '') . '
982
                        ' . (($mode == 'post_review_edit') ? " AND p.post_id = $cur_post_id" : '') . '
983
                ORDER BY p.post_time ';
984
        $sql .= ($mode == 'post_review') ? 'ASC' : 'DESC';
985
        $result = $db->sql_query_limit($sql, $config['posts_per_page']);
986
987
        $post_list = array();
988
989
        while ($row = $db->sql_fetchrow($result))
990
        {
991
                $post_list[] = $row['post_id'];
992
        }
993
994
        $db->sql_freeresult($result);
995
996
        if (!sizeof($post_list))
997
        {
998
                return false;
999
        }
1000
1001
        // Handle 'post_review_edit' like 'post_review' from now on
1002
        if ($mode == 'post_review_edit')
1003
        {
1004
                $mode = 'post_review';
1005
        }
1006
1007
        $sql_ary = array(
1008
                'SELECT'        => 'u.username, u.user_id, u.user_colour, p.*, z.friend, z.foe',
1009
1010
                'FROM'                => array(
1011
                        USERS_TABLE                => 'u',
1012
                        POSTS_TABLE                => 'p',
1013
                ),
1014
1015
                'LEFT_JOIN'        => array(
1016
                        array(
1017
                                'FROM'        => array(ZEBRA_TABLE => 'z'),
1018
                                'ON'        => 'z.user_id = ' . $user->data['user_id'] . ' AND z.zebra_id = p.poster_id',
1019
                        ),
1020
                ),
1021
1022
                'WHERE'                => $db->sql_in_set('p.post_id', $post_list) . '
1023
                        AND u.user_id = p.poster_id',
1024
        );
1025
1026
        $sql = $db->sql_build_query('SELECT', $sql_ary);
1027
        $result = $db->sql_query($sql);
1028
1029
        $bbcode_bitfield = '';
1030
        $rowset = array();
1031
        $has_attachments = false;
1032
        while ($row = $db->sql_fetchrow($result))
1033
        {
1034
                $rowset[$row['post_id']] = $row;
1035
                $bbcode_bitfield = $bbcode_bitfield | base64_decode($row['bbcode_bitfield']);
1036
1037
                if ($row['post_attachment'])
1038
                {
1039
                        $has_attachments = true;
1040
                }
1041
        }
1042
        $db->sql_freeresult($result);
1043
1044
        // Instantiate BBCode class
1045
        if (!isset($bbcode) && $bbcode_bitfield !== '')
1046
        {
1047
                include_once($phpbb_root_path . 'includes/bbcode.' . $phpEx);
1048
                $bbcode = new bbcode(base64_encode($bbcode_bitfield));
1049
        }
1050
1051
        // Grab extensions
1052
        $extensions = $attachments = array();
1053
        if ($has_attachments && $auth->acl_get('u_download') && $auth->acl_get('f_download', $forum_id))
1054
        {
1055
                $extensions = $cache->obtain_attach_extensions($forum_id);
1056
1057
                // Get attachments...
1058
                $sql = 'SELECT *
1059
                        FROM ' . ATTACHMENTS_TABLE . '
1060
                        WHERE ' . $db->sql_in_set('post_msg_id', $post_list) . '
1061
                                AND in_message = 0
1062
                        ORDER BY filetime DESC, post_msg_id ASC';
1063
                $result = $db->sql_query($sql);
1064
1065
                while ($row = $db->sql_fetchrow($result))
1066
                {
1067
                        $attachments[$row['post_msg_id']][] = $row;
1068
                }
1069
                $db->sql_freeresult($result);
1070
        }
1071
1072
        for ($i = 0, $end = sizeof($post_list); $i < $end; ++$i)
1073
        {
1074
                // A non-existing rowset only happens if there was no user present for the entered poster_id
1075
                // This could be a broken posts table.
1076
                if (!isset($rowset[$post_list[$i]]))
1077
                {
1078
                        continue;
1079
                }
1080
1081
                $row = $rowset[$post_list[$i]];
1082
1083
                $poster_id                = $row['user_id'];
1084
                $post_subject        = $row['post_subject'];
1085
                $message                = censor_text($row['post_text']);
1086
1087
                $decoded_message = false;
1088
1089
                if ($show_quote_button && $auth->acl_get('f_reply', $forum_id))
1090
                {
1091
                        $decoded_message = $message;
1092
                        decode_message($decoded_message, $row['bbcode_uid']);
1093
1094
                        $decoded_message = bbcode_nl2br($decoded_message);
1095
                }
1096
1097
                if ($row['bbcode_bitfield'])
1098
                {
1099
                        $bbcode->bbcode_second_pass($message, $row['bbcode_uid'], $row['bbcode_bitfield']);
1100
                }
1101
1102
                $message = bbcode_nl2br($message);
1103
                $message = smiley_text($message, !$row['enable_smilies']);
1104
1105
                if (!empty($attachments[$row['post_id']]))
1106
                {
1107
                        $update_count = array();
1108
                        parse_attachments($forum_id, $message, $attachments[$row['post_id']], $update_count);
1109
                }
1110
1111
                $post_subject = censor_text($post_subject);
1112
1113
                $post_anchor = ($mode == 'post_review') ? 'ppr' . $row['post_id'] : 'pr' . $row['post_id'];
1114
                $u_show_post = append_sid($phpbb_root_path . 'viewtopic.' . $phpEx, "f=$forum_id&amp;t=$topic_id&amp;p={$row['post_id']}&amp;view=show#p{$row['post_id']}");
1115
1116
                $template->assign_block_vars($mode . '_row', array(
1117
                        'POST_AUTHOR_FULL'                => get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']),
1118
                        'POST_AUTHOR_COLOUR'        => get_username_string('colour', $poster_id, $row['username'], $row['user_colour'], $row['post_username']),
1119
                        'POST_AUTHOR'                        => get_username_string('username', $poster_id, $row['username'], $row['user_colour'], $row['post_username']),
1120
                        'U_POST_AUTHOR'                        => get_username_string('profile', $poster_id, $row['username'], $row['user_colour'], $row['post_username']),
1121
1122
                        'S_HAS_ATTACHMENTS'        => (!empty($attachments[$row['post_id']])) ? true : false,
1123
                        'S_FRIEND'                        => ($row['friend']) ? true : false,
1124
                        'S_IGNORE_POST'                => ($row['foe']) ? true : false,
1125
                        'L_IGNORE_POST'                => ($row['foe']) ? sprintf($user->lang['POST_BY_FOE'], get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), "<a href=\"{$u_show_post}\" onclick=\"dE('{$post_anchor}', 1); return false;\">", '</a>') : '',
1126
1127
                        'POST_SUBJECT'                => $post_subject,
1128
                        'MINI_POST_IMG'                => $user->img('icon_post_target', $user->lang['POST']),
1129
                        'POST_DATE'                        => $user->format_date($row['post_time']),
1130
                        'MESSAGE'                        => $message,
1131
                        'DECODED_MESSAGE'        => $decoded_message,
1132
                        'POST_ID'                        => $row['post_id'],
1133
                        'U_MINI_POST'                => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'p=' . $row['post_id']) . '#p' . $row['post_id'],
1134
                        'U_MCP_DETAILS'                => ($auth->acl_get('m_info', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=main&amp;mode=post_details&amp;f=' . $forum_id . '&amp;p=' . $row['post_id'], true, $user->session_id) : '',
1135
                        'POSTER_QUOTE'                => ($show_quote_button && $auth->acl_get('f_reply', $forum_id)) ? addslashes(get_username_string('username', $poster_id, $row['username'], $row['user_colour'], $row['post_username'])) : '')
1136
                );
1137
1138
                // Display not already displayed Attachments for this post, we already parsed them. ;)
1139
                if (!empty($attachments[$row['post_id']]))
1140
                {
1141
                        foreach ($attachments[$row['post_id']] as $attachment)
1142
                        {
1143
                                $template->assign_block_vars($mode . '_row.attachment', array(
1144
                                        'DISPLAY_ATTACHMENT'        => $attachment)
1145
                                );
1146
                        }
1147
                }
1148
1149
                unset($rowset[$post_list[$i]]);
1150
        }
1151
1152
        if ($mode == 'topic_review')
1153
        {
1154
                $template->assign_var('QUOTE_IMG', $user->img('icon_post_quote', $user->lang['REPLY_WITH_QUOTE']));
1155
        }
1156
1157
        return true;
1158
}
1159
1160
/**
1161
* User Notification
1162
*/
1163
function user_notification($mode, $subject, $topic_title, $forum_name, $forum_id, $topic_id, $post_id)
1164
{
1165
        global $db, $user, $config, $phpbb_root_path, $phpEx, $auth;
1166
1167
        $topic_notification = ($mode == 'reply' || $mode == 'quote') ? true : false;
1168
        $forum_notification = ($mode == 'post') ? true : false;
1169
1170
        if (!$topic_notification && !$forum_notification)
1171
        {
1172
                trigger_error('NO_MODE');
1173
        }
1174
1175
        if (($topic_notification && !$config['allow_topic_notify']) || ($forum_notification && !$config['allow_forum_notify']))
1176
        {
1177
                return;
1178
        }
1179
1180
        $topic_title = ($topic_notification) ? $topic_title : $subject;
1181
        $topic_title = censor_text($topic_title);
1182
1183
        // Get banned User ID's
1184
        $sql = 'SELECT ban_userid
1185
                FROM ' . BANLIST_TABLE . '
1186
                WHERE ban_userid <> 0
1187
                        AND ban_exclude <> 1';
1188
        $result = $db->sql_query($sql);
1189
1190
        $sql_ignore_users = ANONYMOUS . ', ' . $user->data['user_id'];
1191
        while ($row = $db->sql_fetchrow($result))
1192
        {
1193
                $sql_ignore_users .= ', ' . (int) $row['ban_userid'];
1194
        }
1195
        $db->sql_freeresult($result);
1196
1197
        $notify_rows = array();
1198
1199
        // -- get forum_userids        || topic_userids
1200
        $sql = 'SELECT u.user_id, u.username, u.user_email, u.user_lang, u.user_notify_type, u.user_jabber
1201
                FROM ' . (($topic_notification) ? TOPICS_WATCH_TABLE : FORUMS_WATCH_TABLE) . ' w, ' . USERS_TABLE . ' u
1202
                WHERE w.' . (($topic_notification) ? 'topic_id' : 'forum_id') . ' = ' . (($topic_notification) ? $topic_id : $forum_id) . "
1203
                        AND w.user_id NOT IN ($sql_ignore_users)
1204
                        AND w.notify_status = " . NOTIFY_YES . '
1205
                        AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')
1206
                        AND u.user_id = w.user_id';
1207
        $result = $db->sql_query($sql);
1208
1209
        while ($row = $db->sql_fetchrow($result))
1210
        {
1211
                $notify_rows[$row['user_id']] = array(
1212
                        'user_id'                => $row['user_id'],
1213
                        'username'                => $row['username'],
1214
                        'user_email'        => $row['user_email'],
1215
                        'user_jabber'        => $row['user_jabber'],
1216
                        'user_lang'                => $row['user_lang'],
1217
                        'notify_type'        => ($topic_notification) ? 'topic' : 'forum',
1218
                        'template'                => ($topic_notification) ? 'topic_notify' : 'newtopic_notify',
1219
                        'method'                => $row['user_notify_type'],
1220
                        'allowed'                => false
1221
                );
1222
        }
1223
        $db->sql_freeresult($result);
1224
1225
        // forum notification is sent to those not already receiving topic notifications
1226
        if ($topic_notification)
1227
        {
1228
                if (sizeof($notify_rows))
1229
                {
1230
                        $sql_ignore_users .= ', ' . implode(', ', array_keys($notify_rows));
1231
                }
1232
1233
                $sql = 'SELECT u.user_id, u.username, u.user_email, u.user_lang, u.user_notify_type, u.user_jabber
1234
                        FROM ' . FORUMS_WATCH_TABLE . ' fw, ' . USERS_TABLE . " u
1235
                        WHERE fw.forum_id = $forum_id
1236
                                AND fw.user_id NOT IN ($sql_ignore_users)
1237
                                AND fw.notify_status = " . NOTIFY_YES . '
1238
                                AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')
1239
                                AND u.user_id = fw.user_id';
1240
                $result = $db->sql_query($sql);
1241
1242
                while ($row = $db->sql_fetchrow($result))
1243
                {
1244
                        $notify_rows[$row['user_id']] = array(
1245
                                'user_id'                => $row['user_id'],
1246
                                'username'                => $row['username'],
1247
                                'user_email'        => $row['user_email'],
1248
                                'user_jabber'        => $row['user_jabber'],
1249
                                'user_lang'                => $row['user_lang'],
1250
                                'notify_type'        => 'forum',
1251
                                'template'                => 'forum_notify',
1252
                                'method'                => $row['user_notify_type'],
1253
                                'allowed'                => false
1254
                        );
1255
                }
1256
                $db->sql_freeresult($result);
1257
        }
1258
1259
        if (!sizeof($notify_rows))
1260
        {
1261
                return;
1262
        }
1263
1264
        // Make sure users are allowed to read the forum
1265
        foreach ($auth->acl_get_list(array_keys($notify_rows), 'f_read', $forum_id) as $forum_id => $forum_ary)
1266
        {
1267
                foreach ($forum_ary as $auth_option => $user_ary)
1268
                {
1269
                        foreach ($user_ary as $user_id)
1270
                        {
1271
                                $notify_rows[$user_id]['allowed'] = true;
1272
                        }
1273
                }
1274
        }
1275
1276
1277
        // Now, we have to do a little step before really sending, we need to distinguish our users a little bit. ;)
1278
        $msg_users = $delete_ids = $update_notification = array();
1279
        foreach ($notify_rows as $user_id => $row)
1280
        {
1281
                if (!$row['allowed'] || !trim($row['user_email']))
1282
                {
1283
                        $delete_ids[$row['notify_type']][] = $row['user_id'];
1284
                }
1285
                else
1286
                {
1287
                        $msg_users[] = $row;
1288
                        $update_notification[$row['notify_type']][] = $row['user_id'];
1289
                }
1290
        }
1291
        unset($notify_rows);
1292
1293
        // Now, we are able to really send out notifications
1294
        if (sizeof($msg_users))
1295
        {
1296
                include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
1297
                $messenger = new messenger();
1298
1299
                $msg_list_ary = array();
1300
                foreach ($msg_users as $row)
1301
                {
1302
                        $pos = (!isset($msg_list_ary[$row['template']])) ? 0 : sizeof($msg_list_ary[$row['template']]);
1303
1304
                        $msg_list_ary[$row['template']][$pos]['method']        = $row['method'];
1305
                        $msg_list_ary[$row['template']][$pos]['email']        = $row['user_email'];
1306
                        $msg_list_ary[$row['template']][$pos]['jabber']        = $row['user_jabber'];
1307
                        $msg_list_ary[$row['template']][$pos]['name']        = $row['username'];
1308
                        $msg_list_ary[$row['template']][$pos]['lang']        = $row['user_lang'];
1309
                        $msg_list_ary[$row['template']][$pos]['user_id']= $row['user_id'];
1310
                }
1311
                unset($msg_users);
1312
1313
                foreach ($msg_list_ary as $email_template => $email_list)
1314
                {
1315
                        foreach ($email_list as $addr)
1316
                        {
1317
                                $messenger->template($email_template, $addr['lang']);
1318
1319
                                $messenger->to($addr['email'], $addr['name']);
1320
                                $messenger->im($addr['jabber'], $addr['name']);
1321
1322
                                $messenger->assign_vars(array(
1323
                                        'USERNAME'                => htmlspecialchars_decode($addr['name']),
1324
                                        'TOPIC_TITLE'        => htmlspecialchars_decode($topic_title),
1325
                                        'FORUM_NAME'        => htmlspecialchars_decode($forum_name),
1326
1327
                                        'U_FORUM'                                => generate_board_url() . "/viewforum.$phpEx?f=$forum_id",
1328
                                        'U_TOPIC'                                => generate_board_url() . "/viewtopic.$phpEx?f=$forum_id&t=$topic_id",
1329
                                        'U_NEWEST_POST'                        => generate_board_url() . "/viewtopic.$phpEx?f=$forum_id&t=$topic_id&p=$post_id&e=$post_id",
1330
                                        'U_STOP_WATCHING_TOPIC'        => generate_board_url() . "/viewtopic.$phpEx?uid={$addr['user_id']}&f=$forum_id&t=$topic_id&unwatch=topic",
1331
                                        'U_STOP_WATCHING_FORUM'        => generate_board_url() . "/viewforum.$phpEx?uid={$addr['user_id']}&f=$forum_id&unwatch=forum",
1332
                                ));
1333
1334
                                $messenger->send($addr['method']);
1335
                        }
1336
                }
1337
                unset($msg_list_ary);
1338
1339
                $messenger->save_queue();
1340
        }
1341
1342
        // Handle the DB updates
1343
        $db->sql_transaction('begin');
1344
1345
        if (!empty($update_notification['topic']))
1346
        {
1347
                $sql = 'UPDATE ' . TOPICS_WATCH_TABLE . '
1348
                        SET notify_status = ' . NOTIFY_NO . "
1349
                        WHERE topic_id = $topic_id
1350
                                AND " . $db->sql_in_set('user_id', $update_notification['topic']);
1351
                $db->sql_query($sql);
1352
        }
1353
1354
        if (!empty($update_notification['forum']))
1355
        {
1356
                $sql = 'UPDATE ' . FORUMS_WATCH_TABLE . '
1357
                        SET notify_status = ' . NOTIFY_NO . "
1358
                        WHERE forum_id = $forum_id
1359
                                AND " . $db->sql_in_set('user_id', $update_notification['forum']);
1360
                $db->sql_query($sql);
1361
        }
1362
1363
        // Now delete the user_ids not authorised to receive notifications on this topic/forum
1364
        if (!empty($delete_ids['topic']))
1365
        {
1366
                $sql = 'DELETE FROM ' . TOPICS_WATCH_TABLE . "
1367
                        WHERE topic_id = $topic_id
1368
                                AND " . $db->sql_in_set('user_id', $delete_ids['topic']);
1369
                $db->sql_query($sql);
1370
        }
1371
1372
        if (!empty($delete_ids['forum']))
1373
        {
1374
                $sql = 'DELETE FROM ' . FORUMS_WATCH_TABLE . "
1375
                        WHERE forum_id = $forum_id
1376
                                AND " . $db->sql_in_set('user_id', $delete_ids['forum']);
1377
                $db->sql_query($sql);
1378
        }
1379
1380
        $db->sql_transaction('commit');
1381
}
1382
1383
//
1384
// Post handling functions
1385
//
1386
1387
/**
1388
* Delete Post
1389
*/
1390
function delete_post($forum_id, $topic_id, $post_id, &$data)
1391
{
1392
        global $db, $user, $auth;
1393
        global $config, $phpEx, $phpbb_root_path;
1394
1395
        // Specify our post mode
1396
        $post_mode = 'delete';
1397
        if (($data['topic_first_post_id'] === $data['topic_last_post_id']) && $data['topic_replies_real'] == 0)
1398
        {
1399
                $post_mode = 'delete_topic';
1400
        }
1401
        else if ($data['topic_first_post_id'] == $post_id)
1402
        {
1403
                $post_mode = 'delete_first_post';
1404
        }
1405
        else if ($data['topic_last_post_id'] == $post_id)
1406
        {
1407
                $post_mode = 'delete_last_post';
1408
        }
1409
        $sql_data = array();
1410
        $next_post_id = false;
1411
1412
        include_once($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
1413
1414
        $db->sql_transaction('begin');
1415
1416
        // we must make sure to update forums that contain the shadow'd topic
1417
        if ($post_mode == 'delete_topic')
1418
        {
1419
                $shadow_forum_ids = array();
1420
1421
                $sql = 'SELECT forum_id
1422
                        FROM ' . TOPICS_TABLE . '
1423
                        WHERE ' . $db->sql_in_set('topic_moved_id', $topic_id);
1424
                $result = $db->sql_query($sql);
1425
                while ($row = $db->sql_fetchrow($result))
1426
                {
1427
                        if (!isset($shadow_forum_ids[(int) $row['forum_id']]))
1428
                        {
1429
                                $shadow_forum_ids[(int) $row['forum_id']] = 1;
1430
                        }
1431
                        else
1432
                        {
1433
                                $shadow_forum_ids[(int) $row['forum_id']]++;
1434
                        }
1435
                }
1436
                $db->sql_freeresult($result);
1437
        }
1438
1439
        if (!delete_posts('post_id', array($post_id), false, false))
1440
        {
1441
                // Try to delete topic, we may had an previous error causing inconsistency
1442
                if ($post_mode == 'delete_topic')
1443
                {
1444
                        delete_topics('topic_id', array($topic_id), false);
1445
                }
1446
                trigger_error('ALREADY_DELETED');
1447
        }
1448
1449
        $db->sql_transaction('commit');
1450
1451
        // Collect the necessary information for updating the tables
1452
        $sql_data[FORUMS_TABLE] = '';
1453
        switch ($post_mode)
1454
        {
1455
                case 'delete_topic':
1456
1457
                        foreach ($shadow_forum_ids as $updated_forum => $topic_count)
1458
                        {
1459
                                // counting is fun! we only have to do sizeof($forum_ids) number of queries,
1460
                                // even if the topic is moved back to where its shadow lives (we count how many times it is in a forum)
1461
                                $db->sql_query('UPDATE ' . FORUMS_TABLE . ' SET forum_topics_real = forum_topics_real - ' . $topic_count . ', forum_topics = forum_topics - ' . $topic_count . ' WHERE forum_id = ' . $updated_forum);
1462
                                update_post_information('forum', $updated_forum);
1463
                        }
1464
1465
                        delete_topics('topic_id', array($topic_id), false);
1466
1467
                        $sql_data[FORUMS_TABLE] .= 'forum_topics_real = forum_topics_real - 1';
1468
                        $sql_data[FORUMS_TABLE] .= ($data['topic_approved']) ? ', forum_posts = forum_posts - 1, forum_topics = forum_topics - 1' : '';
1469
1470
                        $update_sql = update_post_information('forum', $forum_id, true);
1471
                        if (sizeof($update_sql))
1472
                        {
1473
                                $sql_data[FORUMS_TABLE] .= ($sql_data[FORUMS_TABLE]) ? ', ' : '';
1474
                                $sql_data[FORUMS_TABLE] .= implode(', ', $update_sql[$forum_id]);
1475
                        }
1476
                break;
1477
1478
                case 'delete_first_post':
1479
                        $sql = 'SELECT p.post_id, p.poster_id, p.post_time, p.post_username, u.username, u.user_colour
1480
                                FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . " u
1481
                                WHERE p.topic_id = $topic_id
1482
                                        AND p.poster_id = u.user_id
1483
                                ORDER BY p.post_time ASC";
1484
                        $result = $db->sql_query_limit($sql, 1);
1485
                        $row = $db->sql_fetchrow($result);
1486
                        $db->sql_freeresult($result);
1487
1488
                        $sql_data[FORUMS_TABLE] = ($data['post_approved']) ? 'forum_posts = forum_posts - 1' : '';
1489
1490
                        $sql_data[TOPICS_TABLE] = 'topic_poster = ' . intval($row['poster_id']) . ', topic_first_post_id = ' . intval($row['post_id']) . ", topic_first_poster_colour = '" . $db->sql_escape($row['user_colour']) . "', topic_first_poster_name = '" . (($row['poster_id'] == ANONYMOUS) ? $db->sql_escape($row['post_username']) : $db->sql_escape($row['username'])) . "', topic_time = " . (int) $row['post_time'];
1491
1492
                        // Decrementing topic_replies here is fine because this case only happens if there is more than one post within the topic - basically removing one "reply"
1493
                        $sql_data[TOPICS_TABLE] .= ', topic_replies_real = topic_replies_real - 1' . (($data['post_approved']) ? ', topic_replies = topic_replies - 1' : '');
1494
1495
                        $next_post_id = (int) $row['post_id'];
1496
                break;
1497
1498
                case 'delete_last_post':
1499
                        $sql_data[FORUMS_TABLE] = ($data['post_approved']) ? 'forum_posts = forum_posts - 1' : '';
1500
1501
                        $update_sql = update_post_information('forum', $forum_id, true);
1502
                        if (sizeof($update_sql))
1503
                        {
1504
                                $sql_data[FORUMS_TABLE] .= ($sql_data[FORUMS_TABLE]) ? ', ' : '';
1505
                                $sql_data[FORUMS_TABLE] .= implode(', ', $update_sql[$forum_id]);
1506
                        }
1507
1508
                        $sql_data[TOPICS_TABLE] = 'topic_bumped = 0, topic_bumper = 0, topic_replies_real = topic_replies_real - 1' . (($data['post_approved']) ? ', topic_replies = topic_replies - 1' : '');
1509
1510
                        $update_sql = update_post_information('topic', $topic_id, true);
1511
                        if (sizeof($update_sql))
1512
                        {
1513
                                $sql_data[TOPICS_TABLE] .= ', ' . implode(', ', $update_sql[$topic_id]);
1514
                                $next_post_id = (int) str_replace('topic_last_post_id = ', '', $update_sql[$topic_id][0]);
1515
                        }
1516
                        else
1517
                        {
1518
                                $sql = 'SELECT MAX(post_id) as last_post_id
1519
                                        FROM ' . POSTS_TABLE . "
1520
                                        WHERE topic_id = $topic_id " .
1521
                                                ((!$auth->acl_get('m_approve', $forum_id)) ? 'AND post_approved = 1' : '');
1522
                                $result = $db->sql_query($sql);
1523
                                $row = $db->sql_fetchrow($result);
1524
                                $db->sql_freeresult($result);
1525
1526
                                $next_post_id = (int) $row['last_post_id'];
1527
                        }
1528
                break;
1529
1530
                case 'delete':
1531
                        $sql = 'SELECT post_id
1532
                                FROM ' . POSTS_TABLE . "
1533
                                WHERE topic_id = $topic_id " .
1534
                                        ((!$auth->acl_get('m_approve', $forum_id)) ? 'AND post_approved = 1' : '') . '
1535
                                        AND post_time > ' . $data['post_time'] . '
1536
                                ORDER BY post_time ASC';
1537
                        $result = $db->sql_query_limit($sql, 1);
1538
                        $row = $db->sql_fetchrow($result);
1539
                        $db->sql_freeresult($result);
1540
1541
                        $sql_data[FORUMS_TABLE] = ($data['post_approved']) ? 'forum_posts = forum_posts - 1' : '';
1542
1543
                        $sql_data[TOPICS_TABLE] = 'topic_replies_real = topic_replies_real - 1' . (($data['post_approved']) ? ', topic_replies = topic_replies - 1' : '');
1544
                        $next_post_id = (int) $row['post_id'];
1545
                break;
1546
        }
1547
1548
        if (($post_mode == 'delete') || ($post_mode == 'delete_last_post') || ($post_mode == 'delete_first_post'))
1549
        {
1550
                $sql = 'SELECT 1 AS has_attachments
1551
                        FROM ' . ATTACHMENTS_TABLE . '
1552
                        WHERE topic_id = ' . $topic_id;
1553
                $result = $db->sql_query_limit($sql, 1);
1554
                $has_attachments = (int) $db->sql_fetchfield('has_attachments');
1555
                $db->sql_freeresult($result);
1556
1557
                if (!$has_attachments)
1558
                {
1559
                        $sql_data[TOPICS_TABLE] .= ', topic_attachment = 0';
1560
                }
1561
        }
1562
1563
//        $sql_data[USERS_TABLE] = ($data['post_postcount']) ? 'user_posts = user_posts - 1' : '';
1564
1565
        $db->sql_transaction('begin');
1566
1567
        $where_sql = array(
1568
                FORUMS_TABLE        => "forum_id = $forum_id",
1569
                TOPICS_TABLE        => "topic_id = $topic_id",
1570
                USERS_TABLE                => 'user_id = ' . $data['poster_id']
1571
        );
1572
1573
        foreach ($sql_data as $table => $update_sql)
1574
        {
1575
                if ($update_sql)
1576
                {
1577
                        $db->sql_query("UPDATE $table SET $update_sql WHERE " . $where_sql[$table]);
1578
                }
1579
        }
1580
1581
        // Adjust posted info for this user by looking for a post by him/her within this topic...
1582
        if ($post_mode != 'delete_topic' && $config['load_db_track'] && $data['poster_id'] != ANONYMOUS)
1583
        {
1584
                $sql = 'SELECT poster_id
1585
                        FROM ' . POSTS_TABLE . '
1586
                        WHERE topic_id = ' . $topic_id . '
1587
                                AND poster_id = ' . $data['poster_id'];
1588
                $result = $db->sql_query_limit($sql, 1);
1589
                $poster_id = (int) $db->sql_fetchfield('poster_id');
1590
                $db->sql_freeresult($result);
1591
1592
                // The user is not having any more posts within this topic
1593
                if (!$poster_id)
1594
                {
1595
                        $sql = 'DELETE FROM ' . TOPICS_POSTED_TABLE . '
1596
                                WHERE topic_id = ' . $topic_id . '
1597
                                        AND user_id = ' . $data['poster_id'];
1598
                        $db->sql_query($sql);
1599
                }
1600
        }
1601
1602
        $db->sql_transaction('commit');
1603
1604
        if ($data['post_reported'] && ($post_mode != 'delete_topic'))
1605
        {
1606
                sync('topic_reported', 'topic_id', array($topic_id));
1607
        }
1608
1609
        return $next_post_id;
1610
}
1611
1612
/**
1613
* Submit Post
1614
* @todo Split up and create lightweight, simple API for this.
1615
*/
1616
function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $update_message = true, $update_search_index = true)
1617
{
1618
        global $db, $auth, $user, $config, $phpEx, $template, $phpbb_root_path;
1619
1620
        // We do not handle erasing posts here
1621
        if ($mode == 'delete')
1622
        {
1623
                return false;
1624
        }
1625
1626
        $current_time = time();
1627
1628
        if ($mode == 'post')
1629
        {
1630
                $post_mode = 'post';
1631
                $update_message = true;
1632
        }
1633
        else if ($mode != 'edit')
1634
        {
1635
                $post_mode = 'reply';
1636
                $update_message = true;
1637
        }
1638
        else if ($mode == 'edit')
1639
        {
1640
                $post_mode = ($data['topic_replies_real'] == 0) ? 'edit_topic' : (($data['topic_first_post_id'] == $data['post_id']) ? 'edit_first_post' : (($data['topic_last_post_id'] == $data['post_id']) ? 'edit_last_post' : 'edit'));
1641
        }
1642
1643
        // First of all make sure the subject and topic title are having the correct length.
1644
        // To achieve this without cutting off between special chars we convert to an array and then count the elements.
1645
        $subject = truncate_string($subject);
1646
        $data['topic_title'] = truncate_string($data['topic_title']);
1647
1648
        // Collect some basic information about which tables and which rows to update/insert
1649
        $sql_data = $topic_row = array();
1650
        $poster_id = ($mode == 'edit') ? $data['poster_id'] : (int) $user->data['user_id'];
1651
1652
        // Retrieve some additional information if not present
1653
        if ($mode == 'edit' && (!isset($data['post_approved']) || !isset($data['topic_approved']) || $data['post_approved'] === false || $data['topic_approved'] === false))
1654
        {
1655
                $sql = 'SELECT p.post_approved, t.topic_type, t.topic_replies, t.topic_replies_real, t.topic_approved
1656
                        FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . ' p
1657
                        WHERE t.topic_id = p.topic_id
1658
                                AND p.post_id = ' . $data['post_id'];
1659
                $result = $db->sql_query($sql);
1660
                $topic_row = $db->sql_fetchrow($result);
1661
                $db->sql_freeresult($result);
1662
1663
                $data['topic_approved'] = $topic_row['topic_approved'];
1664
                $data['post_approved'] = $topic_row['post_approved'];
1665
        }
1666
1667
        // This variable indicates if the user is able to post or put into the queue - it is used later for all code decisions regarding approval
1668
        // The variable name should be $post_approved, because it indicates if the post is approved or not
1669
        $post_approval = 1;
1670
1671
        // Check the permissions for post approval. Moderators are not affected.
1672
        if (!$auth->acl_get('f_noapprove', $data['forum_id']) && !$auth->acl_get('m_approve', $data['forum_id']))
1673
        {
1674
                // Post not approved, but in queue
1675
                $post_approval = 0;
1676
        }
1677
1678
        // Mods are able to force approved/unapproved posts. True means the post is approved, false the post is unapproved
1679
        if (isset($data['force_approved_state']))
1680
        {
1681
                $post_approval = ($data['force_approved_state']) ? 1 : 0;
1682
        }
1683
1684
        // Start the transaction here
1685
        $db->sql_transaction('begin');
1686
1687
        // Collect Information
1688
        switch ($post_mode)
1689
        {
1690
                case 'post':
1691
                case 'reply':
1692
                        $sql_data[POSTS_TABLE]['sql'] = array(
1693
                                'forum_id'                        => $data['forum_id'],
1694
                                'poster_id'                        => (int) $user->data['user_id'],
1695
                                'icon_id'                        => $data['icon_id'],
1696
                                'poster_ip'                        => $user->ip,
1697
                                'post_time'                        => $current_time,
1698
                                'post_approved'                => $post_approval,
1699
                                'enable_bbcode'                => $data['enable_bbcode'],
1700
                                'enable_smilies'        => $data['enable_smilies'],
1701
                                'enable_magic_url'        => $data['enable_urls'],
1702
                                'enable_sig'                => $data['enable_sig'],
1703
                                'post_username'                => (!$user->data['is_registered']) ? $username : '',
1704
                                'post_subject'                => $subject,
1705
                                'post_text'                        => $data['message'],
1706
                                'post_checksum'                => $data['message_md5'],
1707
                                'post_attachment'        => (!empty($data['attachment_data'])) ? 1 : 0,
1708
                                'bbcode_bitfield'        => $data['bbcode_bitfield'],
1709
                                'bbcode_uid'                => $data['bbcode_uid'],
1710
                                'post_postcount'        => ($auth->acl_get('f_postcount', $data['forum_id'])) ? 1 : 0,
1711
                                'post_edit_locked'        => $data['post_edit_locked']
1712
                        );
1713
                break;
1714
1715
                case 'edit_first_post':
1716
                case 'edit':
1717
1718
                case 'edit_last_post':
1719
                case 'edit_topic':
1720
1721
                        // If edit reason is given always display edit info
1722
1723
                        // If editing last post then display no edit info
1724
                        // If m_edit permission then display no edit info
1725
                        // If normal edit display edit info
1726
1727
                        // Display edit info if edit reason given or user is editing his post, which is not the last within the topic.
1728
                        if ($data['post_edit_reason'] || (!$auth->acl_get('m_edit', $data['forum_id']) && ($post_mode == 'edit' || $post_mode == 'edit_first_post')))
1729
                        {
1730
                                $data['post_edit_reason']                = truncate_string($data['post_edit_reason'], 255, 255, false);
1731
1732
                                $sql_data[POSTS_TABLE]['sql']        = array(
1733
                                        'post_edit_time'        => $current_time,
1734
                                        'post_edit_reason'        => $data['post_edit_reason'],
1735
                                        'post_edit_user'        => (int) $data['post_edit_user'],
1736
                                );
1737
1738
                                $sql_data[POSTS_TABLE]['stat'][] = 'post_edit_count = post_edit_count + 1';
1739
                        }
1740
                        else if (!$data['post_edit_reason'] && $mode == 'edit' && $auth->acl_get('m_edit', $data['forum_id']))
1741
                        {
1742
                                $sql_data[POSTS_TABLE]['sql'] = array(
1743
                                        'post_edit_reason'        => '',
1744
                                );
1745
                        }
1746
1747
                        // If the person editing this post is different to the one having posted then we will add a log entry stating the edit
1748
                        // Could be simplified by only adding to the log if the edit is not tracked - but this may confuse admins/mods
1749
                        if ($user->data['user_id'] != $poster_id)
1750
                        {
1751
                                $log_subject = ($subject) ? $subject : $data['topic_title'];
1752
                                add_log('mod', $data['forum_id'], $data['topic_id'], 'LOG_POST_EDITED', $log_subject, (!empty($username)) ? $username : $user->lang['GUEST']);
1753
                        }
1754
1755
                        if (!isset($sql_data[POSTS_TABLE]['sql']))
1756
                        {
1757
                                $sql_data[POSTS_TABLE]['sql'] = array();
1758
                        }
1759
1760
                        $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array(
1761
                                'forum_id'                        => $data['forum_id'],
1762
                                'poster_id'                        => $data['poster_id'],
1763
                                'icon_id'                        => $data['icon_id'],
1764
                                'post_approved'                => (!$post_approval) ? 0 : $data['post_approved'],
1765
                                'enable_bbcode'                => $data['enable_bbcode'],
1766
                                'enable_smilies'        => $data['enable_smilies'],
1767
                                'enable_magic_url'        => $data['enable_urls'],
1768
                                'enable_sig'                => $data['enable_sig'],
1769
                                'post_username'                => ($username && $data['poster_id'] == ANONYMOUS) ? $username : '',
1770
                                'post_subject'                => $subject,
1771
                                'post_checksum'                => $data['message_md5'],
1772
                                'post_attachment'        => (!empty($data['attachment_data'])) ? 1 : 0,
1773
                                'bbcode_bitfield'        => $data['bbcode_bitfield'],
1774
                                'bbcode_uid'                => $data['bbcode_uid'],
1775
                                'post_edit_locked'        => $data['post_edit_locked'])
1776
                        );
1777
1778
                        if ($update_message)
1779
                        {
1780
                                $sql_data[POSTS_TABLE]['sql']['post_text'] = $data['message'];
1781
                        }
1782
1783
                break;
1784
        }
1785
1786
        $post_approved = $sql_data[POSTS_TABLE]['sql']['post_approved'];
1787
        $topic_row = array();
1788
1789
        // And the topic ladies and gentlemen
1790
        switch ($post_mode)
1791
        {
1792
                case 'post':
1793
                        $sql_data[TOPICS_TABLE]['sql'] = array(
1794
                                'topic_poster'                                => (int) $user->data['user_id'],
1795
                                'topic_time'                                => $current_time,
1796
                                'topic_last_view_time'                => $current_time,
1797
                                'forum_id'                                        => $data['forum_id'],
1798
                                'icon_id'                                        => $data['icon_id'],
1799
                                'topic_approved'                        => $post_approval,
1800
                                'topic_title'                                => $subject,
1801
                                'topic_first_poster_name'        => (!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : ''),
1802
                                'topic_first_poster_colour'        => $user->data['user_colour'],
1803
                                'topic_type'                                => $topic_type,
1804
                                'topic_time_limit'                        => ($topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE) ? ($data['topic_time_limit'] * 86400) : 0,
1805
                                'topic_attachment'                        => (!empty($data['attachment_data'])) ? 1 : 0,
1806
                        );
1807
1808
                        if (isset($poll['poll_options']) && !empty($poll['poll_options']))
1809
                        {
1810
                                $poll_start = ($poll['poll_start']) ? $poll['poll_start'] : $current_time;
1811
                                $poll_length = $poll['poll_length'] * 86400;
1812
                                if ($poll_length < 0)
1813
                                {
1814
                                        $poll_start = $poll_start + $poll_length;
1815
                                        if ($poll_start < 0)
1816
                                        {
1817
                                                $poll_start = 0;
1818
                                        }
1819
                                        $poll_length = 1;
1820
                                }
1821
1822
                                $sql_data[TOPICS_TABLE]['sql'] = array_merge($sql_data[TOPICS_TABLE]['sql'], array(
1823
                                        'poll_title'                => $poll['poll_title'],
1824
                                        'poll_start'                => $poll_start,
1825
                                        'poll_max_options'        => $poll['poll_max_options'],
1826
                                        'poll_length'                => $poll_length,
1827
                                        'poll_vote_change'        => $poll['poll_vote_change'])
1828
                                );
1829
                        }
1830
1831
                        $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data['forum_id']) && $post_approval) ? ', user_posts = user_posts + 1' : '');
1832
1833
                        if ($post_approval)
1834
                        {
1835
                                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts + 1';
1836
                        }
1837
                        $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_real = forum_topics_real + 1' . (($post_approval) ? ', forum_topics = forum_topics + 1' : '');
1838
                break;
1839
1840
                case 'reply':
1841
                        $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_view_time = ' . $current_time . ',
1842
                                topic_replies_real = topic_replies_real + 1,
1843
                                topic_bumped = 0,
1844
                                topic_bumper = 0' .
1845
                                (($post_approval) ? ', topic_replies = topic_replies + 1' : '') .
1846
                                ((!empty($data['attachment_data']) || (isset($data['topic_attachment']) && $data['topic_attachment'])) ? ', topic_attachment = 1' : '');
1847
1848
                        $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data['forum_id']) && $post_approval) ? ', user_posts = user_posts + 1' : '');
1849
1850
                        if ($post_approval)
1851
                        {
1852
                                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts + 1';
1853
                        }
1854
                break;
1855
1856
                case 'edit_topic':
1857
                case 'edit_first_post':
1858
                        if (isset($poll['poll_options']))
1859
                        {
1860
                                $poll_start = ($poll['poll_start'] || empty($poll['poll_options'])) ? $poll['poll_start'] : $current_time;
1861
                                $poll_length = $poll['poll_length'] * 86400;
1862
                                if ($poll_length < 0)
1863
                                {
1864
                                        $poll_start = $poll_start + $poll_length;
1865
                                        if ($poll_start < 0)
1866
                                        {
1867
                                                $poll_start = 0;
1868
                                        }
1869
                                        $poll_length = 1;
1870
                                }
1871
                        }
1872
1873
                        $sql_data[TOPICS_TABLE]['sql'] = array(
1874
                                'forum_id'                                        => $data['forum_id'],
1875
                                'icon_id'                                        => $data['icon_id'],
1876
                                'topic_approved'                        => (!$post_approval) ? 0 : $data['topic_approved'],
1877
                                'topic_title'                                => $subject,
1878
                                'topic_first_poster_name'        => $username,
1879
                                'topic_type'                                => $topic_type,
1880
                                'topic_time_limit'                        => ($topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE) ? ($data['topic_time_limit'] * 86400) : 0,
1881
                                'poll_title'                                => (isset($poll['poll_options'])) ? $poll['poll_title'] : '',
1882
                                'poll_start'                                => (isset($poll['poll_options'])) ? $poll_start : 0,
1883
                                'poll_max_options'                        => (isset($poll['poll_options'])) ? $poll['poll_max_options'] : 1,
1884
                                'poll_length'                                => (isset($poll['poll_options'])) ? $poll_length : 0,
1885
                                'poll_vote_change'                        => (isset($poll['poll_vote_change'])) ? $poll['poll_vote_change'] : 0,
1886
                                'topic_last_view_time'                => $current_time,
1887
1888
                                'topic_attachment'                        => (!empty($data['attachment_data'])) ? 1 : (isset($data['topic_attachment']) ? $data['topic_attachment'] : 0),
1889
                        );
1890
1891
                        // Correctly set back the topic replies and forum posts... only if the topic was approved before and now gets disapproved
1892
                        if (!$post_approval && $data['topic_approved'])
1893
                        {
1894
                                // Do we need to grab some topic informations?
1895
                                if (!sizeof($topic_row))
1896
                                {
1897
                                        $sql = 'SELECT topic_type, topic_replies, topic_replies_real, topic_approved
1898
                                                FROM ' . TOPICS_TABLE . '
1899
                                                WHERE topic_id = ' . $data['topic_id'];
1900
                                        $result = $db->sql_query($sql);
1901
                                        $topic_row = $db->sql_fetchrow($result);
1902
                                        $db->sql_freeresult($result);
1903
                                }
1904
1905
                                // If this is the only post remaining we do not need to decrement topic_replies.
1906
                                // Also do not decrement if first post - then the topic_replies will not be adjusted if approving the topic again.
1907
1908
                                // If this is an edited topic or the first post the topic gets completely disapproved later on...
1909
                                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics = forum_topics - 1';
1910
                                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts - ' . ($topic_row['topic_replies'] + 1);
1911
1912
                                set_config_count('num_topics', -1, true);
1913
                                set_config_count('num_posts', ($topic_row['topic_replies'] + 1) * (-1), true);
1914
1915
                                // Only decrement this post, since this is the one non-approved now
1916
                                if ($auth->acl_get('f_postcount', $data['forum_id']))
1917
                                {
1918
                                        $sql_data[USERS_TABLE]['stat'][] = 'user_posts = user_posts - 1';
1919
                                }
1920
                        }
1921
1922
                break;
1923
1924
                case 'edit':
1925
                case 'edit_last_post':
1926
1927
                        // Correctly set back the topic replies and forum posts... but only if the post was approved before.
1928
                        if (!$post_approval && $data['post_approved'])
1929
                        {
1930
                                $sql_data[TOPICS_TABLE]['stat'][] = 'topic_replies = topic_replies - 1, topic_last_view_time = ' . $current_time;
1931
                                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts - 1';
1932
1933
                                set_config_count('num_posts', -1, true);
1934
1935
                                if ($auth->acl_get('f_postcount', $data['forum_id']))
1936
                                {
1937
                                        $sql_data[USERS_TABLE]['stat'][] = 'user_posts = user_posts - 1';
1938
                                }
1939
                        }
1940
1941
                break;
1942
        }
1943
1944
        // Submit new topic
1945
        if ($post_mode == 'post')
1946
        {
1947
                $sql = 'INSERT INTO ' . TOPICS_TABLE . ' ' .
1948
                        $db->sql_build_array('INSERT', $sql_data[TOPICS_TABLE]['sql']);
1949
                $db->sql_query($sql);
1950
1951
                $data['topic_id'] = $db->sql_nextid();
1952
1953
                $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array(
1954
                        'topic_id' => $data['topic_id'])
1955
                );
1956
                unset($sql_data[TOPICS_TABLE]['sql']);
1957
        }
1958
1959
        // Submit new post
1960
        if ($post_mode == 'post' || $post_mode == 'reply')
1961
        {
1962
                if ($post_mode == 'reply')
1963
                {
1964
                        $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array(
1965
                                'topic_id' => $data['topic_id'])
1966
                        );
1967
                }
1968
1969
                $sql = 'INSERT INTO ' . POSTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data[POSTS_TABLE]['sql']);
1970
                $db->sql_query($sql);
1971
                $data['post_id'] = $db->sql_nextid();
1972
1973
                if ($post_mode == 'post')
1974
                {
1975
                        $sql_data[TOPICS_TABLE]['sql'] = array(
1976
                                'topic_first_post_id'                => $data['post_id'],
1977
                                'topic_last_post_id'                => $data['post_id'],
1978
                                'topic_last_post_time'                => $current_time,
1979
                                'topic_last_poster_id'                => (int) $user->data['user_id'],
1980
                                'topic_last_poster_name'        => (!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : ''),
1981
                                'topic_last_poster_colour'        => $user->data['user_colour'],
1982
                                'topic_last_post_subject'        => (string) $subject,
1983
                        );
1984
                }
1985
1986
                unset($sql_data[POSTS_TABLE]['sql']);
1987
        }
1988
1989
        // Update the topics table
1990
        if (isset($sql_data[TOPICS_TABLE]['sql']))
1991
        {
1992
                $sql = 'UPDATE ' . TOPICS_TABLE . '
1993
                        SET ' . $db->sql_build_array('UPDATE', $sql_data[TOPICS_TABLE]['sql']) . '
1994
                        WHERE topic_id = ' . $data['topic_id'];
1995
                $db->sql_query($sql);
1996
        }
1997
1998
        // Update the posts table
1999
        if (isset($sql_data[POSTS_TABLE]['sql']))
2000
        {
2001
                $sql = 'UPDATE ' . POSTS_TABLE . '
2002
                        SET ' . $db->sql_build_array('UPDATE', $sql_data[POSTS_TABLE]['sql']) . '
2003
                        WHERE post_id = ' . $data['post_id'];
2004
                $db->sql_query($sql);
2005
        }
2006
2007
        // Update Poll Tables
2008
        if (isset($poll['poll_options']))
2009
        {
2010
                $cur_poll_options = array();
2011
2012
                if ($mode == 'edit')
2013
                {
2014
                        $sql = 'SELECT *
2015
                                FROM ' . POLL_OPTIONS_TABLE . '
2016
                                WHERE topic_id = ' . $data['topic_id'] . '
2017
                                ORDER BY poll_option_id';
2018
                        $result = $db->sql_query($sql);
2019
2020
                        $cur_poll_options = array();
2021
                        while ($row = $db->sql_fetchrow($result))
2022
                        {
2023
                                $cur_poll_options[] = $row;
2024
                        }
2025
                        $db->sql_freeresult($result);
2026
                }
2027
2028
                $sql_insert_ary = array();
2029
2030
                for ($i = 0, $size = sizeof($poll['poll_options']); $i < $size; $i++)
2031
                {
2032
                        if (strlen(trim($poll['poll_options'][$i])))
2033
                        {
2034
                                if (empty($cur_poll_options[$i]))
2035
                                {
2036
                                        // If we add options we need to put them to the end to be able to preserve votes...
2037
                                        $sql_insert_ary[] = array(
2038
                                                'poll_option_id'        => (int) sizeof($cur_poll_options) + 1 + sizeof($sql_insert_ary),
2039
                                                'topic_id'                        => (int) $data['topic_id'],
2040
                                                'poll_option_text'        => (string) $poll['poll_options'][$i]
2041
                                        );
2042
                                }
2043
                                else if ($poll['poll_options'][$i] != $cur_poll_options[$i])
2044
                                {
2045
                                        $sql = 'UPDATE ' . POLL_OPTIONS_TABLE . "
2046
                                                SET poll_option_text = '" . $db->sql_escape($poll['poll_options'][$i]) . "'
2047
                                                WHERE poll_option_id = " . $cur_poll_options[$i]['poll_option_id'] . '
2048
                                                        AND topic_id = ' . $data['topic_id'];
2049
                                        $db->sql_query($sql);
2050
                                }
2051
                        }
2052
                }
2053
2054
                $db->sql_multi_insert(POLL_OPTIONS_TABLE, $sql_insert_ary);
2055
2056
                if (sizeof($poll['poll_options']) < sizeof($cur_poll_options))
2057
                {
2058
                        $sql = 'DELETE FROM ' . POLL_OPTIONS_TABLE . '
2059
                                WHERE poll_option_id > ' . sizeof($poll['poll_options']) . '
2060
                                        AND topic_id = ' . $data['topic_id'];
2061
                        $db->sql_query($sql);
2062
                }
2063
2064
                // If edited, we would need to reset votes (since options can be re-ordered above, you can't be sure if the change is for changing the text or adding an option
2065
                if ($mode == 'edit' && sizeof($poll['poll_options']) != sizeof($cur_poll_options))
2066
                {
2067
                        $db->sql_query('DELETE FROM ' . POLL_VOTES_TABLE . ' WHERE topic_id = ' . $data['topic_id']);
2068
                        $db->sql_query('UPDATE ' . POLL_OPTIONS_TABLE . ' SET poll_option_total = 0 WHERE topic_id = ' . $data['topic_id']);
2069
                }
2070
        }
2071
2072
        // Submit Attachments
2073
        if (!empty($data['attachment_data']) && $data['post_id'] && in_array($mode, array('post', 'reply', 'quote', 'edit')))
2074
        {
2075
                $space_taken = $files_added = 0;
2076
                $orphan_rows = array();
2077
2078
                foreach ($data['attachment_data'] as $pos => $attach_row)
2079
                {
2080
                        $orphan_rows[(int) $attach_row['attach_id']] = array();
2081
                }
2082
2083
                if (sizeof($orphan_rows))
2084
                {
2085
                        $sql = 'SELECT attach_id, filesize, physical_filename
2086
                                FROM ' . ATTACHMENTS_TABLE . '
2087
                                WHERE ' . $db->sql_in_set('attach_id', array_keys($orphan_rows)) . '
2088
                                        AND is_orphan = 1
2089
                                        AND poster_id = ' . $user->data['user_id'];
2090
                        $result = $db->sql_query($sql);
2091
2092
                        $orphan_rows = array();
2093
                        while ($row = $db->sql_fetchrow($result))
2094
                        {
2095
                                $orphan_rows[$row['attach_id']] = $row;
2096
                        }
2097
                        $db->sql_freeresult($result);
2098
                }
2099
2100
                foreach ($data['attachment_data'] as $pos => $attach_row)
2101
                {
2102
                        if ($attach_row['is_orphan'] && !isset($orphan_rows[$attach_row['attach_id']]))
2103
                        {
2104
                                continue;
2105
                        }
2106
2107
                        if (!$attach_row['is_orphan'])
2108
                        {
2109
                                // update entry in db if attachment already stored in db and filespace
2110
                                $sql = 'UPDATE ' . ATTACHMENTS_TABLE . "
2111
                                        SET attach_comment = '" . $db->sql_escape($attach_row['attach_comment']) . "'
2112
                                        WHERE attach_id = " . (int) $attach_row['attach_id'] . '
2113
                                                AND is_orphan = 0';
2114
                                $db->sql_query($sql);
2115
                        }
2116
                        else
2117
                        {
2118
                                // insert attachment into db
2119
                                if (!@file_exists($phpbb_root_path . $config['upload_path'] . '/' . utf8_basename($orphan_rows[$attach_row['attach_id']]['physical_filename'])))
2120
                                {
2121
                                        continue;
2122
                                }
2123
2124
                                $space_taken += $orphan_rows[$attach_row['attach_id']]['filesize'];
2125
                                $files_added++;
2126
2127
                                $attach_sql = array(
2128
                                        'post_msg_id'                => $data['post_id'],
2129
                                        'topic_id'                        => $data['topic_id'],
2130
                                        'is_orphan'                        => 0,
2131
                                        'poster_id'                        => $poster_id,
2132
                                        'attach_comment'        => $attach_row['attach_comment'],
2133
                                );
2134
2135
                                $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $attach_sql) . '
2136
                                        WHERE attach_id = ' . $attach_row['attach_id'] . '
2137
                                                AND is_orphan = 1
2138
                                                AND poster_id = ' . $user->data['user_id'];
2139
                                $db->sql_query($sql);
2140
                        }
2141
                }
2142
2143
                if ($space_taken && $files_added)
2144
                {
2145
                        set_config_count('upload_dir_size', $space_taken, true);
2146
                        set_config_count('num_files', $files_added, true);
2147
                }
2148
        }
2149
2150
        // we need to update the last forum information
2151
        // only applicable if the topic is approved
2152
        if ($post_approved || !$data['post_approved'])
2153
        {
2154
                // the last post makes us update the forum table. This can happen if...
2155
                // We make a new topic
2156
                // We reply to a topic
2157
                // We edit the last post in a topic and this post is the latest in the forum (maybe)
2158
                // We edit the only post in the topic
2159
                // We edit the first post in the topic and all the other posts are not approved
2160
                if (($post_mode == 'post' || $post_mode == 'reply') && $post_approved)
2161
                {
2162
                        $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . $data['post_id'];
2163
                        $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($subject) . "'";
2164
                        $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = ' . $current_time;
2165
                        $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = ' . (int) $user->data['user_id'];
2166
                        $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape((!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : '')) . "'";
2167
                        $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = '" . $db->sql_escape($user->data['user_colour']) . "'";
2168
                }
2169
                else if ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || ($post_mode == 'edit_first_post' && !$data['topic_replies']))
2170
                {
2171
                        // this does not _necessarily_ mean that we must update the info again,
2172
                        // it just means that we might have to
2173
                        $sql = 'SELECT forum_last_post_id, forum_last_post_subject
2174
                                FROM ' . FORUMS_TABLE . '
2175
                                WHERE forum_id = ' . (int) $data['forum_id'];
2176
                        $result = $db->sql_query($sql);
2177
                        $row = $db->sql_fetchrow($result);
2178
                        $db->sql_freeresult($result);
2179
2180
                        // this post is the latest post in the forum, better update
2181
                        if ($row['forum_last_post_id'] == $data['post_id'])
2182
                        {
2183
                                // If post approved and subject changed, or poster is anonymous, we need to update the forum_last* rows
2184
                                if ($post_approved && ($row['forum_last_post_subject'] !== $subject || $data['poster_id'] == ANONYMOUS))
2185
                                {
2186
                                        // the post's subject changed
2187
                                        if ($row['forum_last_post_subject'] !== $subject)
2188
                                        {
2189
                                                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_subject = \'' . $db->sql_escape($subject) . '\'';
2190
                                        }
2191
2192
                                        // Update the user name if poster is anonymous... just in case an admin changed it
2193
                                        if ($data['poster_id'] == ANONYMOUS)
2194
                                        {
2195
                                                $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape($username) . "'";
2196
                                        }
2197
                                }
2198
                                else if ($data['post_approved'] !== $post_approved)
2199
                                {
2200
                                        // we need a fresh change of socks, everything has become invalidated
2201
                                        $sql = 'SELECT MAX(topic_last_post_id) as last_post_id
2202
                                                FROM ' . TOPICS_TABLE . '
2203
                                                WHERE forum_id = ' . (int) $data['forum_id'] . '
2204
                                                        AND topic_approved = 1';
2205
                                        $result = $db->sql_query($sql);
2206
                                        $row = $db->sql_fetchrow($result);
2207
                                        $db->sql_freeresult($result);
2208
2209
                                        // any posts left in this forum?
2210
                                        if (!empty($row['last_post_id']))
2211
                                        {
2212
                                                $sql = 'SELECT p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.user_id, u.username, u.user_colour
2213
                                                        FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u
2214
                                                        WHERE p.poster_id = u.user_id
2215
                                                                AND p.post_id = ' . (int) $row['last_post_id'];
2216
                                                $result = $db->sql_query($sql);
2217
                                                $row = $db->sql_fetchrow($result);
2218
                                                $db->sql_freeresult($result);
2219
2220
                                                // salvation, a post is found! jam it into the forums table
2221
                                                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . (int) $row['post_id'];
2222
                                                $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($row['post_subject']) . "'";
2223
                                                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = ' . (int) $row['post_time'];
2224
                                                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = ' . (int) $row['poster_id'];
2225
                                                $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape(($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username']) . "'";
2226
                                                $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = '" . $db->sql_escape($row['user_colour']) . "'";
2227
                                        }
2228
                                        else
2229
                                        {
2230
                                                // just our luck, the last topic in the forum has just been turned unapproved...
2231
                                                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = 0';
2232
                                                $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = ''";
2233
                                                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = 0';
2234
                                                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = 0';
2235
                                                $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = ''";
2236
                                                $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = ''";
2237
                                        }
2238
                                }
2239
                        }
2240
                }
2241
        }
2242
2243
        // topic sync time!
2244
        // simply, we update if it is a reply or the last post is edited
2245
        if ($post_approved)
2246
        {
2247
                // reply requires the whole thing
2248
                if ($post_mode == 'reply')
2249
                {
2250
                        $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_post_id = ' . (int) $data['post_id'];
2251
                        $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_poster_id = ' . (int) $user->data['user_id'];
2252
                        $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_name = '" . $db->sql_escape((!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : '')) . "'";
2253
                        $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_colour = '" . (($user->data['user_id'] != ANONYMOUS) ? $db->sql_escape($user->data['user_colour']) : '') . "'";
2254
                        $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_post_subject = '" . $db->sql_escape($subject) . "'";
2255
                        $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_post_time = ' . (int) $current_time;
2256
                }
2257
                else if ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || ($post_mode == 'edit_first_post' && !$data['topic_replies']))
2258
                {
2259
                        // only the subject can be changed from edit
2260
                        $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_post_subject = '" . $db->sql_escape($subject) . "'";
2261
2262
                        // Maybe not only the subject, but also changing anonymous usernames. ;)
2263
                        if ($data['poster_id'] == ANONYMOUS)
2264
                        {
2265
                                $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_name = '" . $db->sql_escape($username) . "'";
2266
                        }
2267
                }
2268
        }
2269
        else if (!$data['post_approved'] && ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || ($post_mode == 'edit_first_post' && !$data['topic_replies'])))
2270
        {
2271
                // like having the rug pulled from under us
2272
                $sql = 'SELECT MAX(post_id) as last_post_id
2273
                        FROM ' . POSTS_TABLE . '
2274
                        WHERE topic_id = ' . (int) $data['topic_id'] . '
2275
                                AND post_approved = 1';
2276
                $result = $db->sql_query($sql);
2277
                $row = $db->sql_fetchrow($result);
2278
                $db->sql_freeresult($result);
2279
2280
                // any posts left in this forum?
2281
                if (!empty($row['last_post_id']))
2282
                {
2283
                        $sql = 'SELECT p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.user_id, u.username, u.user_colour
2284
                                FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u
2285
                                WHERE p.poster_id = u.user_id
2286
                                        AND p.post_id = ' . (int) $row['last_post_id'];
2287
                        $result = $db->sql_query($sql);
2288
                        $row = $db->sql_fetchrow($result);
2289
                        $db->sql_freeresult($result);
2290
2291
                        // salvation, a post is found! jam it into the topics table
2292
                        $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_post_id = ' . (int) $row['post_id'];
2293
                        $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_post_subject = '" . $db->sql_escape($row['post_subject']) . "'";
2294
                        $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_post_time = ' . (int) $row['post_time'];
2295
                        $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_poster_id = ' . (int) $row['poster_id'];
2296
                        $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_name = '" . $db->sql_escape(($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username']) . "'";
2297
                        $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_colour = '" . $db->sql_escape($row['user_colour']) . "'";
2298
                }
2299
        }
2300
2301
        // Update total post count, do not consider moderated posts/topics
2302
        if ($post_approval)
2303
        {
2304
                if ($post_mode == 'post')
2305
                {
2306
                        set_config_count('num_topics', 1, true);
2307
                        set_config_count('num_posts', 1, true);
2308
                }
2309
2310
                if ($post_mode == 'reply')
2311
                {
2312
                        set_config_count('num_posts', 1, true);
2313
                }
2314
        }
2315
2316
        // Update forum stats
2317
        $where_sql = array(POSTS_TABLE => 'post_id = ' . $data['post_id'], TOPICS_TABLE => 'topic_id = ' . $data['topic_id'], FORUMS_TABLE => 'forum_id = ' . $data['forum_id'], USERS_TABLE => 'user_id = ' . $poster_id);
2318
2319
        foreach ($sql_data as $table => $update_ary)
2320
        {
2321
                if (isset($update_ary['stat']) && implode('', $update_ary['stat']))
2322
                {
2323
                        $sql = "UPDATE $table SET " . implode(', ', $update_ary['stat']) . ' WHERE ' . $where_sql[$table];
2324
                        $db->sql_query($sql);
2325
                }
2326
        }
2327
2328
        // Delete topic shadows (if any exist). We do not need a shadow topic for an global announcement
2329
        if ($topic_type == POST_GLOBAL)
2330
        {
2331
                $sql = 'DELETE FROM ' . TOPICS_TABLE . '
2332
                        WHERE topic_moved_id = ' . $data['topic_id'];
2333
                $db->sql_query($sql);
2334
        }
2335
2336
        // Committing the transaction before updating search index
2337
        $db->sql_transaction('commit');
2338
2339
        // Delete draft if post was loaded...
2340
        $draft_id = request_var('draft_loaded', 0);
2341
        if ($draft_id)
2342
        {
2343
                $sql = 'DELETE FROM ' . DRAFTS_TABLE . "
2344
                        WHERE draft_id = $draft_id
2345
                                AND user_id = {$user->data['user_id']}";
2346
                $db->sql_query($sql);
2347
        }
2348
2349
        // Index message contents
2350
        if ($update_search_index && $data['enable_indexing'])
2351
        {
2352
                // Select the search method and do some additional checks to ensure it can actually be utilised
2353
                $search_type = $config['search_type'];
2354
2355
                if (!class_exists($search_type))
2356
                {
2357
                        trigger_error('NO_SUCH_SEARCH_MODULE');
2358
                }
2359
2360
                $error = false;
2361
                $search = new $search_type($error);
2362
2363
                if ($error)
2364
                {
2365
                        trigger_error($error);
2366
                }
2367
2368
                $search->index($mode, $data['post_id'], $data['message'], $subject, $poster_id, $data['forum_id']);
2369
        }
2370
2371
        // Topic Notification, do not change if moderator is changing other users posts...
2372
        if ($user->data['user_id'] == $poster_id)
2373
        {
2374
                if (!$data['notify_set'] && $data['notify'])
2375
                {
2376
                        $sql = 'INSERT INTO ' . TOPICS_WATCH_TABLE . ' (user_id, topic_id)
2377
                                VALUES (' . $user->data['user_id'] . ', ' . $data['topic_id'] . ')';
2378
                        $db->sql_query($sql);
2379
                }
2380
                else if (($config['email_enable'] || $config['jab_enable']) && $data['notify_set'] && !$data['notify'])
2381
                {
2382
                        $sql = 'DELETE FROM ' . TOPICS_WATCH_TABLE . '
2383
                                WHERE user_id = ' . $user->data['user_id'] . '
2384
                                        AND topic_id = ' . $data['topic_id'];
2385
                        $db->sql_query($sql);
2386
                }
2387
        }
2388
2389
        if ($mode == 'post' || $mode == 'reply' || $mode == 'quote')
2390
        {
2391
                // Mark this topic as posted to
2392
                markread('post', $data['forum_id'], $data['topic_id']);
2393
        }
2394
2395
        // Mark this topic as read
2396
        // We do not use post_time here, this is intended (post_time can have a date in the past if editing a message)
2397
        markread('topic', $data['forum_id'], $data['topic_id'], time());
2398
2399
        //
2400
        if ($config['load_db_lastread'] && $user->data['is_registered'])
2401
        {
2402
                $sql = 'SELECT mark_time
2403
                        FROM ' . FORUMS_TRACK_TABLE . '
2404
                        WHERE user_id = ' . $user->data['user_id'] . '
2405
                                AND forum_id = ' . $data['forum_id'];
2406
                $result = $db->sql_query($sql);
2407
                $f_mark_time = (int) $db->sql_fetchfield('mark_time');
2408
                $db->sql_freeresult($result);
2409
        }
2410
        else if ($config['load_anon_lastread'] || $user->data['is_registered'])
2411
        {
2412
                $f_mark_time = false;
2413
        }
2414
2415
        if (($config['load_db_lastread'] && $user->data['is_registered']) || $config['load_anon_lastread'] || $user->data['is_registered'])
2416
        {
2417
                // Update forum info
2418
                $sql = 'SELECT forum_last_post_time
2419
                        FROM ' . FORUMS_TABLE . '
2420
                        WHERE forum_id = ' . $data['forum_id'];
2421
                $result = $db->sql_query($sql);
2422
                $forum_last_post_time = (int) $db->sql_fetchfield('forum_last_post_time');
2423
                $db->sql_freeresult($result);
2424
2425
                update_forum_tracking_info($data['forum_id'], $forum_last_post_time, $f_mark_time, false);
2426
        }
2427
2428
        // Send Notifications
2429
        if (($mode == 'reply' || $mode == 'quote' || $mode == 'post') && $post_approval)
2430
        {
2431
                user_notification($mode, $subject, $data['topic_title'], $data['forum_name'], $data['forum_id'], $data['topic_id'], $data['post_id']);
2432
        }
2433
2434
        $params = $add_anchor = '';
2435
2436
        if ($post_approval)
2437
        {
2438
                $params .= '&amp;t=' . $data['topic_id'];
2439
2440
                if ($mode != 'post')
2441
                {
2442
                        $params .= '&amp;p=' . $data['post_id'];
2443
                        $add_anchor = '#p' . $data['post_id'];
2444
                }
2445
        }
2446
        else if ($mode != 'post' && $post_mode != 'edit_first_post' && $post_mode != 'edit_topic')
2447
        {
2448
                $params .= '&amp;t=' . $data['topic_id'];
2449
        }
2450
2451
        $url = (!$params) ? "{$phpbb_root_path}viewforum.$phpEx" : "{$phpbb_root_path}viewtopic.$phpEx";
2452
        $url = append_sid($url, 'f=' . $data['forum_id'] . $params) . $add_anchor;
2453
2454
        return $url;
2455
}
2456
2457
/**
2458
* Handle topic bumping
2459
* @param int $forum_id The ID of the forum the topic is being bumped belongs to
2460
* @param int $topic_id The ID of the topic is being bumping
2461
* @param array $post_data Passes some topic parameters:
2462
*                                - 'topic_title'
2463
*                                - 'topic_last_post_id'
2464
*                                - 'topic_last_poster_id'
2465
*                                - 'topic_last_post_subject'
2466
*                                - 'topic_last_poster_name'
2467
*                                - 'topic_last_poster_colour'
2468
* @param int $bump_time The time at which topic was bumped, usually it is a current time as obtained via time().
2469
* @return string An URL to the bumped topic, example: ./viewtopic.php?forum_id=1&amptopic_id=2&ampp=3#p3
2470
*/
2471
function phpbb_bump_topic($forum_id, $topic_id, $post_data, $bump_time = false)
2472
{
2473
        global $config, $db, $user, $phpEx, $phpbb_root_path;
2474
2475
        if ($bump_time === false)
2476
        {
2477
                $bump_time = time();
2478
        }
2479
2480
        // Begin bumping
2481
        $db->sql_transaction('begin');
2482
2483
        // Update the topic's last post post_time
2484
        $sql = 'UPDATE ' . POSTS_TABLE . "
2485
                SET post_time = $bump_time
2486
                WHERE post_id = {$post_data['topic_last_post_id']}
2487
                        AND topic_id = $topic_id";
2488
        $db->sql_query($sql);
2489
2490
        // Sync the topic's last post time, the rest of the topic's last post data isn't changed
2491
        $sql = 'UPDATE ' . TOPICS_TABLE . "
2492
                SET topic_last_post_time = $bump_time,
2493
                        topic_bumped = 1,
2494
                        topic_bumper = " . $user->data['user_id'] . "
2495
                WHERE topic_id = $topic_id";
2496
        $db->sql_query($sql);
2497
2498
        // Update the forum's last post info
2499
        $sql = 'UPDATE ' . FORUMS_TABLE . "
2500
                SET forum_last_post_id = " . $post_data['topic_last_post_id'] . ",
2501
                        forum_last_poster_id = " . $post_data['topic_last_poster_id'] . ",
2502
                        forum_last_post_subject = '" . $db->sql_escape($post_data['topic_last_post_subject']) . "',
2503
                        forum_last_post_time = $bump_time,
2504
                        forum_last_poster_name = '" . $db->sql_escape($post_data['topic_last_poster_name']) . "',
2505
                        forum_last_poster_colour = '" . $db->sql_escape($post_data['topic_last_poster_colour']) . "'
2506
                WHERE forum_id = $forum_id";
2507
        $db->sql_query($sql);
2508
2509
        // Update bumper's time of the last posting to prevent flood
2510
        $sql = 'UPDATE ' . USERS_TABLE . "
2511
                SET user_lastpost_time = $bump_time
2512
                WHERE user_id = " . $user->data['user_id'];
2513
        $db->sql_query($sql);
2514
2515
        $db->sql_transaction('commit');
2516
2517
        // Mark this topic as posted to
2518
        markread('post', $forum_id, $topic_id, $bump_time);
2519
2520
        // Mark this topic as read
2521
        markread('topic', $forum_id, $topic_id, $bump_time);
2522
2523
        // Update forum tracking info
2524
        if ($config['load_db_lastread'] && $user->data['is_registered'])
2525
        {
2526
                $sql = 'SELECT mark_time
2527
                        FROM ' . FORUMS_TRACK_TABLE . '
2528
                        WHERE user_id = ' . $user->data['user_id'] . '
2529
                                AND forum_id = ' . $forum_id;
2530
                $result = $db->sql_query($sql);
2531
                $f_mark_time = (int) $db->sql_fetchfield('mark_time');
2532
                $db->sql_freeresult($result);
2533
        }
2534
        else if ($config['load_anon_lastread'] || $user->data['is_registered'])
2535
        {
2536
                $f_mark_time = false;
2537
        }
2538
2539
        if (($config['load_db_lastread'] && $user->data['is_registered']) || $config['load_anon_lastread'] || $user->data['is_registered'])
2540
        {
2541
                // Update forum info
2542
                $sql = 'SELECT forum_last_post_time
2543
                        FROM ' . FORUMS_TABLE . '
2544
                        WHERE forum_id = ' . $forum_id;
2545
                $result = $db->sql_query($sql);
2546
                $forum_last_post_time = (int) $db->sql_fetchfield('forum_last_post_time');
2547
                $db->sql_freeresult($result);
2548
2549
                update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_time, false);
2550
        }
2551
2552
        add_log('mod', $forum_id, $topic_id, 'LOG_BUMP_TOPIC', $post_data['topic_title']);
2553
2554
        $url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&amp;t=$topic_id&amp;p={$post_data['topic_last_post_id']}") . "#p{$post_data['topic_last_post_id']}";
2555
2556
        return $url;
2557
}