comparison forum/Sources/Post.php @ 76:e3e11437ecea website

Add forum code
author Chris Cannam
date Sun, 07 Jul 2013 11:25:48 +0200
parents
children
comparison
equal deleted inserted replaced
75:72f59aa7e503 76:e3e11437ecea
1 <?php
2
3 /**
4 * Simple Machines Forum (SMF)
5 *
6 * @package SMF
7 * @author Simple Machines http://www.simplemachines.org
8 * @copyright 2011 Simple Machines
9 * @license http://www.simplemachines.org/about/smf/license.php BSD
10 *
11 * @version 2.0
12 */
13
14 if (!defined('SMF'))
15 die('Hacking attempt...');
16
17 /* The job of this file is to handle everything related to posting replies,
18 new topics, quotes, and modifications to existing posts. It also handles
19 quoting posts by way of javascript.
20
21 void Post()
22 - handles showing the post screen, loading the post to be modified, and
23 loading any post quoted.
24 - additionally handles previews of posts.
25 - uses the Post template and language file, main sub template.
26 - allows wireless access using the protocol_post sub template.
27 - requires different permissions depending on the actions, but most
28 notably post_new, post_reply_own, and post_reply_any.
29 - shows options for the editing and posting of calendar events and
30 attachments, as well as the posting of polls.
31 - accessed from ?action=post.
32
33 void Post2()
34 - actually posts or saves the message composed with Post().
35 - requires various permissions depending on the action.
36 - handles attachment, post, and calendar saving.
37 - sends off notifications, and allows for announcements and moderation.
38 - accessed from ?action=post2.
39
40 void AnnounceTopic()
41 - handle the announce topic function (action=announce).
42 - checks the topic announcement permissions and loads the announcement
43 template.
44 - requires the announce_topic permission.
45 - uses the ManageMembers template and Post language file.
46 - call the right function based on the sub-action.
47
48 void AnnouncementSelectMembergroup()
49 - lets the user select the membergroups that will receive the topic
50 announcement.
51
52 void AnnouncementSend()
53 - splits the members to be sent a topic announcement into chunks.
54 - composes notification messages in all languages needed.
55 - does the actual sending of the topic announcements in chunks.
56 - calculates a rough estimate of the percentage items sent.
57
58 void notifyMembersBoard(notifyData)
59 - notifies members who have requested notification for new topics
60 posted on a board of said posts.
61 - receives data on the topics to send out notifications to by the passed in array.
62 - only sends notifications to those who can *currently* see the topic
63 (it doesn't matter if they could when they requested notification.)
64 - loads the Post language file multiple times for each language if the
65 userLanguage setting is set.
66
67 void getTopic()
68 - gets a summary of the most recent posts in a topic.
69 - depends on the topicSummaryPosts setting.
70 - if you are editing a post, only shows posts previous to that post.
71
72 void QuoteFast()
73 - loads a post an inserts it into the current editing text box.
74 - uses the Post language file.
75 - uses special (sadly browser dependent) javascript to parse entities
76 for internationalization reasons.
77 - accessed with ?action=quotefast.
78
79 void JavaScriptModify()
80 // !!!
81 */
82
83 function Post()
84 {
85 global $txt, $scripturl, $topic, $modSettings, $board;
86 global $user_info, $sc, $board_info, $context, $settings;
87 global $sourcedir, $options, $smcFunc, $language;
88
89 loadLanguage('Post');
90
91 // You can't reply with a poll... hacker.
92 if (isset($_REQUEST['poll']) && !empty($topic) && !isset($_REQUEST['msg']))
93 unset($_REQUEST['poll']);
94
95 // Posting an event?
96 $context['make_event'] = isset($_REQUEST['calendar']);
97 $context['robot_no_index'] = true;
98
99 // You must be posting to *some* board.
100 if (empty($board) && !$context['make_event'])
101 fatal_lang_error('no_board', false);
102
103 require_once($sourcedir . '/Subs-Post.php');
104
105 if (isset($_REQUEST['xml']))
106 {
107 $context['sub_template'] = 'post';
108
109 // Just in case of an earlier error...
110 $context['preview_message'] = '';
111 $context['preview_subject'] = '';
112 }
113
114 // No message is complete without a topic.
115 if (empty($topic) && !empty($_REQUEST['msg']))
116 {
117 $request = $smcFunc['db_query']('', '
118 SELECT id_topic
119 FROM {db_prefix}messages
120 WHERE id_msg = {int:msg}',
121 array(
122 'msg' => (int) $_REQUEST['msg'],
123 ));
124 if ($smcFunc['db_num_rows']($request) != 1)
125 unset($_REQUEST['msg'], $_POST['msg'], $_GET['msg']);
126 else
127 list ($topic) = $smcFunc['db_fetch_row']($request);
128 $smcFunc['db_free_result']($request);
129 }
130
131 // Check if it's locked. It isn't locked if no topic is specified.
132 if (!empty($topic))
133 {
134 $request = $smcFunc['db_query']('', '
135 SELECT
136 t.locked, IFNULL(ln.id_topic, 0) AS notify, t.is_sticky, t.id_poll, t.id_last_msg, mf.id_member,
137 t.id_first_msg, mf.subject,
138 CASE WHEN ml.poster_time > ml.modified_time THEN ml.poster_time ELSE ml.modified_time END AS last_post_time
139 FROM {db_prefix}topics AS t
140 LEFT JOIN {db_prefix}log_notify AS ln ON (ln.id_topic = t.id_topic AND ln.id_member = {int:current_member})
141 LEFT JOIN {db_prefix}messages AS mf ON (mf.id_msg = t.id_first_msg)
142 LEFT JOIN {db_prefix}messages AS ml ON (ml.id_msg = t.id_last_msg)
143 WHERE t.id_topic = {int:current_topic}
144 LIMIT 1',
145 array(
146 'current_member' => $user_info['id'],
147 'current_topic' => $topic,
148 )
149 );
150 list ($locked, $context['notify'], $sticky, $pollID, $context['topic_last_message'], $id_member_poster, $id_first_msg, $first_subject, $lastPostTime) = $smcFunc['db_fetch_row']($request);
151 $smcFunc['db_free_result']($request);
152
153 // If this topic already has a poll, they sure can't add another.
154 if (isset($_REQUEST['poll']) && $pollID > 0)
155 unset($_REQUEST['poll']);
156
157 if (empty($_REQUEST['msg']))
158 {
159 if ($user_info['is_guest'] && !allowedTo('post_reply_any') && (!$modSettings['postmod_active'] || !allowedTo('post_unapproved_replies_any')))
160 is_not_guest();
161
162 // By default the reply will be approved...
163 $context['becomes_approved'] = true;
164 if ($id_member_poster != $user_info['id'])
165 {
166 if ($modSettings['postmod_active'] && allowedTo('post_unapproved_replies_any') && !allowedTo('post_reply_any'))
167 $context['becomes_approved'] = false;
168 else
169 isAllowedTo('post_reply_any');
170 }
171 elseif (!allowedTo('post_reply_any'))
172 {
173 if ($modSettings['postmod_active'] && allowedTo('post_unapproved_replies_own') && !allowedTo('post_reply_own'))
174 $context['becomes_approved'] = false;
175 else
176 isAllowedTo('post_reply_own');
177 }
178 }
179 else
180 $context['becomes_approved'] = true;
181
182 $context['can_lock'] = allowedTo('lock_any') || ($user_info['id'] == $id_member_poster && allowedTo('lock_own'));
183 $context['can_sticky'] = allowedTo('make_sticky') && !empty($modSettings['enableStickyTopics']);
184
185 $context['notify'] = !empty($context['notify']);
186 $context['sticky'] = isset($_REQUEST['sticky']) ? !empty($_REQUEST['sticky']) : $sticky;
187 }
188 else
189 {
190 $context['becomes_approved'] = true;
191 if ((!$context['make_event'] || !empty($board)))
192 {
193 if ($modSettings['postmod_active'] && !allowedTo('post_new') && allowedTo('post_unapproved_topics'))
194 $context['becomes_approved'] = false;
195 else
196 isAllowedTo('post_new');
197 }
198
199 $locked = 0;
200 // !!! These won't work if you're making an event.
201 $context['can_lock'] = allowedTo(array('lock_any', 'lock_own'));
202 $context['can_sticky'] = allowedTo('make_sticky') && !empty($modSettings['enableStickyTopics']);
203
204 $context['notify'] = !empty($context['notify']);
205 $context['sticky'] = !empty($_REQUEST['sticky']);
206 }
207
208 // !!! These won't work if you're posting an event!
209 $context['can_notify'] = allowedTo('mark_any_notify');
210 $context['can_move'] = allowedTo('move_any');
211 $context['move'] = !empty($_REQUEST['move']);
212 $context['announce'] = !empty($_REQUEST['announce']);
213 // You can only announce topics that will get approved...
214 $context['can_announce'] = allowedTo('announce_topic') && $context['becomes_approved'];
215 $context['locked'] = !empty($locked) || !empty($_REQUEST['lock']);
216 $context['can_quote'] = empty($modSettings['disabledBBC']) || !in_array('quote', explode(',', $modSettings['disabledBBC']));
217
218 // Generally don't show the approval box... (Assume we want things approved)
219 $context['show_approval'] = false;
220
221 // An array to hold all the attachments for this topic.
222 $context['current_attachments'] = array();
223
224 // Don't allow a post if it's locked and you aren't all powerful.
225 if ($locked && !allowedTo('moderate_board'))
226 fatal_lang_error('topic_locked', false);
227 // Check the users permissions - is the user allowed to add or post a poll?
228 if (isset($_REQUEST['poll']) && $modSettings['pollMode'] == '1')
229 {
230 // New topic, new poll.
231 if (empty($topic))
232 isAllowedTo('poll_post');
233 // This is an old topic - but it is yours! Can you add to it?
234 elseif ($user_info['id'] == $id_member_poster && !allowedTo('poll_add_any'))
235 isAllowedTo('poll_add_own');
236 // If you're not the owner, can you add to any poll?
237 else
238 isAllowedTo('poll_add_any');
239
240 require_once($sourcedir . '/Subs-Members.php');
241 $allowedVoteGroups = groupsAllowedTo('poll_vote', $board);
242
243 // Set up the poll options.
244 $context['poll_options'] = array(
245 'max_votes' => empty($_POST['poll_max_votes']) ? '1' : max(1, $_POST['poll_max_votes']),
246 'hide' => empty($_POST['poll_hide']) ? 0 : $_POST['poll_hide'],
247 'expire' => !isset($_POST['poll_expire']) ? '' : $_POST['poll_expire'],
248 'change_vote' => isset($_POST['poll_change_vote']),
249 'guest_vote' => isset($_POST['poll_guest_vote']),
250 'guest_vote_enabled' => in_array(-1, $allowedVoteGroups['allowed']),
251 );
252
253 // Make all five poll choices empty.
254 $context['choices'] = array(
255 array('id' => 0, 'number' => 1, 'label' => '', 'is_last' => false),
256 array('id' => 1, 'number' => 2, 'label' => '', 'is_last' => false),
257 array('id' => 2, 'number' => 3, 'label' => '', 'is_last' => false),
258 array('id' => 3, 'number' => 4, 'label' => '', 'is_last' => false),
259 array('id' => 4, 'number' => 5, 'label' => '', 'is_last' => true)
260 );
261 }
262
263 if ($context['make_event'])
264 {
265 // They might want to pick a board.
266 if (!isset($context['current_board']))
267 $context['current_board'] = 0;
268
269 // Start loading up the event info.
270 $context['event'] = array();
271 $context['event']['title'] = isset($_REQUEST['evtitle']) ? htmlspecialchars(stripslashes($_REQUEST['evtitle'])) : '';
272
273 $context['event']['id'] = isset($_REQUEST['eventid']) ? (int) $_REQUEST['eventid'] : -1;
274 $context['event']['new'] = $context['event']['id'] == -1;
275
276 // Permissions check!
277 isAllowedTo('calendar_post');
278
279 // Editing an event? (but NOT previewing!?)
280 if (!$context['event']['new'] && !isset($_REQUEST['subject']))
281 {
282 // If the user doesn't have permission to edit the post in this topic, redirect them.
283 if ((empty($id_member_poster) || $id_member_poster != $user_info['id'] || !allowedTo('modify_own')) && !allowedTo('modify_any'))
284 {
285 require_once($sourcedir . '/Calendar.php');
286 return CalendarPost();
287 }
288
289 // Get the current event information.
290 $request = $smcFunc['db_query']('', '
291 SELECT
292 id_member, title, MONTH(start_date) AS month, DAYOFMONTH(start_date) AS day,
293 YEAR(start_date) AS year, (TO_DAYS(end_date) - TO_DAYS(start_date)) AS span
294 FROM {db_prefix}calendar
295 WHERE id_event = {int:id_event}
296 LIMIT 1',
297 array(
298 'id_event' => $context['event']['id'],
299 )
300 );
301 $row = $smcFunc['db_fetch_assoc']($request);
302 $smcFunc['db_free_result']($request);
303
304 // Make sure the user is allowed to edit this event.
305 if ($row['id_member'] != $user_info['id'])
306 isAllowedTo('calendar_edit_any');
307 elseif (!allowedTo('calendar_edit_any'))
308 isAllowedTo('calendar_edit_own');
309
310 $context['event']['month'] = $row['month'];
311 $context['event']['day'] = $row['day'];
312 $context['event']['year'] = $row['year'];
313 $context['event']['title'] = $row['title'];
314 $context['event']['span'] = $row['span'] + 1;
315 }
316 else
317 {
318 $today = getdate();
319
320 // You must have a month and year specified!
321 if (!isset($_REQUEST['month']))
322 $_REQUEST['month'] = $today['mon'];
323 if (!isset($_REQUEST['year']))
324 $_REQUEST['year'] = $today['year'];
325
326 $context['event']['month'] = (int) $_REQUEST['month'];
327 $context['event']['year'] = (int) $_REQUEST['year'];
328 $context['event']['day'] = isset($_REQUEST['day']) ? $_REQUEST['day'] : ($_REQUEST['month'] == $today['mon'] ? $today['mday'] : 0);
329 $context['event']['span'] = isset($_REQUEST['span']) ? $_REQUEST['span'] : 1;
330
331 // Make sure the year and month are in the valid range.
332 if ($context['event']['month'] < 1 || $context['event']['month'] > 12)
333 fatal_lang_error('invalid_month', false);
334 if ($context['event']['year'] < $modSettings['cal_minyear'] || $context['event']['year'] > $modSettings['cal_maxyear'])
335 fatal_lang_error('invalid_year', false);
336
337 // Get a list of boards they can post in.
338 $boards = boardsAllowedTo('post_new');
339 if (empty($boards))
340 fatal_lang_error('cannot_post_new', 'user');
341
342 // Load a list of boards for this event in the context.
343 require_once($sourcedir . '/Subs-MessageIndex.php');
344 $boardListOptions = array(
345 'included_boards' => in_array(0, $boards) ? null : $boards,
346 'not_redirection' => true,
347 'use_permissions' => true,
348 'selected_board' => empty($context['current_board']) ? $modSettings['cal_defaultboard'] : $context['current_board'],
349 );
350 $context['event']['categories'] = getBoardList($boardListOptions);
351 }
352
353 // Find the last day of the month.
354 $context['event']['last_day'] = (int) strftime('%d', mktime(0, 0, 0, $context['event']['month'] == 12 ? 1 : $context['event']['month'] + 1, 0, $context['event']['month'] == 12 ? $context['event']['year'] + 1 : $context['event']['year']));
355
356 $context['event']['board'] = !empty($board) ? $board : $modSettings['cal_defaultboard'];
357 }
358
359 if (empty($context['post_errors']))
360 $context['post_errors'] = array();
361
362 // See if any new replies have come along.
363 if (empty($_REQUEST['msg']) && !empty($topic))
364 {
365 if (empty($options['no_new_reply_warning']) && isset($_REQUEST['last_msg']) && $context['topic_last_message'] > $_REQUEST['last_msg'])
366 {
367 $request = $smcFunc['db_query']('', '
368 SELECT COUNT(*)
369 FROM {db_prefix}messages
370 WHERE id_topic = {int:current_topic}
371 AND id_msg > {int:last_msg}' . (!$modSettings['postmod_active'] || allowedTo('approve_posts') ? '' : '
372 AND approved = {int:approved}') . '
373 LIMIT 1',
374 array(
375 'current_topic' => $topic,
376 'last_msg' => (int) $_REQUEST['last_msg'],
377 'approved' => 1,
378 )
379 );
380 list ($context['new_replies']) = $smcFunc['db_fetch_row']($request);
381 $smcFunc['db_free_result']($request);
382
383 if (!empty($context['new_replies']))
384 {
385 if ($context['new_replies'] == 1)
386 $txt['error_new_reply'] = isset($_GET['last_msg']) ? $txt['error_new_reply_reading'] : $txt['error_new_reply'];
387 else
388 $txt['error_new_replies'] = sprintf(isset($_GET['last_msg']) ? $txt['error_new_replies_reading'] : $txt['error_new_replies'], $context['new_replies']);
389
390 // If they've come from the display page then we treat the error differently....
391 if (isset($_GET['last_msg']))
392 $newRepliesError = $context['new_replies'];
393 else
394 $context['post_error'][$context['new_replies'] == 1 ? 'new_reply' : 'new_replies'] = true;
395
396 $modSettings['topicSummaryPosts'] = $context['new_replies'] > $modSettings['topicSummaryPosts'] ? max($modSettings['topicSummaryPosts'], 5) : $modSettings['topicSummaryPosts'];
397 }
398 }
399 // Check whether this is a really old post being bumped...
400 if (!empty($modSettings['oldTopicDays']) && $lastPostTime + $modSettings['oldTopicDays'] * 86400 < time() && empty($sticky) && !isset($_REQUEST['subject']))
401 $oldTopicError = true;
402 }
403
404 // Get a response prefix (like 'Re:') in the default forum language.
405 if (!isset($context['response_prefix']) && !($context['response_prefix'] = cache_get_data('response_prefix')))
406 {
407 if ($language === $user_info['language'])
408 $context['response_prefix'] = $txt['response_prefix'];
409 else
410 {
411 loadLanguage('index', $language, false);
412 $context['response_prefix'] = $txt['response_prefix'];
413 loadLanguage('index');
414 }
415 cache_put_data('response_prefix', $context['response_prefix'], 600);
416 }
417
418 // Previewing, modifying, or posting?
419 if (isset($_REQUEST['message']) || !empty($context['post_error']))
420 {
421 // Validate inputs.
422 if (empty($context['post_error']))
423 {
424 if (htmltrim__recursive(htmlspecialchars__recursive($_REQUEST['subject'])) == '')
425 $context['post_error']['no_subject'] = true;
426 if (htmltrim__recursive(htmlspecialchars__recursive($_REQUEST['message'])) == '')
427 $context['post_error']['no_message'] = true;
428 if (!empty($modSettings['max_messageLength']) && $smcFunc['strlen']($_REQUEST['message']) > $modSettings['max_messageLength'])
429 $context['post_error']['long_message'] = true;
430
431 // Are you... a guest?
432 if ($user_info['is_guest'])
433 {
434 $_REQUEST['guestname'] = !isset($_REQUEST['guestname']) ? '' : trim($_REQUEST['guestname']);
435 $_REQUEST['email'] = !isset($_REQUEST['email']) ? '' : trim($_REQUEST['email']);
436
437 // Validate the name and email.
438 if (!isset($_REQUEST['guestname']) || trim(strtr($_REQUEST['guestname'], '_', ' ')) == '')
439 $context['post_error']['no_name'] = true;
440 elseif ($smcFunc['strlen']($_REQUEST['guestname']) > 25)
441 $context['post_error']['long_name'] = true;
442 else
443 {
444 require_once($sourcedir . '/Subs-Members.php');
445 if (isReservedName(htmlspecialchars($_REQUEST['guestname']), 0, true, false))
446 $context['post_error']['bad_name'] = true;
447 }
448
449 if (empty($modSettings['guest_post_no_email']))
450 {
451 if (!isset($_REQUEST['email']) || $_REQUEST['email'] == '')
452 $context['post_error']['no_email'] = true;
453 elseif (preg_match('~^[0-9A-Za-z=_+\-/][0-9A-Za-z=_\'+\-/\.]*@[\w\-]+(\.[\w\-]+)*(\.[\w]{2,6})$~', $_REQUEST['email']) == 0)
454 $context['post_error']['bad_email'] = true;
455 }
456 }
457
458 // This is self explanatory - got any questions?
459 if (isset($_REQUEST['question']) && trim($_REQUEST['question']) == '')
460 $context['post_error']['no_question'] = true;
461
462 // This means they didn't click Post and get an error.
463 $really_previewing = true;
464 }
465 else
466 {
467 if (!isset($_REQUEST['subject']))
468 $_REQUEST['subject'] = '';
469 if (!isset($_REQUEST['message']))
470 $_REQUEST['message'] = '';
471 if (!isset($_REQUEST['icon']))
472 $_REQUEST['icon'] = 'xx';
473
474 // They are previewing if they asked to preview (i.e. came from quick reply).
475 $really_previewing = !empty($_POST['preview']);
476 }
477
478 // In order to keep the approval status flowing through, we have to pass it through the form...
479 $context['becomes_approved'] = empty($_REQUEST['not_approved']);
480 $context['show_approval'] = isset($_REQUEST['approve']) ? ($_REQUEST['approve'] ? 2 : 1) : 0;
481 $context['can_announce'] &= $context['becomes_approved'];
482
483 // Set up the inputs for the form.
484 $form_subject = strtr($smcFunc['htmlspecialchars']($_REQUEST['subject']), array("\r" => '', "\n" => '', "\t" => ''));
485 $form_message = $smcFunc['htmlspecialchars']($_REQUEST['message'], ENT_QUOTES);
486
487 // Make sure the subject isn't too long - taking into account special characters.
488 if ($smcFunc['strlen']($form_subject) > 100)
489 $form_subject = $smcFunc['substr']($form_subject, 0, 100);
490
491 // Have we inadvertently trimmed off the subject of useful information?
492 if ($smcFunc['htmltrim']($form_subject) === '')
493 $context['post_error']['no_subject'] = true;
494
495 // Any errors occurred?
496 if (!empty($context['post_error']))
497 {
498 loadLanguage('Errors');
499
500 $context['error_type'] = 'minor';
501
502 $context['post_error']['messages'] = array();
503 foreach ($context['post_error'] as $post_error => $dummy)
504 {
505 if ($post_error == 'messages')
506 continue;
507
508 if ($post_error == 'long_message')
509 $txt['error_' . $post_error] = sprintf($txt['error_' . $post_error], $modSettings['max_messageLength']);
510
511 $context['post_error']['messages'][] = $txt['error_' . $post_error];
512
513 // If it's not a minor error flag it as such.
514 if (!in_array($post_error, array('new_reply', 'not_approved', 'new_replies', 'old_topic', 'need_qr_verification')))
515 $context['error_type'] = 'serious';
516 }
517 }
518
519 if (isset($_REQUEST['poll']))
520 {
521 $context['question'] = isset($_REQUEST['question']) ? $smcFunc['htmlspecialchars'](trim($_REQUEST['question'])) : '';
522
523 $context['choices'] = array();
524 $choice_id = 0;
525
526 $_POST['options'] = empty($_POST['options']) ? array() : htmlspecialchars__recursive($_POST['options']);
527 foreach ($_POST['options'] as $option)
528 {
529 if (trim($option) == '')
530 continue;
531
532 $context['choices'][] = array(
533 'id' => $choice_id++,
534 'number' => $choice_id,
535 'label' => $option,
536 'is_last' => false
537 );
538 }
539
540 if (count($context['choices']) < 2)
541 {
542 $context['choices'][] = array(
543 'id' => $choice_id++,
544 'number' => $choice_id,
545 'label' => '',
546 'is_last' => false
547 );
548 $context['choices'][] = array(
549 'id' => $choice_id++,
550 'number' => $choice_id,
551 'label' => '',
552 'is_last' => false
553 );
554 }
555 $context['choices'][count($context['choices']) - 1]['is_last'] = true;
556 }
557
558 // Are you... a guest?
559 if ($user_info['is_guest'])
560 {
561 $_REQUEST['guestname'] = !isset($_REQUEST['guestname']) ? '' : trim($_REQUEST['guestname']);
562 $_REQUEST['email'] = !isset($_REQUEST['email']) ? '' : trim($_REQUEST['email']);
563
564 $_REQUEST['guestname'] = htmlspecialchars($_REQUEST['guestname']);
565 $context['name'] = $_REQUEST['guestname'];
566 $_REQUEST['email'] = htmlspecialchars($_REQUEST['email']);
567 $context['email'] = $_REQUEST['email'];
568
569 $user_info['name'] = $_REQUEST['guestname'];
570 }
571
572 // Only show the preview stuff if they hit Preview.
573 if ($really_previewing == true || isset($_REQUEST['xml']))
574 {
575 // Set up the preview message and subject and censor them...
576 $context['preview_message'] = $form_message;
577 preparsecode($form_message, true);
578 preparsecode($context['preview_message']);
579
580 // Do all bulletin board code tags, with or without smileys.
581 $context['preview_message'] = parse_bbc($context['preview_message'], isset($_REQUEST['ns']) ? 0 : 1);
582
583 if ($form_subject != '')
584 {
585 $context['preview_subject'] = $form_subject;
586
587 censorText($context['preview_subject']);
588 censorText($context['preview_message']);
589 }
590 else
591 $context['preview_subject'] = '<em>' . $txt['no_subject'] . '</em>';
592
593 // Protect any CDATA blocks.
594 if (isset($_REQUEST['xml']))
595 $context['preview_message'] = strtr($context['preview_message'], array(']]>' => ']]]]><![CDATA[>'));
596 }
597
598 // Set up the checkboxes.
599 $context['notify'] = !empty($_REQUEST['notify']);
600 $context['use_smileys'] = !isset($_REQUEST['ns']);
601
602 $context['icon'] = isset($_REQUEST['icon']) ? preg_replace('~[\./\\\\*\':"<>]~', '', $_REQUEST['icon']) : 'xx';
603
604 // Set the destination action for submission.
605 $context['destination'] = 'post2;start=' . $_REQUEST['start'] . (isset($_REQUEST['msg']) ? ';msg=' . $_REQUEST['msg'] . ';' . $context['session_var'] . '=' . $context['session_id'] : '') . (isset($_REQUEST['poll']) ? ';poll' : '');
606 $context['submit_label'] = isset($_REQUEST['msg']) ? $txt['save'] : $txt['post'];
607
608 // Previewing an edit?
609 if (isset($_REQUEST['msg']) && !empty($topic))
610 {
611 // Get the existing message.
612 $request = $smcFunc['db_query']('', '
613 SELECT
614 m.id_member, m.modified_time, m.smileys_enabled, m.body,
615 m.poster_name, m.poster_email, m.subject, m.icon, m.approved,
616 IFNULL(a.size, -1) AS filesize, a.filename, a.id_attach,
617 a.approved AS attachment_approved, t.id_member_started AS id_member_poster,
618 m.poster_time
619 FROM {db_prefix}messages AS m
620 INNER JOIN {db_prefix}topics AS t ON (t.id_topic = {int:current_topic})
621 LEFT JOIN {db_prefix}attachments AS a ON (a.id_msg = m.id_msg AND a.attachment_type = {int:attachment_type})
622 WHERE m.id_msg = {int:id_msg}
623 AND m.id_topic = {int:current_topic}',
624 array(
625 'current_topic' => $topic,
626 'attachment_type' => 0,
627 'id_msg' => $_REQUEST['msg'],
628 )
629 );
630 // The message they were trying to edit was most likely deleted.
631 // !!! Change this error message?
632 if ($smcFunc['db_num_rows']($request) == 0)
633 fatal_lang_error('no_board', false);
634 $row = $smcFunc['db_fetch_assoc']($request);
635
636 $attachment_stuff = array($row);
637 while ($row2 = $smcFunc['db_fetch_assoc']($request))
638 $attachment_stuff[] = $row2;
639 $smcFunc['db_free_result']($request);
640
641 if ($row['id_member'] == $user_info['id'] && !allowedTo('modify_any'))
642 {
643 // Give an extra five minutes over the disable time threshold, so they can type - assuming the post is public.
644 if ($row['approved'] && !empty($modSettings['edit_disable_time']) && $row['poster_time'] + ($modSettings['edit_disable_time'] + 5) * 60 < time())
645 fatal_lang_error('modify_post_time_passed', false);
646 elseif ($row['id_member_poster'] == $user_info['id'] && !allowedTo('modify_own'))
647 isAllowedTo('modify_replies');
648 else
649 isAllowedTo('modify_own');
650 }
651 elseif ($row['id_member_poster'] == $user_info['id'] && !allowedTo('modify_any'))
652 isAllowedTo('modify_replies');
653 else
654 isAllowedTo('modify_any');
655
656 if (!empty($modSettings['attachmentEnable']))
657 {
658 $request = $smcFunc['db_query']('', '
659 SELECT IFNULL(size, -1) AS filesize, filename, id_attach, approved
660 FROM {db_prefix}attachments
661 WHERE id_msg = {int:id_msg}
662 AND attachment_type = {int:attachment_type}',
663 array(
664 'id_msg' => (int) $_REQUEST['msg'],
665 'attachment_type' => 0,
666 )
667 );
668 while ($row = $smcFunc['db_fetch_assoc']($request))
669 {
670 if ($row['filesize'] <= 0)
671 continue;
672 $context['current_attachments'][] = array(
673 'name' => htmlspecialchars($row['filename']),
674 'id' => $row['id_attach'],
675 'approved' => $row['approved'],
676 );
677 }
678 $smcFunc['db_free_result']($request);
679 }
680
681 // Allow moderators to change names....
682 if (allowedTo('moderate_forum') && !empty($topic))
683 {
684 $request = $smcFunc['db_query']('', '
685 SELECT id_member, poster_name, poster_email
686 FROM {db_prefix}messages
687 WHERE id_msg = {int:id_msg}
688 AND id_topic = {int:current_topic}
689 LIMIT 1',
690 array(
691 'current_topic' => $topic,
692 'id_msg' => (int) $_REQUEST['msg'],
693 )
694 );
695 $row = $smcFunc['db_fetch_assoc']($request);
696 $smcFunc['db_free_result']($request);
697
698 if (empty($row['id_member']))
699 {
700 $context['name'] = htmlspecialchars($row['poster_name']);
701 $context['email'] = htmlspecialchars($row['poster_email']);
702 }
703 }
704 }
705
706 // No check is needed, since nothing is really posted.
707 checkSubmitOnce('free');
708 }
709 // Editing a message...
710 elseif (isset($_REQUEST['msg']) && !empty($topic))
711 {
712 $_REQUEST['msg'] = (int) $_REQUEST['msg'];
713
714 // Get the existing message.
715 $request = $smcFunc['db_query']('', '
716 SELECT
717 m.id_member, m.modified_time, m.smileys_enabled, m.body,
718 m.poster_name, m.poster_email, m.subject, m.icon, m.approved,
719 IFNULL(a.size, -1) AS filesize, a.filename, a.id_attach,
720 a.approved AS attachment_approved, t.id_member_started AS id_member_poster,
721 m.poster_time
722 FROM {db_prefix}messages AS m
723 INNER JOIN {db_prefix}topics AS t ON (t.id_topic = {int:current_topic})
724 LEFT JOIN {db_prefix}attachments AS a ON (a.id_msg = m.id_msg AND a.attachment_type = {int:attachment_type})
725 WHERE m.id_msg = {int:id_msg}
726 AND m.id_topic = {int:current_topic}',
727 array(
728 'current_topic' => $topic,
729 'attachment_type' => 0,
730 'id_msg' => $_REQUEST['msg'],
731 )
732 );
733 // The message they were trying to edit was most likely deleted.
734 // !!! Change this error message?
735 if ($smcFunc['db_num_rows']($request) == 0)
736 fatal_lang_error('no_board', false);
737 $row = $smcFunc['db_fetch_assoc']($request);
738
739 $attachment_stuff = array($row);
740 while ($row2 = $smcFunc['db_fetch_assoc']($request))
741 $attachment_stuff[] = $row2;
742 $smcFunc['db_free_result']($request);
743
744 if ($row['id_member'] == $user_info['id'] && !allowedTo('modify_any'))
745 {
746 // Give an extra five minutes over the disable time threshold, so they can type - assuming the post is public.
747 if ($row['approved'] && !empty($modSettings['edit_disable_time']) && $row['poster_time'] + ($modSettings['edit_disable_time'] + 5) * 60 < time())
748 fatal_lang_error('modify_post_time_passed', false);
749 elseif ($row['id_member_poster'] == $user_info['id'] && !allowedTo('modify_own'))
750 isAllowedTo('modify_replies');
751 else
752 isAllowedTo('modify_own');
753 }
754 elseif ($row['id_member_poster'] == $user_info['id'] && !allowedTo('modify_any'))
755 isAllowedTo('modify_replies');
756 else
757 isAllowedTo('modify_any');
758
759 // When was it last modified?
760 if (!empty($row['modified_time']))
761 $context['last_modified'] = timeformat($row['modified_time']);
762
763 // Get the stuff ready for the form.
764 $form_subject = $row['subject'];
765 $form_message = un_preparsecode($row['body']);
766 censorText($form_message);
767 censorText($form_subject);
768
769 // Check the boxes that should be checked.
770 $context['use_smileys'] = !empty($row['smileys_enabled']);
771 $context['icon'] = $row['icon'];
772
773 // Show an "approve" box if the user can approve it, and the message isn't approved.
774 if (!$row['approved'] && !$context['show_approval'])
775 $context['show_approval'] = allowedTo('approve_posts');
776
777 // Load up 'em attachments!
778 foreach ($attachment_stuff as $attachment)
779 {
780 if ($attachment['filesize'] >= 0 && !empty($modSettings['attachmentEnable']))
781 $context['current_attachments'][] = array(
782 'name' => htmlspecialchars($attachment['filename']),
783 'id' => $attachment['id_attach'],
784 'approved' => $attachment['attachment_approved'],
785 );
786 }
787
788 // Allow moderators to change names....
789 if (allowedTo('moderate_forum') && empty($row['id_member']))
790 {
791 $context['name'] = htmlspecialchars($row['poster_name']);
792 $context['email'] = htmlspecialchars($row['poster_email']);
793 }
794
795 // Set the destinaton.
796 $context['destination'] = 'post2;start=' . $_REQUEST['start'] . ';msg=' . $_REQUEST['msg'] . ';' . $context['session_var'] . '=' . $context['session_id'] . (isset($_REQUEST['poll']) ? ';poll' : '');
797 $context['submit_label'] = $txt['save'];
798 }
799 // Posting...
800 else
801 {
802 // By default....
803 $context['use_smileys'] = true;
804 $context['icon'] = 'xx';
805
806 if ($user_info['is_guest'])
807 {
808 $context['name'] = isset($_SESSION['guest_name']) ? $_SESSION['guest_name'] : '';
809 $context['email'] = isset($_SESSION['guest_email']) ? $_SESSION['guest_email'] : '';
810 }
811 $context['destination'] = 'post2;start=' . $_REQUEST['start'] . (isset($_REQUEST['poll']) ? ';poll' : '');
812
813 $context['submit_label'] = $txt['post'];
814
815 // Posting a quoted reply?
816 if (!empty($topic) && !empty($_REQUEST['quote']))
817 {
818 // Make sure they _can_ quote this post, and if so get it.
819 $request = $smcFunc['db_query']('', '
820 SELECT m.subject, IFNULL(mem.real_name, m.poster_name) AS poster_name, m.poster_time, m.body
821 FROM {db_prefix}messages AS m
822 INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board AND {query_see_board})
823 LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member)
824 WHERE m.id_msg = {int:id_msg}' . (!$modSettings['postmod_active'] || allowedTo('approve_posts') ? '' : '
825 AND m.approved = {int:is_approved}') . '
826 LIMIT 1',
827 array(
828 'id_msg' => (int) $_REQUEST['quote'],
829 'is_approved' => 1,
830 )
831 );
832 if ($smcFunc['db_num_rows']($request) == 0)
833 fatal_lang_error('quoted_post_deleted', false);
834 list ($form_subject, $mname, $mdate, $form_message) = $smcFunc['db_fetch_row']($request);
835 $smcFunc['db_free_result']($request);
836
837 // Add 'Re: ' to the front of the quoted subject.
838 if (trim($context['response_prefix']) != '' && $smcFunc['strpos']($form_subject, trim($context['response_prefix'])) !== 0)
839 $form_subject = $context['response_prefix'] . $form_subject;
840
841 // Censor the message and subject.
842 censorText($form_message);
843 censorText($form_subject);
844
845 // But if it's in HTML world, turn them into htmlspecialchar's so they can be edited!
846 if (strpos($form_message, '[html]') !== false)
847 {
848 $parts = preg_split('~(\[/code\]|\[code(?:=[^\]]+)?\])~i', $form_message, -1, PREG_SPLIT_DELIM_CAPTURE);
849 for ($i = 0, $n = count($parts); $i < $n; $i++)
850 {
851 // It goes 0 = outside, 1 = begin tag, 2 = inside, 3 = close tag, repeat.
852 if ($i % 4 == 0)
853 $parts[$i] = preg_replace('~\[html\](.+?)\[/html\]~ise', '\'[html]\' . preg_replace(\'~<br\s?/?' . '>~i\', \'&lt;br /&gt;<br />\', \'$1\') . \'[/html]\'', $parts[$i]);
854 }
855 $form_message = implode('', $parts);
856 }
857
858 $form_message = preg_replace('~<br ?/?' . '>~i', "\n", $form_message);
859
860 // Remove any nested quotes, if necessary.
861 if (!empty($modSettings['removeNestedQuotes']))
862 $form_message = preg_replace(array('~\n?\[quote.*?\].+?\[/quote\]\n?~is', '~^\n~', '~\[/quote\]~'), '', $form_message);
863
864 // Add a quote string on the front and end.
865 $form_message = '[quote author=' . $mname . ' link=topic=' . $topic . '.msg' . (int) $_REQUEST['quote'] . '#msg' . (int) $_REQUEST['quote'] . ' date=' . $mdate . ']' . "\n" . rtrim($form_message) . "\n" . '[/quote]';
866 }
867 // Posting a reply without a quote?
868 elseif (!empty($topic) && empty($_REQUEST['quote']))
869 {
870 // Get the first message's subject.
871 $form_subject = $first_subject;
872
873 // Add 'Re: ' to the front of the subject.
874 if (trim($context['response_prefix']) != '' && $form_subject != '' && $smcFunc['strpos']($form_subject, trim($context['response_prefix'])) !== 0)
875 $form_subject = $context['response_prefix'] . $form_subject;
876
877 // Censor the subject.
878 censorText($form_subject);
879
880 $form_message = '';
881 }
882 else
883 {
884 $form_subject = isset($_GET['subject']) ? $_GET['subject'] : '';
885 $form_message = '';
886 }
887 }
888
889 // !!! This won't work if you're posting an event.
890 if (allowedTo('post_attachment') || allowedTo('post_unapproved_attachments'))
891 {
892 if (empty($_SESSION['temp_attachments']))
893 $_SESSION['temp_attachments'] = array();
894
895 if (!empty($modSettings['currentAttachmentUploadDir']))
896 {
897 if (!is_array($modSettings['attachmentUploadDir']))
898 $modSettings['attachmentUploadDir'] = unserialize($modSettings['attachmentUploadDir']);
899
900 // Just use the current path for temp files.
901 $current_attach_dir = $modSettings['attachmentUploadDir'][$modSettings['currentAttachmentUploadDir']];
902 }
903 else
904 $current_attach_dir = $modSettings['attachmentUploadDir'];
905
906 // If this isn't a new post, check the current attachments.
907 if (isset($_REQUEST['msg']))
908 {
909 $request = $smcFunc['db_query']('', '
910 SELECT COUNT(*), SUM(size)
911 FROM {db_prefix}attachments
912 WHERE id_msg = {int:id_msg}
913 AND attachment_type = {int:attachment_type}',
914 array(
915 'id_msg' => (int) $_REQUEST['msg'],
916 'attachment_type' => 0,
917 )
918 );
919 list ($quantity, $total_size) = $smcFunc['db_fetch_row']($request);
920 $smcFunc['db_free_result']($request);
921 }
922 else
923 {
924 $quantity = 0;
925 $total_size = 0;
926 }
927
928 $temp_start = 0;
929
930 if (!empty($_SESSION['temp_attachments']))
931 {
932 if ($context['current_action'] != 'post2' || !empty($_POST['from_qr']))
933 {
934 $context['post_error']['messages'][] = $txt['error_temp_attachments'];
935 $context['error_type'] = 'minor';
936 }
937
938 foreach ($_SESSION['temp_attachments'] as $attachID => $name)
939 {
940 $temp_start++;
941
942 if (preg_match('~^post_tmp_' . $user_info['id'] . '_\d+$~', $attachID) == 0)
943 {
944 unset($_SESSION['temp_attachments'][$attachID]);
945 continue;
946 }
947
948 if (!empty($_POST['attach_del']) && !in_array($attachID, $_POST['attach_del']))
949 {
950 $deleted_attachments = true;
951 unset($_SESSION['temp_attachments'][$attachID]);
952 @unlink($current_attach_dir . '/' . $attachID);
953 continue;
954 }
955
956 $quantity++;
957 $total_size += filesize($current_attach_dir . '/' . $attachID);
958
959 $context['current_attachments'][] = array(
960 'name' => htmlspecialchars($name),
961 'id' => $attachID,
962 'approved' => 1,
963 );
964 }
965 }
966
967 if (!empty($_POST['attach_del']))
968 {
969 $del_temp = array();
970 foreach ($_POST['attach_del'] as $i => $dummy)
971 $del_temp[$i] = (int) $dummy;
972
973 foreach ($context['current_attachments'] as $k => $dummy)
974 if (!in_array($dummy['id'], $del_temp))
975 {
976 $context['current_attachments'][$k]['unchecked'] = true;
977 $deleted_attachments = !isset($deleted_attachments) || is_bool($deleted_attachments) ? 1 : $deleted_attachments + 1;
978 $quantity--;
979 }
980 }
981
982 if (!empty($_FILES['attachment']))
983 foreach ($_FILES['attachment']['tmp_name'] as $n => $dummy)
984 {
985 if ($_FILES['attachment']['name'][$n] == '')
986 continue;
987
988 if (!is_uploaded_file($_FILES['attachment']['tmp_name'][$n]) || (@ini_get('open_basedir') == '' && !file_exists($_FILES['attachment']['tmp_name'][$n])))
989 fatal_lang_error('attach_timeout', 'critical');
990
991 if (!empty($modSettings['attachmentSizeLimit']) && $_FILES['attachment']['size'][$n] > $modSettings['attachmentSizeLimit'] * 1024)
992 fatal_lang_error('file_too_big', false, array($modSettings['attachmentSizeLimit']));
993
994 $quantity++;
995 if (!empty($modSettings['attachmentNumPerPostLimit']) && $quantity > $modSettings['attachmentNumPerPostLimit'])
996 fatal_lang_error('attachments_limit_per_post', false, array($modSettings['attachmentNumPerPostLimit']));
997
998 $total_size += $_FILES['attachment']['size'][$n];
999 if (!empty($modSettings['attachmentPostLimit']) && $total_size > $modSettings['attachmentPostLimit'] * 1024)
1000 fatal_lang_error('file_too_big', false, array($modSettings['attachmentPostLimit']));
1001
1002 if (!empty($modSettings['attachmentCheckExtensions']))
1003 {
1004 if (!in_array(strtolower(substr(strrchr($_FILES['attachment']['name'][$n], '.'), 1)), explode(',', strtolower($modSettings['attachmentExtensions']))))
1005 fatal_error($_FILES['attachment']['name'][$n] . '.<br />' . $txt['cant_upload_type'] . ' ' . $modSettings['attachmentExtensions'] . '.', false);
1006 }
1007
1008 if (!empty($modSettings['attachmentDirSizeLimit']))
1009 {
1010 // Make sure the directory isn't full.
1011 $dirSize = 0;
1012 $dir = @opendir($current_attach_dir) or fatal_lang_error('cant_access_upload_path', 'critical');
1013 while ($file = readdir($dir))
1014 {
1015 if ($file == '.' || $file == '..')
1016 continue;
1017
1018 if (preg_match('~^post_tmp_\d+_\d+$~', $file) != 0)
1019 {
1020 // Temp file is more than 5 hours old!
1021 if (filemtime($current_attach_dir . '/' . $file) < time() - 18000)
1022 @unlink($current_attach_dir . '/' . $file);
1023 continue;
1024 }
1025
1026 $dirSize += filesize($current_attach_dir . '/' . $file);
1027 }
1028 closedir($dir);
1029
1030 // Too big! Maybe you could zip it or something...
1031 if ($_FILES['attachment']['size'][$n] + $dirSize > $modSettings['attachmentDirSizeLimit'] * 1024)
1032 fatal_lang_error('ran_out_of_space');
1033 }
1034
1035 if (!is_writable($current_attach_dir))
1036 fatal_lang_error('attachments_no_write', 'critical');
1037
1038 $attachID = 'post_tmp_' . $user_info['id'] . '_' . $temp_start++;
1039 $_SESSION['temp_attachments'][$attachID] = basename($_FILES['attachment']['name'][$n]);
1040 $context['current_attachments'][] = array(
1041 'name' => htmlspecialchars(basename($_FILES['attachment']['name'][$n])),
1042 'id' => $attachID,
1043 'approved' => 1,
1044 );
1045
1046 $destName = $current_attach_dir . '/' . $attachID;
1047
1048 if (!move_uploaded_file($_FILES['attachment']['tmp_name'][$n], $destName))
1049 fatal_lang_error('attach_timeout', 'critical');
1050 @chmod($destName, 0644);
1051 }
1052 }
1053
1054 // If we are coming here to make a reply, and someone has already replied... make a special warning message.
1055 if (isset($newRepliesError))
1056 {
1057 $context['post_error']['messages'][] = $newRepliesError == 1 ? $txt['error_new_reply'] : $txt['error_new_replies'];
1058 $context['error_type'] = 'minor';
1059 }
1060
1061 if (isset($oldTopicError))
1062 {
1063 $context['post_error']['messages'][] = sprintf($txt['error_old_topic'], $modSettings['oldTopicDays']);
1064 $context['error_type'] = 'minor';
1065 }
1066
1067 // What are you doing? Posting a poll, modifying, previewing, new post, or reply...
1068 if (isset($_REQUEST['poll']))
1069 $context['page_title'] = $txt['new_poll'];
1070 elseif ($context['make_event'])
1071 $context['page_title'] = $context['event']['id'] == -1 ? $txt['calendar_post_event'] : $txt['calendar_edit'];
1072 elseif (isset($_REQUEST['msg']))
1073 $context['page_title'] = $txt['modify_msg'];
1074 elseif (isset($_REQUEST['subject'], $context['preview_subject']))
1075 $context['page_title'] = $txt['preview'] . ' - ' . strip_tags($context['preview_subject']);
1076 elseif (empty($topic))
1077 $context['page_title'] = $txt['start_new_topic'];
1078 else
1079 $context['page_title'] = $txt['post_reply'];
1080
1081 // Build the link tree.
1082 if (empty($topic))
1083 $context['linktree'][] = array(
1084 'name' => '<em>' . $txt['start_new_topic'] . '</em>'
1085 );
1086 else
1087 $context['linktree'][] = array(
1088 'url' => $scripturl . '?topic=' . $topic . '.' . $_REQUEST['start'],
1089 'name' => $form_subject,
1090 'extra_before' => '<span' . ($settings['linktree_inline'] ? ' class="smalltext"' : '') . '><strong class="nav">' . $context['page_title'] . ' ( </strong></span>',
1091 'extra_after' => '<span' . ($settings['linktree_inline'] ? ' class="smalltext"' : '') . '><strong class="nav"> )</strong></span>'
1092 );
1093
1094 // Give wireless a linktree url to the post screen, so that they can switch to full version.
1095 if (WIRELESS)
1096 $context['linktree'][count($context['linktree']) - 1]['url'] = $scripturl . '?action=post;' . (!empty($topic) ? 'topic=' . $topic : 'board=' . $board) . '.' . $_REQUEST['start'] . (isset($_REQUEST['msg']) ? ';msg=' . (int) $_REQUEST['msg'] . ';' . $context['session_var'] . '=' . $context['session_id'] : '');
1097
1098 // If they've unchecked an attachment, they may still want to attach that many more files, but don't allow more than num_allowed_attachments.
1099 // !!! This won't work if you're posting an event.
1100 $context['num_allowed_attachments'] = empty($modSettings['attachmentNumPerPostLimit']) ? 50 : min($modSettings['attachmentNumPerPostLimit'] - count($context['current_attachments']) + (isset($deleted_attachments) ? $deleted_attachments : 0), $modSettings['attachmentNumPerPostLimit']);
1101 $context['can_post_attachment'] = !empty($modSettings['attachmentEnable']) && $modSettings['attachmentEnable'] == 1 && (allowedTo('post_attachment') || ($modSettings['postmod_active'] && allowedTo('post_unapproved_attachments'))) && $context['num_allowed_attachments'] > 0;
1102 $context['can_post_attachment_unapproved'] = allowedTo('post_attachment');
1103
1104 $context['subject'] = addcslashes($form_subject, '"');
1105 $context['message'] = str_replace(array('"', '<', '>', '&nbsp;'), array('&quot;', '&lt;', '&gt;', ' '), $form_message);
1106
1107 // Needed for the editor and message icons.
1108 require_once($sourcedir . '/Subs-Editor.php');
1109
1110 // Now create the editor.
1111 $editorOptions = array(
1112 'id' => 'message',
1113 'value' => $context['message'],
1114 'labels' => array(
1115 'post_button' => $context['submit_label'],
1116 ),
1117 // add height and width for the editor
1118 'height' => '175px',
1119 'width' => '100%',
1120 // We do XML preview here.
1121 'preview_type' => 2,
1122 );
1123 create_control_richedit($editorOptions);
1124
1125 // Store the ID.
1126 $context['post_box_name'] = $editorOptions['id'];
1127
1128 $context['attached'] = '';
1129 $context['make_poll'] = isset($_REQUEST['poll']);
1130
1131 // Message icons - customized icons are off?
1132 $context['icons'] = getMessageIcons($board);
1133
1134 if (!empty($context['icons']))
1135 $context['icons'][count($context['icons']) - 1]['is_last'] = true;
1136
1137 $context['icon_url'] = '';
1138 for ($i = 0, $n = count($context['icons']); $i < $n; $i++)
1139 {
1140 $context['icons'][$i]['selected'] = $context['icon'] == $context['icons'][$i]['value'];
1141 if ($context['icons'][$i]['selected'])
1142 $context['icon_url'] = $context['icons'][$i]['url'];
1143 }
1144 if (empty($context['icon_url']))
1145 {
1146 $context['icon_url'] = $settings[file_exists($settings['theme_dir'] . '/images/post/' . $context['icon'] . '.gif') ? 'images_url' : 'default_images_url'] . '/post/' . $context['icon'] . '.gif';
1147 array_unshift($context['icons'], array(
1148 'value' => $context['icon'],
1149 'name' => $txt['current_icon'],
1150 'url' => $context['icon_url'],
1151 'is_last' => empty($context['icons']),
1152 'selected' => true,
1153 ));
1154 }
1155
1156 if (!empty($topic) && !empty($modSettings['topicSummaryPosts']))
1157 getTopic();
1158
1159 // If the user can post attachments prepare the warning labels.
1160 if ($context['can_post_attachment'])
1161 {
1162 $context['allowed_extensions'] = strtr($modSettings['attachmentExtensions'], array(',' => ', '));
1163 $context['attachment_restrictions'] = array();
1164 $attachmentRestrictionTypes = array('attachmentNumPerPostLimit', 'attachmentPostLimit', 'attachmentSizeLimit');
1165 foreach ($attachmentRestrictionTypes as $type)
1166 if (!empty($modSettings[$type]))
1167 $context['attachment_restrictions'][] = sprintf($txt['attach_restrict_' . $type], $modSettings[$type]);
1168 }
1169
1170 $context['back_to_topic'] = isset($_REQUEST['goback']) || (isset($_REQUEST['msg']) && !isset($_REQUEST['subject']));
1171 $context['show_additional_options'] = !empty($_POST['additional_options']) || !empty($_SESSION['temp_attachments']) || !empty($deleted_attachments);
1172
1173 $context['is_new_topic'] = empty($topic);
1174 $context['is_new_post'] = !isset($_REQUEST['msg']);
1175 $context['is_first_post'] = $context['is_new_topic'] || (isset($_REQUEST['msg']) && $_REQUEST['msg'] == $id_first_msg);
1176
1177 // Do we need to show the visual verification image?
1178 $context['require_verification'] = !$user_info['is_mod'] && !$user_info['is_admin'] && !empty($modSettings['posts_require_captcha']) && ($user_info['posts'] < $modSettings['posts_require_captcha'] || ($user_info['is_guest'] && $modSettings['posts_require_captcha'] == -1));
1179 if ($context['require_verification'])
1180 {
1181 require_once($sourcedir . '/Subs-Editor.php');
1182 $verificationOptions = array(
1183 'id' => 'post',
1184 );
1185 $context['require_verification'] = create_control_verification($verificationOptions);
1186 $context['visual_verification_id'] = $verificationOptions['id'];
1187 }
1188
1189 // If they came from quick reply, and have to enter verification details, give them some notice.
1190 if (!empty($_REQUEST['from_qr']) && !empty($context['require_verification']))
1191 {
1192 $context['post_error']['messages'][] = $txt['enter_verification_details'];
1193 $context['error_type'] = 'minor';
1194 }
1195
1196 // WYSIWYG only works if BBC is enabled
1197 $modSettings['disable_wysiwyg'] = !empty($modSettings['disable_wysiwyg']) || empty($modSettings['enableBBC']);
1198
1199 // Register this form in the session variables.
1200 checkSubmitOnce('register');
1201
1202 // Finally, load the template.
1203 if (WIRELESS && WIRELESS_PROTOCOL != 'wap')
1204 $context['sub_template'] = WIRELESS_PROTOCOL . '_post';
1205 elseif (!isset($_REQUEST['xml']))
1206 loadTemplate('Post');
1207 }
1208
1209 function Post2()
1210 {
1211 global $board, $topic, $txt, $modSettings, $sourcedir, $context;
1212 global $user_info, $board_info, $options, $smcFunc;
1213
1214 // Sneaking off, are we?
1215 if (empty($_POST) && empty($topic))
1216 redirectexit('action=post;board=' . $board . '.0');
1217 elseif (empty($_POST) && !empty($topic))
1218 redirectexit('action=post;topic=' . $topic . '.0');
1219
1220 // No need!
1221 $context['robot_no_index'] = true;
1222
1223 // If we came from WYSIWYG then turn it back into BBC regardless.
1224 if (!empty($_REQUEST['message_mode']) && isset($_REQUEST['message']))
1225 {
1226 require_once($sourcedir . '/Subs-Editor.php');
1227
1228 $_REQUEST['message'] = html_to_bbc($_REQUEST['message']);
1229
1230 // We need to unhtml it now as it gets done shortly.
1231 $_REQUEST['message'] = un_htmlspecialchars($_REQUEST['message']);
1232
1233 // We need this for everything else.
1234 $_POST['message'] = $_REQUEST['message'];
1235 }
1236
1237 // Previewing? Go back to start.
1238 if (isset($_REQUEST['preview']))
1239 return Post();
1240
1241 // Prevent double submission of this form.
1242 checkSubmitOnce('check');
1243
1244 // No errors as yet.
1245 $post_errors = array();
1246
1247 // If the session has timed out, let the user re-submit their form.
1248 if (checkSession('post', '', false) != '')
1249 $post_errors[] = 'session_timeout';
1250
1251 // Wrong verification code?
1252 if (!$user_info['is_admin'] && !$user_info['is_mod'] && !empty($modSettings['posts_require_captcha']) && ($user_info['posts'] < $modSettings['posts_require_captcha'] || ($user_info['is_guest'] && $modSettings['posts_require_captcha'] == -1)))
1253 {
1254 require_once($sourcedir . '/Subs-Editor.php');
1255 $verificationOptions = array(
1256 'id' => 'post',
1257 );
1258 $context['require_verification'] = create_control_verification($verificationOptions, true);
1259 if (is_array($context['require_verification']))
1260 $post_errors = array_merge($post_errors, $context['require_verification']);
1261 }
1262
1263 require_once($sourcedir . '/Subs-Post.php');
1264 loadLanguage('Post');
1265
1266 // If this isn't a new topic load the topic info that we need.
1267 if (!empty($topic))
1268 {
1269 $request = $smcFunc['db_query']('', '
1270 SELECT locked, is_sticky, id_poll, approved, id_first_msg, id_last_msg, id_member_started, id_board
1271 FROM {db_prefix}topics
1272 WHERE id_topic = {int:current_topic}
1273 LIMIT 1',
1274 array(
1275 'current_topic' => $topic,
1276 )
1277 );
1278 $topic_info = $smcFunc['db_fetch_assoc']($request);
1279 $smcFunc['db_free_result']($request);
1280
1281 // Though the topic should be there, it might have vanished.
1282 if (!is_array($topic_info))
1283 fatal_lang_error('topic_doesnt_exist');
1284
1285 // Did this topic suddenly move? Just checking...
1286 if ($topic_info['id_board'] != $board)
1287 fatal_lang_error('not_a_topic');
1288 }
1289
1290 // Replying to a topic?
1291 if (!empty($topic) && !isset($_REQUEST['msg']))
1292 {
1293 // Don't allow a post if it's locked.
1294 if ($topic_info['locked'] != 0 && !allowedTo('moderate_board'))
1295 fatal_lang_error('topic_locked', false);
1296
1297 // Sorry, multiple polls aren't allowed... yet. You should stop giving me ideas :P.
1298 if (isset($_REQUEST['poll']) && $topic_info['id_poll'] > 0)
1299 unset($_REQUEST['poll']);
1300
1301 // Do the permissions and approval stuff...
1302 $becomesApproved = true;
1303 if ($topic_info['id_member_started'] != $user_info['id'])
1304 {
1305 if ($modSettings['postmod_active'] && allowedTo('post_unapproved_replies_any') && !allowedTo('post_reply_any'))
1306 $becomesApproved = false;
1307 else
1308 isAllowedTo('post_reply_any');
1309 }
1310 elseif (!allowedTo('post_reply_any'))
1311 {
1312 if ($modSettings['postmod_active'] && allowedTo('post_unapproved_replies_own') && !allowedTo('post_reply_own'))
1313 $becomesApproved = false;
1314 else
1315 isAllowedTo('post_reply_own');
1316 }
1317
1318 if (isset($_POST['lock']))
1319 {
1320 // Nothing is changed to the lock.
1321 if ((empty($topic_info['locked']) && empty($_POST['lock'])) || (!empty($_POST['lock']) && !empty($topic_info['locked'])))
1322 unset($_POST['lock']);
1323 // You're have no permission to lock this topic.
1324 elseif (!allowedTo(array('lock_any', 'lock_own')) || (!allowedTo('lock_any') && $user_info['id'] != $topic_info['id_member_started']))
1325 unset($_POST['lock']);
1326 // You are allowed to (un)lock your own topic only.
1327 elseif (!allowedTo('lock_any'))
1328 {
1329 // You cannot override a moderator lock.
1330 if ($topic_info['locked'] == 1)
1331 unset($_POST['lock']);
1332 else
1333 $_POST['lock'] = empty($_POST['lock']) ? 0 : 2;
1334 }
1335 // Hail mighty moderator, (un)lock this topic immediately.
1336 else
1337 $_POST['lock'] = empty($_POST['lock']) ? 0 : 1;
1338 }
1339
1340 // So you wanna (un)sticky this...let's see.
1341 if (isset($_POST['sticky']) && (empty($modSettings['enableStickyTopics']) || $_POST['sticky'] == $topic_info['is_sticky'] || !allowedTo('make_sticky')))
1342 unset($_POST['sticky']);
1343
1344 // If the number of replies has changed, if the setting is enabled, go back to Post() - which handles the error.
1345 if (empty($options['no_new_reply_warning']) && isset($_POST['last_msg']) && $topic_info['id_last_msg'] > $_POST['last_msg'])
1346 {
1347 $_REQUEST['preview'] = true;
1348 return Post();
1349 }
1350
1351 $posterIsGuest = $user_info['is_guest'];
1352 }
1353 // Posting a new topic.
1354 elseif (empty($topic))
1355 {
1356 // Now don't be silly, new topics will get their own id_msg soon enough.
1357 unset($_REQUEST['msg'], $_POST['msg'], $_GET['msg']);
1358
1359 // Do like, the permissions, for safety and stuff...
1360 $becomesApproved = true;
1361 if ($modSettings['postmod_active'] && !allowedTo('post_new') && allowedTo('post_unapproved_topics'))
1362 $becomesApproved = false;
1363 else
1364 isAllowedTo('post_new');
1365
1366 if (isset($_POST['lock']))
1367 {
1368 // New topics are by default not locked.
1369 if (empty($_POST['lock']))
1370 unset($_POST['lock']);
1371 // Besides, you need permission.
1372 elseif (!allowedTo(array('lock_any', 'lock_own')))
1373 unset($_POST['lock']);
1374 // A moderator-lock (1) can override a user-lock (2).
1375 else
1376 $_POST['lock'] = allowedTo('lock_any') ? 1 : 2;
1377 }
1378
1379 if (isset($_POST['sticky']) && (empty($modSettings['enableStickyTopics']) || empty($_POST['sticky']) || !allowedTo('make_sticky')))
1380 unset($_POST['sticky']);
1381
1382 $posterIsGuest = $user_info['is_guest'];
1383 }
1384 // Modifying an existing message?
1385 elseif (isset($_REQUEST['msg']) && !empty($topic))
1386 {
1387 $_REQUEST['msg'] = (int) $_REQUEST['msg'];
1388
1389 $request = $smcFunc['db_query']('', '
1390 SELECT id_member, poster_name, poster_email, poster_time, approved
1391 FROM {db_prefix}messages
1392 WHERE id_msg = {int:id_msg}
1393 LIMIT 1',
1394 array(
1395 'id_msg' => $_REQUEST['msg'],
1396 )
1397 );
1398 if ($smcFunc['db_num_rows']($request) == 0)
1399 fatal_lang_error('cant_find_messages', false);
1400 $row = $smcFunc['db_fetch_assoc']($request);
1401 $smcFunc['db_free_result']($request);
1402
1403 if (!empty($topic_info['locked']) && !allowedTo('moderate_board'))
1404 fatal_lang_error('topic_locked', false);
1405
1406 if (isset($_POST['lock']))
1407 {
1408 // Nothing changes to the lock status.
1409 if ((empty($_POST['lock']) && empty($topic_info['locked'])) || (!empty($_POST['lock']) && !empty($topic_info['locked'])))
1410 unset($_POST['lock']);
1411 // You're simply not allowed to (un)lock this.
1412 elseif (!allowedTo(array('lock_any', 'lock_own')) || (!allowedTo('lock_any') && $user_info['id'] != $topic_info['id_member_started']))
1413 unset($_POST['lock']);
1414 // You're only allowed to lock your own topics.
1415 elseif (!allowedTo('lock_any'))
1416 {
1417 // You're not allowed to break a moderator's lock.
1418 if ($topic_info['locked'] == 1)
1419 unset($_POST['lock']);
1420 // Lock it with a soft lock or unlock it.
1421 else
1422 $_POST['lock'] = empty($_POST['lock']) ? 0 : 2;
1423 }
1424 // You must be the moderator.
1425 else
1426 $_POST['lock'] = empty($_POST['lock']) ? 0 : 1;
1427 }
1428
1429 // Change the sticky status of this topic?
1430 if (isset($_POST['sticky']) && (!allowedTo('make_sticky') || $_POST['sticky'] == $topic_info['is_sticky']))
1431 unset($_POST['sticky']);
1432
1433 if ($row['id_member'] == $user_info['id'] && !allowedTo('modify_any'))
1434 {
1435 if ((!$modSettings['postmod_active'] || $row['approved']) && !empty($modSettings['edit_disable_time']) && $row['poster_time'] + ($modSettings['edit_disable_time'] + 5) * 60 < time())
1436 fatal_lang_error('modify_post_time_passed', false);
1437 elseif ($topic_info['id_member_started'] == $user_info['id'] && !allowedTo('modify_own'))
1438 isAllowedTo('modify_replies');
1439 else
1440 isAllowedTo('modify_own');
1441 }
1442 elseif ($topic_info['id_member_started'] == $user_info['id'] && !allowedTo('modify_any'))
1443 {
1444 isAllowedTo('modify_replies');
1445
1446 // If you're modifying a reply, I say it better be logged...
1447 $moderationAction = true;
1448 }
1449 else
1450 {
1451 isAllowedTo('modify_any');
1452
1453 // Log it, assuming you're not modifying your own post.
1454 if ($row['id_member'] != $user_info['id'])
1455 $moderationAction = true;
1456 }
1457
1458 $posterIsGuest = empty($row['id_member']);
1459
1460 // Can they approve it?
1461 $can_approve = allowedTo('approve_posts');
1462 $becomesApproved = $modSettings['postmod_active'] ? ($can_approve && !$row['approved'] ? (!empty($_REQUEST['approve']) ? 1 : 0) : $row['approved']) : 1;
1463 $approve_has_changed = $row['approved'] != $becomesApproved;
1464
1465 if (!allowedTo('moderate_forum') || !$posterIsGuest)
1466 {
1467 $_POST['guestname'] = $row['poster_name'];
1468 $_POST['email'] = $row['poster_email'];
1469 }
1470 }
1471
1472 // If the poster is a guest evaluate the legality of name and email.
1473 if ($posterIsGuest)
1474 {
1475 $_POST['guestname'] = !isset($_POST['guestname']) ? '' : trim($_POST['guestname']);
1476 $_POST['email'] = !isset($_POST['email']) ? '' : trim($_POST['email']);
1477
1478 if ($_POST['guestname'] == '' || $_POST['guestname'] == '_')
1479 $post_errors[] = 'no_name';
1480 if ($smcFunc['strlen']($_POST['guestname']) > 25)
1481 $post_errors[] = 'long_name';
1482
1483 if (empty($modSettings['guest_post_no_email']))
1484 {
1485 // Only check if they changed it!
1486 if (!isset($row) || $row['poster_email'] != $_POST['email'])
1487 {
1488 if (!allowedTo('moderate_forum') && (!isset($_POST['email']) || $_POST['email'] == ''))
1489 $post_errors[] = 'no_email';
1490 if (!allowedTo('moderate_forum') && preg_match('~^[0-9A-Za-z=_+\-/][0-9A-Za-z=_\'+\-/\.]*@[\w\-]+(\.[\w\-]+)*(\.[\w]{2,6})$~', $_POST['email']) == 0)
1491 $post_errors[] = 'bad_email';
1492 }
1493
1494 // Now make sure this email address is not banned from posting.
1495 isBannedEmail($_POST['email'], 'cannot_post', sprintf($txt['you_are_post_banned'], $txt['guest_title']));
1496 }
1497
1498 // In case they are making multiple posts this visit, help them along by storing their name.
1499 if (empty($post_errors))
1500 {
1501 $_SESSION['guest_name'] = $_POST['guestname'];
1502 $_SESSION['guest_email'] = $_POST['email'];
1503 }
1504 }
1505
1506 // Check the subject and message.
1507 if (!isset($_POST['subject']) || $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['subject'])) === '')
1508 $post_errors[] = 'no_subject';
1509 if (!isset($_POST['message']) || $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['message']), ENT_QUOTES) === '')
1510 $post_errors[] = 'no_message';
1511 elseif (!empty($modSettings['max_messageLength']) && $smcFunc['strlen']($_POST['message']) > $modSettings['max_messageLength'])
1512 $post_errors[] = 'long_message';
1513 else
1514 {
1515 // Prepare the message a bit for some additional testing.
1516 $_POST['message'] = $smcFunc['htmlspecialchars']($_POST['message'], ENT_QUOTES);
1517
1518 // Preparse code. (Zef)
1519 if ($user_info['is_guest'])
1520 $user_info['name'] = $_POST['guestname'];
1521 preparsecode($_POST['message']);
1522
1523 // Let's see if there's still some content left without the tags.
1524 if ($smcFunc['htmltrim'](strip_tags(parse_bbc($_POST['message'], false), '<img>')) === '' && (!allowedTo('admin_forum') || strpos($_POST['message'], '[html]') === false))
1525 $post_errors[] = 'no_message';
1526 }
1527 if (isset($_POST['calendar']) && !isset($_REQUEST['deleteevent']) && $smcFunc['htmltrim']($_POST['evtitle']) === '')
1528 $post_errors[] = 'no_event';
1529 // You are not!
1530 if (isset($_POST['message']) && strtolower($_POST['message']) == 'i am the administrator.' && !$user_info['is_admin'])
1531 fatal_error('Knave! Masquerader! Charlatan!', false);
1532
1533 // Validate the poll...
1534 if (isset($_REQUEST['poll']) && $modSettings['pollMode'] == '1')
1535 {
1536 if (!empty($topic) && !isset($_REQUEST['msg']))
1537 fatal_lang_error('no_access', false);
1538
1539 // This is a new topic... so it's a new poll.
1540 if (empty($topic))
1541 isAllowedTo('poll_post');
1542 // Can you add to your own topics?
1543 elseif ($user_info['id'] == $topic_info['id_member_started'] && !allowedTo('poll_add_any'))
1544 isAllowedTo('poll_add_own');
1545 // Can you add polls to any topic, then?
1546 else
1547 isAllowedTo('poll_add_any');
1548
1549 if (!isset($_POST['question']) || trim($_POST['question']) == '')
1550 $post_errors[] = 'no_question';
1551
1552 $_POST['options'] = empty($_POST['options']) ? array() : htmltrim__recursive($_POST['options']);
1553
1554 // Get rid of empty ones.
1555 foreach ($_POST['options'] as $k => $option)
1556 if ($option == '')
1557 unset($_POST['options'][$k], $_POST['options'][$k]);
1558
1559 // What are you going to vote between with one choice?!?
1560 if (count($_POST['options']) < 2)
1561 $post_errors[] = 'poll_few';
1562 }
1563
1564 if ($posterIsGuest)
1565 {
1566 // If user is a guest, make sure the chosen name isn't taken.
1567 require_once($sourcedir . '/Subs-Members.php');
1568 if (isReservedName($_POST['guestname'], 0, true, false) && (!isset($row['poster_name']) || $_POST['guestname'] != $row['poster_name']))
1569 $post_errors[] = 'bad_name';
1570 }
1571 // If the user isn't a guest, get his or her name and email.
1572 elseif (!isset($_REQUEST['msg']))
1573 {
1574 $_POST['guestname'] = $user_info['username'];
1575 $_POST['email'] = $user_info['email'];
1576 }
1577
1578 // Any mistakes?
1579 if (!empty($post_errors))
1580 {
1581 loadLanguage('Errors');
1582 // Previewing.
1583 $_REQUEST['preview'] = true;
1584
1585 $context['post_error'] = array('messages' => array());
1586 foreach ($post_errors as $post_error)
1587 {
1588 $context['post_error'][$post_error] = true;
1589 if ($post_error == 'long_message')
1590 $txt['error_' . $post_error] = sprintf($txt['error_' . $post_error], $modSettings['max_messageLength']);
1591
1592 $context['post_error']['messages'][] = $txt['error_' . $post_error];
1593 }
1594
1595 return Post();
1596 }
1597
1598 // Make sure the user isn't spamming the board.
1599 if (!isset($_REQUEST['msg']))
1600 spamProtection('post');
1601
1602 // At about this point, we're posting and that's that.
1603 ignore_user_abort(true);
1604 @set_time_limit(300);
1605
1606 // Add special html entities to the subject, name, and email.
1607 $_POST['subject'] = strtr($smcFunc['htmlspecialchars']($_POST['subject']), array("\r" => '', "\n" => '', "\t" => ''));
1608 $_POST['guestname'] = htmlspecialchars($_POST['guestname']);
1609 $_POST['email'] = htmlspecialchars($_POST['email']);
1610
1611 // At this point, we want to make sure the subject isn't too long.
1612 if ($smcFunc['strlen']($_POST['subject']) > 100)
1613 $_POST['subject'] = $smcFunc['substr']($_POST['subject'], 0, 100);
1614
1615 // Make the poll...
1616 if (isset($_REQUEST['poll']))
1617 {
1618 // Make sure that the user has not entered a ridiculous number of options..
1619 if (empty($_POST['poll_max_votes']) || $_POST['poll_max_votes'] <= 0)
1620 $_POST['poll_max_votes'] = 1;
1621 elseif ($_POST['poll_max_votes'] > count($_POST['options']))
1622 $_POST['poll_max_votes'] = count($_POST['options']);
1623 else
1624 $_POST['poll_max_votes'] = (int) $_POST['poll_max_votes'];
1625
1626 $_POST['poll_expire'] = (int) $_POST['poll_expire'];
1627 $_POST['poll_expire'] = $_POST['poll_expire'] > 9999 ? 9999 : ($_POST['poll_expire'] < 0 ? 0 : $_POST['poll_expire']);
1628
1629 // Just set it to zero if it's not there..
1630 if (!isset($_POST['poll_hide']))
1631 $_POST['poll_hide'] = 0;
1632 else
1633 $_POST['poll_hide'] = (int) $_POST['poll_hide'];
1634 $_POST['poll_change_vote'] = isset($_POST['poll_change_vote']) ? 1 : 0;
1635
1636 $_POST['poll_guest_vote'] = isset($_POST['poll_guest_vote']) ? 1 : 0;
1637 // Make sure guests are actually allowed to vote generally.
1638 if ($_POST['poll_guest_vote'])
1639 {
1640 require_once($sourcedir . '/Subs-Members.php');
1641 $allowedVoteGroups = groupsAllowedTo('poll_vote', $board);
1642 if (!in_array(-1, $allowedVoteGroups['allowed']))
1643 $_POST['poll_guest_vote'] = 0;
1644 }
1645
1646 // If the user tries to set the poll too far in advance, don't let them.
1647 if (!empty($_POST['poll_expire']) && $_POST['poll_expire'] < 1)
1648 fatal_lang_error('poll_range_error', false);
1649 // Don't allow them to select option 2 for hidden results if it's not time limited.
1650 elseif (empty($_POST['poll_expire']) && $_POST['poll_hide'] == 2)
1651 $_POST['poll_hide'] = 1;
1652
1653 // Clean up the question and answers.
1654 $_POST['question'] = htmlspecialchars($_POST['question']);
1655 $_POST['question'] = $smcFunc['truncate']($_POST['question'], 255);
1656 $_POST['question'] = preg_replace('~&amp;#(\d{4,5}|[2-9]\d{2,4}|1[2-9]\d);~', '&#$1;', $_POST['question']);
1657 $_POST['options'] = htmlspecialchars__recursive($_POST['options']);
1658 }
1659
1660 // Check if they are trying to delete any current attachments....
1661 if (isset($_REQUEST['msg'], $_POST['attach_del']) && (allowedTo('post_attachment') || ($modSettings['postmod_active'] && allowedTo('post_unapproved_attachments'))))
1662 {
1663 $del_temp = array();
1664 foreach ($_POST['attach_del'] as $i => $dummy)
1665 $del_temp[$i] = (int) $dummy;
1666
1667 require_once($sourcedir . '/ManageAttachments.php');
1668 $attachmentQuery = array(
1669 'attachment_type' => 0,
1670 'id_msg' => (int) $_REQUEST['msg'],
1671 'not_id_attach' => $del_temp,
1672 );
1673 removeAttachments($attachmentQuery);
1674 }
1675
1676 // ...or attach a new file...
1677 if (isset($_FILES['attachment']['name']) || (!empty($_SESSION['temp_attachments']) && empty($_POST['from_qr'])))
1678 {
1679 // Verify they can post them!
1680 if (!$modSettings['postmod_active'] || !allowedTo('post_unapproved_attachments'))
1681 isAllowedTo('post_attachment');
1682
1683 // Make sure we're uploading to the right place.
1684 if (!empty($modSettings['currentAttachmentUploadDir']))
1685 {
1686 if (!is_array($modSettings['attachmentUploadDir']))
1687 $modSettings['attachmentUploadDir'] = unserialize($modSettings['attachmentUploadDir']);
1688
1689 // The current directory, of course!
1690 $current_attach_dir = $modSettings['attachmentUploadDir'][$modSettings['currentAttachmentUploadDir']];
1691 }
1692 else
1693 $current_attach_dir = $modSettings['attachmentUploadDir'];
1694
1695 // If this isn't a new post, check the current attachments.
1696 if (isset($_REQUEST['msg']))
1697 {
1698 $request = $smcFunc['db_query']('', '
1699 SELECT COUNT(*), SUM(size)
1700 FROM {db_prefix}attachments
1701 WHERE id_msg = {int:id_msg}
1702 AND attachment_type = {int:attachment_type}',
1703 array(
1704 'id_msg' => (int) $_REQUEST['msg'],
1705 'attachment_type' => 0,
1706 )
1707 );
1708 list ($quantity, $total_size) = $smcFunc['db_fetch_row']($request);
1709 $smcFunc['db_free_result']($request);
1710 }
1711 else
1712 {
1713 $quantity = 0;
1714 $total_size = 0;
1715 }
1716
1717 if (!empty($_SESSION['temp_attachments']))
1718 foreach ($_SESSION['temp_attachments'] as $attachID => $name)
1719 {
1720 if (preg_match('~^post_tmp_' . $user_info['id'] . '_\d+$~', $attachID) == 0)
1721 continue;
1722
1723 if (!empty($_POST['attach_del']) && !in_array($attachID, $_POST['attach_del']))
1724 {
1725 unset($_SESSION['temp_attachments'][$attachID]);
1726 @unlink($current_attach_dir . '/' . $attachID);
1727 continue;
1728 }
1729
1730 $_FILES['attachment']['tmp_name'][] = $attachID;
1731 $_FILES['attachment']['name'][] = $name;
1732 $_FILES['attachment']['size'][] = filesize($current_attach_dir . '/' . $attachID);
1733 list ($_FILES['attachment']['width'][], $_FILES['attachment']['height'][]) = @getimagesize($current_attach_dir . '/' . $attachID);
1734
1735 unset($_SESSION['temp_attachments'][$attachID]);
1736 }
1737
1738 if (!isset($_FILES['attachment']['name']))
1739 $_FILES['attachment']['tmp_name'] = array();
1740
1741 $attachIDs = array();
1742 foreach ($_FILES['attachment']['tmp_name'] as $n => $dummy)
1743 {
1744 if ($_FILES['attachment']['name'][$n] == '')
1745 continue;
1746
1747 // Have we reached the maximum number of files we are allowed?
1748 $quantity++;
1749 if (!empty($modSettings['attachmentNumPerPostLimit']) && $quantity > $modSettings['attachmentNumPerPostLimit'])
1750 {
1751 checkSubmitOnce('free');
1752 fatal_lang_error('attachments_limit_per_post', false, array($modSettings['attachmentNumPerPostLimit']));
1753 }
1754
1755 // Check the total upload size for this post...
1756 $total_size += $_FILES['attachment']['size'][$n];
1757 if (!empty($modSettings['attachmentPostLimit']) && $total_size > $modSettings['attachmentPostLimit'] * 1024)
1758 {
1759 checkSubmitOnce('free');
1760 fatal_lang_error('file_too_big', false, array($modSettings['attachmentPostLimit']));
1761 }
1762
1763 $attachmentOptions = array(
1764 'post' => isset($_REQUEST['msg']) ? $_REQUEST['msg'] : 0,
1765 'poster' => $user_info['id'],
1766 'name' => $_FILES['attachment']['name'][$n],
1767 'tmp_name' => $_FILES['attachment']['tmp_name'][$n],
1768 'size' => $_FILES['attachment']['size'][$n],
1769 'approved' => !$modSettings['postmod_active'] || allowedTo('post_attachment'),
1770 );
1771
1772 if (createAttachment($attachmentOptions))
1773 {
1774 $attachIDs[] = $attachmentOptions['id'];
1775 if (!empty($attachmentOptions['thumb']))
1776 $attachIDs[] = $attachmentOptions['thumb'];
1777 }
1778 else
1779 {
1780 if (in_array('could_not_upload', $attachmentOptions['errors']))
1781 {
1782 checkSubmitOnce('free');
1783 fatal_lang_error('attach_timeout', 'critical');
1784 }
1785 if (in_array('too_large', $attachmentOptions['errors']))
1786 {
1787 checkSubmitOnce('free');
1788 fatal_lang_error('file_too_big', false, array($modSettings['attachmentSizeLimit']));
1789 }
1790 if (in_array('bad_extension', $attachmentOptions['errors']))
1791 {
1792 checkSubmitOnce('free');
1793 fatal_error($attachmentOptions['name'] . '.<br />' . $txt['cant_upload_type'] . ' ' . $modSettings['attachmentExtensions'] . '.', false);
1794 }
1795 if (in_array('directory_full', $attachmentOptions['errors']))
1796 {
1797 checkSubmitOnce('free');
1798 fatal_lang_error('ran_out_of_space', 'critical');
1799 }
1800 if (in_array('bad_filename', $attachmentOptions['errors']))
1801 {
1802 checkSubmitOnce('free');
1803 fatal_error(basename($attachmentOptions['name']) . '.<br />' . $txt['restricted_filename'] . '.', 'critical');
1804 }
1805 if (in_array('taken_filename', $attachmentOptions['errors']))
1806 {
1807 checkSubmitOnce('free');
1808 fatal_lang_error('filename_exists');
1809 }
1810 if (in_array('bad_attachment', $attachmentOptions['errors']))
1811 {
1812 checkSubmitOnce('free');
1813 fatal_lang_error('bad_attachment');
1814 }
1815 }
1816 }
1817 }
1818
1819 // Make the poll...
1820 if (isset($_REQUEST['poll']))
1821 {
1822 // Create the poll.
1823 $smcFunc['db_insert']('',
1824 '{db_prefix}polls',
1825 array(
1826 'question' => 'string-255', 'hide_results' => 'int', 'max_votes' => 'int', 'expire_time' => 'int', 'id_member' => 'int',
1827 'poster_name' => 'string-255', 'change_vote' => 'int', 'guest_vote' => 'int'
1828 ),
1829 array(
1830 $_POST['question'], $_POST['poll_hide'], $_POST['poll_max_votes'], (empty($_POST['poll_expire']) ? 0 : time() + $_POST['poll_expire'] * 3600 * 24), $user_info['id'],
1831 $_POST['guestname'], $_POST['poll_change_vote'], $_POST['poll_guest_vote'],
1832 ),
1833 array('id_poll')
1834 );
1835 $id_poll = $smcFunc['db_insert_id']('{db_prefix}polls', 'id_poll');
1836
1837 // Create each answer choice.
1838 $i = 0;
1839 $pollOptions = array();
1840 foreach ($_POST['options'] as $option)
1841 {
1842 $pollOptions[] = array($id_poll, $i, $option);
1843 $i++;
1844 }
1845
1846 $smcFunc['db_insert']('insert',
1847 '{db_prefix}poll_choices',
1848 array('id_poll' => 'int', 'id_choice' => 'int', 'label' => 'string-255'),
1849 $pollOptions,
1850 array('id_poll', 'id_choice')
1851 );
1852 }
1853 else
1854 $id_poll = 0;
1855
1856 // Creating a new topic?
1857 $newTopic = empty($_REQUEST['msg']) && empty($topic);
1858
1859 $_POST['icon'] = !empty($attachIDs) && $_POST['icon'] == 'xx' ? 'clip' : $_POST['icon'];
1860
1861 // Collect all parameters for the creation or modification of a post.
1862 $msgOptions = array(
1863 'id' => empty($_REQUEST['msg']) ? 0 : (int) $_REQUEST['msg'],
1864 'subject' => $_POST['subject'],
1865 'body' => $_POST['message'],
1866 'icon' => preg_replace('~[\./\\\\*:"\'<>]~', '', $_POST['icon']),
1867 'smileys_enabled' => !isset($_POST['ns']),
1868 'attachments' => empty($attachIDs) ? array() : $attachIDs,
1869 'approved' => $becomesApproved,
1870 );
1871 $topicOptions = array(
1872 'id' => empty($topic) ? 0 : $topic,
1873 'board' => $board,
1874 'poll' => isset($_REQUEST['poll']) ? $id_poll : null,
1875 'lock_mode' => isset($_POST['lock']) ? (int) $_POST['lock'] : null,
1876 'sticky_mode' => isset($_POST['sticky']) && !empty($modSettings['enableStickyTopics']) ? (int) $_POST['sticky'] : null,
1877 'mark_as_read' => true,
1878 'is_approved' => !$modSettings['postmod_active'] || empty($topic) || !empty($board_info['cur_topic_approved']),
1879 );
1880 $posterOptions = array(
1881 'id' => $user_info['id'],
1882 'name' => $_POST['guestname'],
1883 'email' => $_POST['email'],
1884 'update_post_count' => !$user_info['is_guest'] && !isset($_REQUEST['msg']) && $board_info['posts_count'],
1885 );
1886
1887 // This is an already existing message. Edit it.
1888 if (!empty($_REQUEST['msg']))
1889 {
1890 // Have admins allowed people to hide their screwups?
1891 if (time() - $row['poster_time'] > $modSettings['edit_wait_time'] || $user_info['id'] != $row['id_member'])
1892 {
1893 $msgOptions['modify_time'] = time();
1894 $msgOptions['modify_name'] = $user_info['name'];
1895 }
1896
1897 // This will save some time...
1898 if (empty($approve_has_changed))
1899 unset($msgOptions['approved']);
1900
1901 modifyPost($msgOptions, $topicOptions, $posterOptions);
1902 }
1903 // This is a new topic or an already existing one. Save it.
1904 else
1905 {
1906 createPost($msgOptions, $topicOptions, $posterOptions);
1907
1908 if (isset($topicOptions['id']))
1909 $topic = $topicOptions['id'];
1910 }
1911
1912 // Editing or posting an event?
1913 if (isset($_POST['calendar']) && (!isset($_REQUEST['eventid']) || $_REQUEST['eventid'] == -1))
1914 {
1915 require_once($sourcedir . '/Subs-Calendar.php');
1916
1917 // Make sure they can link an event to this post.
1918 canLinkEvent();
1919
1920 // Insert the event.
1921 $eventOptions = array(
1922 'board' => $board,
1923 'topic' => $topic,
1924 'title' => $_POST['evtitle'],
1925 'member' => $user_info['id'],
1926 'start_date' => sprintf('%04d-%02d-%02d', $_POST['year'], $_POST['month'], $_POST['day']),
1927 'span' => isset($_POST['span']) && $_POST['span'] > 0 ? min((int) $modSettings['cal_maxspan'], (int) $_POST['span'] - 1) : 0,
1928 );
1929 insertEvent($eventOptions);
1930 }
1931 elseif (isset($_POST['calendar']))
1932 {
1933 $_REQUEST['eventid'] = (int) $_REQUEST['eventid'];
1934
1935 // Validate the post...
1936 require_once($sourcedir . '/Subs-Calendar.php');
1937 validateEventPost();
1938
1939 // If you're not allowed to edit any events, you have to be the poster.
1940 if (!allowedTo('calendar_edit_any'))
1941 {
1942 // Get the event's poster.
1943 $request = $smcFunc['db_query']('', '
1944 SELECT id_member
1945 FROM {db_prefix}calendar
1946 WHERE id_event = {int:id_event}',
1947 array(
1948 'id_event' => $_REQUEST['eventid'],
1949 )
1950 );
1951 $row2 = $smcFunc['db_fetch_assoc']($request);
1952 $smcFunc['db_free_result']($request);
1953
1954 // Silly hacker, Trix are for kids. ...probably trademarked somewhere, this is FAIR USE! (parody...)
1955 isAllowedTo('calendar_edit_' . ($row2['id_member'] == $user_info['id'] ? 'own' : 'any'));
1956 }
1957
1958 // Delete it?
1959 if (isset($_REQUEST['deleteevent']))
1960 $smcFunc['db_query']('', '
1961 DELETE FROM {db_prefix}calendar
1962 WHERE id_event = {int:id_event}',
1963 array(
1964 'id_event' => $_REQUEST['eventid'],
1965 )
1966 );
1967 // ... or just update it?
1968 else
1969 {
1970 $span = !empty($modSettings['cal_allowspan']) && !empty($_REQUEST['span']) ? min((int) $modSettings['cal_maxspan'], (int) $_REQUEST['span'] - 1) : 0;
1971 $start_time = mktime(0, 0, 0, (int) $_REQUEST['month'], (int) $_REQUEST['day'], (int) $_REQUEST['year']);
1972
1973 $smcFunc['db_query']('', '
1974 UPDATE {db_prefix}calendar
1975 SET end_date = {date:end_date},
1976 start_date = {date:start_date},
1977 title = {string:title}
1978 WHERE id_event = {int:id_event}',
1979 array(
1980 'end_date' => strftime('%Y-%m-%d', $start_time + $span * 86400),
1981 'start_date' => strftime('%Y-%m-%d', $start_time),
1982 'id_event' => $_REQUEST['eventid'],
1983 'title' => $smcFunc['htmlspecialchars']($_REQUEST['evtitle'], ENT_QUOTES),
1984 )
1985 );
1986 }
1987 updateSettings(array(
1988 'calendar_updated' => time(),
1989 ));
1990 }
1991
1992 // Marking read should be done even for editing messages....
1993 // Mark all the parents read. (since you just posted and they will be unread.)
1994 if (!$user_info['is_guest'] && !empty($board_info['parent_boards']))
1995 {
1996 $smcFunc['db_query']('', '
1997 UPDATE {db_prefix}log_boards
1998 SET id_msg = {int:id_msg}
1999 WHERE id_member = {int:current_member}
2000 AND id_board IN ({array_int:board_list})',
2001 array(
2002 'current_member' => $user_info['id'],
2003 'board_list' => array_keys($board_info['parent_boards']),
2004 'id_msg' => $modSettings['maxMsgID'],
2005 )
2006 );
2007 }
2008
2009 // Turn notification on or off. (note this just blows smoke if it's already on or off.)
2010 if (!empty($_POST['notify']) && allowedTo('mark_any_notify'))
2011 {
2012 $smcFunc['db_insert']('ignore',
2013 '{db_prefix}log_notify',
2014 array('id_member' => 'int', 'id_topic' => 'int', 'id_board' => 'int'),
2015 array($user_info['id'], $topic, 0),
2016 array('id_member', 'id_topic', 'id_board')
2017 );
2018 }
2019 elseif (!$newTopic)
2020 $smcFunc['db_query']('', '
2021 DELETE FROM {db_prefix}log_notify
2022 WHERE id_member = {int:current_member}
2023 AND id_topic = {int:current_topic}',
2024 array(
2025 'current_member' => $user_info['id'],
2026 'current_topic' => $topic,
2027 )
2028 );
2029
2030 // Log an act of moderation - modifying.
2031 if (!empty($moderationAction))
2032 logAction('modify', array('topic' => $topic, 'message' => (int) $_REQUEST['msg'], 'member' => $row['id_member'], 'board' => $board));
2033
2034 if (isset($_POST['lock']) && $_POST['lock'] != 2)
2035 logAction('lock', array('topic' => $topicOptions['id'], 'board' => $topicOptions['board']));
2036
2037 if (isset($_POST['sticky']) && !empty($modSettings['enableStickyTopics']))
2038 logAction('sticky', array('topic' => $topicOptions['id'], 'board' => $topicOptions['board']));
2039
2040 // Notify any members who have notification turned on for this topic - only do this if it's going to be approved(!)
2041 if ($becomesApproved)
2042 {
2043 if ($newTopic)
2044 {
2045 $notifyData = array(
2046 'body' => $_POST['message'],
2047 'subject' => $_POST['subject'],
2048 'name' => $user_info['name'],
2049 'poster' => $user_info['id'],
2050 'msg' => $msgOptions['id'],
2051 'board' => $board,
2052 'topic' => $topic,
2053 );
2054 notifyMembersBoard($notifyData);
2055 }
2056 elseif (empty($_REQUEST['msg']))
2057 {
2058 // Only send it to everyone if the topic is approved, otherwise just to the topic starter if they want it.
2059 if ($topic_info['approved'])
2060 sendNotifications($topic, 'reply');
2061 else
2062 sendNotifications($topic, 'reply', array(), $topic_info['id_member_started']);
2063 }
2064 }
2065
2066 // Returning to the topic?
2067 if (!empty($_REQUEST['goback']))
2068 {
2069 // Mark the board as read.... because it might get confusing otherwise.
2070 $smcFunc['db_query']('', '
2071 UPDATE {db_prefix}log_boards
2072 SET id_msg = {int:maxMsgID}
2073 WHERE id_member = {int:current_member}
2074 AND id_board = {int:current_board}',
2075 array(
2076 'current_board' => $board,
2077 'current_member' => $user_info['id'],
2078 'maxMsgID' => $modSettings['maxMsgID'],
2079 )
2080 );
2081 }
2082
2083 if ($board_info['num_topics'] == 0)
2084 cache_put_data('board-' . $board, null, 120);
2085
2086 if (!empty($_POST['announce_topic']))
2087 redirectexit('action=announce;sa=selectgroup;topic=' . $topic . (!empty($_POST['move']) && allowedTo('move_any') ? ';move' : '') . (empty($_REQUEST['goback']) ? '' : ';goback'));
2088
2089 if (!empty($_POST['move']) && allowedTo('move_any'))
2090 redirectexit('action=movetopic;topic=' . $topic . '.0' . (empty($_REQUEST['goback']) ? '' : ';goback'));
2091
2092 // Return to post if the mod is on.
2093 if (isset($_REQUEST['msg']) && !empty($_REQUEST['goback']))
2094 redirectexit('topic=' . $topic . '.msg' . $_REQUEST['msg'] . '#msg' . $_REQUEST['msg'], $context['browser']['is_ie']);
2095 elseif (!empty($_REQUEST['goback']))
2096 redirectexit('topic=' . $topic . '.new#new', $context['browser']['is_ie']);
2097 // Dut-dut-duh-duh-DUH-duh-dut-duh-duh! *dances to the Final Fantasy Fanfare...*
2098 else
2099 redirectexit('board=' . $board . '.0');
2100 }
2101
2102 // General function for topic announcements.
2103 function AnnounceTopic()
2104 {
2105 global $context, $txt, $topic;
2106
2107 isAllowedTo('announce_topic');
2108
2109 validateSession();
2110
2111 if (empty($topic))
2112 fatal_lang_error('topic_gone', false);
2113
2114 loadLanguage('Post');
2115 loadTemplate('Post');
2116
2117 $subActions = array(
2118 'selectgroup' => 'AnnouncementSelectMembergroup',
2119 'send' => 'AnnouncementSend',
2120 );
2121
2122 $context['page_title'] = $txt['announce_topic'];
2123
2124 // Call the function based on the sub-action.
2125 $subActions[isset($_REQUEST['sa']) && isset($subActions[$_REQUEST['sa']]) ? $_REQUEST['sa'] : 'selectgroup']();
2126 }
2127
2128 // Allow a user to chose the membergroups to send the announcement to.
2129 function AnnouncementSelectMembergroup()
2130 {
2131 global $txt, $context, $topic, $board, $board_info, $smcFunc;
2132
2133 $groups = array_merge($board_info['groups'], array(1));
2134 foreach ($groups as $id => $group)
2135 $groups[$id] = (int) $group;
2136
2137 $context['groups'] = array();
2138 if (in_array(0, $groups))
2139 {
2140 $context['groups'][0] = array(
2141 'id' => 0,
2142 'name' => $txt['announce_regular_members'],
2143 'member_count' => 'n/a',
2144 );
2145 }
2146
2147 // Get all membergroups that have access to the board the announcement was made on.
2148 $request = $smcFunc['db_query']('', '
2149 SELECT mg.id_group, COUNT(mem.id_member) AS num_members
2150 FROM {db_prefix}membergroups AS mg
2151 LEFT JOIN {db_prefix}members AS mem ON (mem.id_group = mg.id_group OR FIND_IN_SET(mg.id_group, mem.additional_groups) != 0 OR mg.id_group = mem.id_post_group)
2152 WHERE mg.id_group IN ({array_int:group_list})
2153 GROUP BY mg.id_group',
2154 array(
2155 'group_list' => $groups,
2156 'newbie_id_group' => 4,
2157 )
2158 );
2159 while ($row = $smcFunc['db_fetch_assoc']($request))
2160 {
2161 $context['groups'][$row['id_group']] = array(
2162 'id' => $row['id_group'],
2163 'name' => '',
2164 'member_count' => $row['num_members'],
2165 );
2166 }
2167 $smcFunc['db_free_result']($request);
2168
2169 // Now get the membergroup names.
2170 $request = $smcFunc['db_query']('', '
2171 SELECT id_group, group_name
2172 FROM {db_prefix}membergroups
2173 WHERE id_group IN ({array_int:group_list})',
2174 array(
2175 'group_list' => $groups,
2176 )
2177 );
2178 while ($row = $smcFunc['db_fetch_assoc']($request))
2179 $context['groups'][$row['id_group']]['name'] = $row['group_name'];
2180 $smcFunc['db_free_result']($request);
2181
2182 // Get the subject of the topic we're about to announce.
2183 $request = $smcFunc['db_query']('', '
2184 SELECT m.subject
2185 FROM {db_prefix}topics AS t
2186 INNER JOIN {db_prefix}messages AS m ON (m.id_msg = t.id_first_msg)
2187 WHERE t.id_topic = {int:current_topic}',
2188 array(
2189 'current_topic' => $topic,
2190 )
2191 );
2192 list ($context['topic_subject']) = $smcFunc['db_fetch_row']($request);
2193 $smcFunc['db_free_result']($request);
2194
2195 censorText($context['announce_topic']['subject']);
2196
2197 $context['move'] = isset($_REQUEST['move']) ? 1 : 0;
2198 $context['go_back'] = isset($_REQUEST['goback']) ? 1 : 0;
2199
2200 $context['sub_template'] = 'announce';
2201 }
2202
2203 // Send the announcement in chunks.
2204 function AnnouncementSend()
2205 {
2206 global $topic, $board, $board_info, $context, $modSettings;
2207 global $language, $scripturl, $txt, $user_info, $sourcedir, $smcFunc;
2208
2209 checkSession();
2210
2211 // !!! Might need an interface?
2212 $chunkSize = empty($modSettings['mail_queue']) ? 50 : 500;
2213
2214 $context['start'] = empty($_REQUEST['start']) ? 0 : (int) $_REQUEST['start'];
2215 $groups = array_merge($board_info['groups'], array(1));
2216
2217 if (isset($_POST['membergroups']))
2218 $_POST['who'] = explode(',', $_POST['membergroups']);
2219
2220 // Check whether at least one membergroup was selected.
2221 if (empty($_POST['who']))
2222 fatal_lang_error('no_membergroup_selected');
2223
2224 // Make sure all membergroups are integers and can access the board of the announcement.
2225 foreach ($_POST['who'] as $id => $mg)
2226 $_POST['who'][$id] = in_array((int) $mg, $groups) ? (int) $mg : 0;
2227
2228 // Get the topic subject and censor it.
2229 $request = $smcFunc['db_query']('', '
2230 SELECT m.id_msg, m.subject, m.body
2231 FROM {db_prefix}topics AS t
2232 INNER JOIN {db_prefix}messages AS m ON (m.id_msg = t.id_first_msg)
2233 WHERE t.id_topic = {int:current_topic}',
2234 array(
2235 'current_topic' => $topic,
2236 )
2237 );
2238 list ($id_msg, $context['topic_subject'], $message) = $smcFunc['db_fetch_row']($request);
2239 $smcFunc['db_free_result']($request);
2240
2241 censorText($context['topic_subject']);
2242 censorText($message);
2243
2244 $message = trim(un_htmlspecialchars(strip_tags(strtr(parse_bbc($message, false, $id_msg), array('<br />' => "\n", '</div>' => "\n", '</li>' => "\n", '&#91;' => '[', '&#93;' => ']')))));
2245
2246 // We need this in order to be able send emails.
2247 require_once($sourcedir . '/Subs-Post.php');
2248
2249 // Select the email addresses for this batch.
2250 $request = $smcFunc['db_query']('', '
2251 SELECT mem.id_member, mem.email_address, mem.lngfile
2252 FROM {db_prefix}members AS mem
2253 WHERE mem.id_member != {int:current_member}' . (!empty($modSettings['allow_disableAnnounce']) ? '
2254 AND mem.notify_announcements = {int:notify_announcements}' : '') . '
2255 AND mem.is_activated = {int:is_activated}
2256 AND (mem.id_group IN ({array_int:group_list}) OR mem.id_post_group IN ({array_int:group_list}) OR FIND_IN_SET({raw:additional_group_list}, mem.additional_groups) != 0)
2257 AND mem.id_member > {int:start}
2258 ORDER BY mem.id_member
2259 LIMIT ' . $chunkSize,
2260 array(
2261 'current_member' => $user_info['id'],
2262 'group_list' => $_POST['who'],
2263 'notify_announcements' => 1,
2264 'is_activated' => 1,
2265 'start' => $context['start'],
2266 'additional_group_list' => implode(', mem.additional_groups) != 0 OR FIND_IN_SET(', $_POST['who']),
2267 )
2268 );
2269
2270 // All members have received a mail. Go to the next screen.
2271 if ($smcFunc['db_num_rows']($request) == 0)
2272 {
2273 if (!empty($_REQUEST['move']) && allowedTo('move_any'))
2274 redirectexit('action=movetopic;topic=' . $topic . '.0' . (empty($_REQUEST['goback']) ? '' : ';goback'));
2275 elseif (!empty($_REQUEST['goback']))
2276 redirectexit('topic=' . $topic . '.new;boardseen#new', $context['browser']['is_ie']);
2277 else
2278 redirectexit('board=' . $board . '.0');
2279 }
2280
2281 // Loop through all members that'll receive an announcement in this batch.
2282 while ($row = $smcFunc['db_fetch_assoc']($request))
2283 {
2284 $cur_language = empty($row['lngfile']) || empty($modSettings['userLanguage']) ? $language : $row['lngfile'];
2285
2286 // If the language wasn't defined yet, load it and compose a notification message.
2287 if (!isset($announcements[$cur_language]))
2288 {
2289 $replacements = array(
2290 'TOPICSUBJECT' => $context['topic_subject'],
2291 'MESSAGE' => $message,
2292 'TOPICLINK' => $scripturl . '?topic=' . $topic . '.0',
2293 );
2294
2295 $emaildata = loadEmailTemplate('new_announcement', $replacements, $cur_language);
2296
2297 $announcements[$cur_language] = array(
2298 'subject' => $emaildata['subject'],
2299 'body' => $emaildata['body'],
2300 'recipients' => array(),
2301 );
2302 }
2303
2304 $announcements[$cur_language]['recipients'][$row['id_member']] = $row['email_address'];
2305 $context['start'] = $row['id_member'];
2306 }
2307 $smcFunc['db_free_result']($request);
2308
2309 // For each language send a different mail - low priority...
2310 foreach ($announcements as $lang => $mail)
2311 sendmail($mail['recipients'], $mail['subject'], $mail['body'], null, null, false, 5);
2312
2313 $context['percentage_done'] = round(100 * $context['start'] / $modSettings['latestMember'], 1);
2314
2315 $context['move'] = empty($_REQUEST['move']) ? 0 : 1;
2316 $context['go_back'] = empty($_REQUEST['goback']) ? 0 : 1;
2317 $context['membergroups'] = implode(',', $_POST['who']);
2318 $context['sub_template'] = 'announcement_send';
2319
2320 // Go back to the correct language for the user ;).
2321 if (!empty($modSettings['userLanguage']))
2322 loadLanguage('Post');
2323 }
2324
2325 // Notify members of a new post.
2326 function notifyMembersBoard(&$topicData)
2327 {
2328 global $txt, $scripturl, $language, $user_info;
2329 global $modSettings, $sourcedir, $board, $smcFunc, $context;
2330
2331 require_once($sourcedir . '/Subs-Post.php');
2332
2333 // Do we have one or lots of topics?
2334 if (isset($topicData['body']))
2335 $topicData = array($topicData);
2336
2337 // Find out what boards we have... and clear out any rubbish!
2338 $boards = array();
2339 foreach ($topicData as $key => $topic)
2340 {
2341 if (!empty($topic['board']))
2342 $boards[$topic['board']][] = $key;
2343 else
2344 {
2345 unset($topic[$key]);
2346 continue;
2347 }
2348
2349 // Censor the subject and body...
2350 censorText($topicData[$key]['subject']);
2351 censorText($topicData[$key]['body']);
2352
2353 $topicData[$key]['subject'] = un_htmlspecialchars($topicData[$key]['subject']);
2354 $topicData[$key]['body'] = trim(un_htmlspecialchars(strip_tags(strtr(parse_bbc($topicData[$key]['body'], false), array('<br />' => "\n", '</div>' => "\n", '</li>' => "\n", '&#91;' => '[', '&#93;' => ']')))));
2355 }
2356
2357 // Just the board numbers.
2358 $board_index = array_unique(array_keys($boards));
2359
2360 if (empty($board_index))
2361 return;
2362
2363 // Yea, we need to add this to the digest queue.
2364 $digest_insert = array();
2365 foreach ($topicData as $id => $data)
2366 $digest_insert[] = array($data['topic'], $data['msg'], 'topic', $user_info['id']);
2367 $smcFunc['db_insert']('',
2368 '{db_prefix}log_digest',
2369 array(
2370 'id_topic' => 'int', 'id_msg' => 'int', 'note_type' => 'string', 'exclude' => 'int',
2371 ),
2372 $digest_insert,
2373 array()
2374 );
2375
2376 // Find the members with notification on for these boards.
2377 $members = $smcFunc['db_query']('', '
2378 SELECT
2379 mem.id_member, mem.email_address, mem.notify_regularity, mem.notify_send_body, mem.lngfile,
2380 ln.sent, ln.id_board, mem.id_group, mem.additional_groups, b.member_groups,
2381 mem.id_post_group
2382 FROM {db_prefix}log_notify AS ln
2383 INNER JOIN {db_prefix}boards AS b ON (b.id_board = ln.id_board)
2384 INNER JOIN {db_prefix}members AS mem ON (mem.id_member = ln.id_member)
2385 WHERE ln.id_board IN ({array_int:board_list})
2386 AND mem.id_member != {int:current_member}
2387 AND mem.is_activated = {int:is_activated}
2388 AND mem.notify_types != {int:notify_types}
2389 AND mem.notify_regularity < {int:notify_regularity}
2390 ORDER BY mem.lngfile',
2391 array(
2392 'current_member' => $user_info['id'],
2393 'board_list' => $board_index,
2394 'is_activated' => 1,
2395 'notify_types' => 4,
2396 'notify_regularity' => 2,
2397 )
2398 );
2399 while ($rowmember = $smcFunc['db_fetch_assoc']($members))
2400 {
2401 if ($rowmember['id_group'] != 1)
2402 {
2403 $allowed = explode(',', $rowmember['member_groups']);
2404 $rowmember['additional_groups'] = explode(',', $rowmember['additional_groups']);
2405 $rowmember['additional_groups'][] = $rowmember['id_group'];
2406 $rowmember['additional_groups'][] = $rowmember['id_post_group'];
2407
2408 if (count(array_intersect($allowed, $rowmember['additional_groups'])) == 0)
2409 continue;
2410 }
2411
2412 $langloaded = loadLanguage('EmailTemplates', empty($rowmember['lngfile']) || empty($modSettings['userLanguage']) ? $language : $rowmember['lngfile'], false);
2413
2414 // Now loop through all the notifications to send for this board.
2415 if (empty($boards[$rowmember['id_board']]))
2416 continue;
2417
2418 $sentOnceAlready = 0;
2419 foreach ($boards[$rowmember['id_board']] as $key)
2420 {
2421 // Don't notify the guy who started the topic!
2422 //!!! In this case actually send them a "it's approved hooray" email
2423 if ($topicData[$key]['poster'] == $rowmember['id_member'])
2424 continue;
2425
2426 // Setup the string for adding the body to the message, if a user wants it.
2427 $send_body = empty($modSettings['disallow_sendBody']) && !empty($rowmember['notify_send_body']);
2428
2429 $replacements = array(
2430 'TOPICSUBJECT' => $topicData[$key]['subject'],
2431 'TOPICLINK' => $scripturl . '?topic=' . $topicData[$key]['topic'] . '.new#new',
2432 'MESSAGE' => $topicData[$key]['body'],
2433 'UNSUBSCRIBELINK' => $scripturl . '?action=notifyboard;board=' . $topicData[$key]['board'] . '.0',
2434 );
2435
2436 if (!$send_body)
2437 unset($replacements['MESSAGE']);
2438
2439 // Figure out which email to send off
2440 $emailtype = '';
2441
2442 // Send only if once is off or it's on and it hasn't been sent.
2443 if (!empty($rowmember['notify_regularity']) && !$sentOnceAlready && empty($rowmember['sent']))
2444 $emailtype = 'notify_boards_once';
2445 elseif (empty($rowmember['notify_regularity']))
2446 $emailtype = 'notify_boards';
2447
2448 if (!empty($emailtype))
2449 {
2450 $emailtype .= $send_body ? '_body' : '';
2451 $emaildata = loadEmailTemplate($emailtype, $replacements, $langloaded);
2452 sendmail($rowmember['email_address'], $emaildata['subject'], $emaildata['body'], null, null, false, 3);
2453 }
2454
2455 $sentOnceAlready = 1;
2456 }
2457 }
2458 $smcFunc['db_free_result']($members);
2459
2460 // Sent!
2461 $smcFunc['db_query']('', '
2462 UPDATE {db_prefix}log_notify
2463 SET sent = {int:is_sent}
2464 WHERE id_board IN ({array_int:board_list})
2465 AND id_member != {int:current_member}',
2466 array(
2467 'current_member' => $user_info['id'],
2468 'board_list' => $board_index,
2469 'is_sent' => 1,
2470 )
2471 );
2472 }
2473
2474 // Get the topic for display purposes.
2475 function getTopic()
2476 {
2477 global $topic, $modSettings, $context, $smcFunc, $counter, $options;
2478
2479 if (isset($_REQUEST['xml']))
2480 $limit = '
2481 LIMIT ' . (empty($context['new_replies']) ? '0' : $context['new_replies']);
2482 else
2483 $limit = empty($modSettings['topicSummaryPosts']) ? '' : '
2484 LIMIT ' . (int) $modSettings['topicSummaryPosts'];
2485
2486 // If you're modifying, get only those posts before the current one. (otherwise get all.)
2487 $request = $smcFunc['db_query']('', '
2488 SELECT
2489 IFNULL(mem.real_name, m.poster_name) AS poster_name, m.poster_time,
2490 m.body, m.smileys_enabled, m.id_msg, m.id_member
2491 FROM {db_prefix}messages AS m
2492 LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member)
2493 WHERE m.id_topic = {int:current_topic}' . (isset($_REQUEST['msg']) ? '
2494 AND m.id_msg < {int:id_msg}' : '') .(!$modSettings['postmod_active'] || allowedTo('approve_posts') ? '' : '
2495 AND m.approved = {int:approved}') . '
2496 ORDER BY m.id_msg DESC' . $limit,
2497 array(
2498 'current_topic' => $topic,
2499 'id_msg' => isset($_REQUEST['msg']) ? (int) $_REQUEST['msg'] : 0,
2500 'approved' => 1,
2501 )
2502 );
2503 $context['previous_posts'] = array();
2504 while ($row = $smcFunc['db_fetch_assoc']($request))
2505 {
2506 // Censor, BBC, ...
2507 censorText($row['body']);
2508 $row['body'] = parse_bbc($row['body'], $row['smileys_enabled'], $row['id_msg']);
2509
2510 // ...and store.
2511 $context['previous_posts'][] = array(
2512 'counter' => $counter++,
2513 'alternate' => $counter % 2,
2514 'poster' => $row['poster_name'],
2515 'message' => $row['body'],
2516 'time' => timeformat($row['poster_time']),
2517 'timestamp' => forum_time(true, $row['poster_time']),
2518 'id' => $row['id_msg'],
2519 'is_new' => !empty($context['new_replies']),
2520 'is_ignored' => !empty($modSettings['enable_buddylist']) && !empty($options['posts_apply_ignore_list']) && in_array($row['id_member'], $context['user']['ignoreusers']),
2521 );
2522
2523 if (!empty($context['new_replies']))
2524 $context['new_replies']--;
2525 }
2526 $smcFunc['db_free_result']($request);
2527 }
2528
2529 function QuoteFast()
2530 {
2531 global $modSettings, $user_info, $txt, $settings, $context;
2532 global $sourcedir, $smcFunc;
2533
2534 loadLanguage('Post');
2535 if (!isset($_REQUEST['xml']))
2536 loadTemplate('Post');
2537
2538 include_once($sourcedir . '/Subs-Post.php');
2539
2540 $moderate_boards = boardsAllowedTo('moderate_board');
2541
2542 // Where we going if we need to?
2543 $context['post_box_name'] = isset($_GET['pb']) ? $_GET['pb'] : '';
2544
2545 $request = $smcFunc['db_query']('', '
2546 SELECT IFNULL(mem.real_name, m.poster_name) AS poster_name, m.poster_time, m.body, m.id_topic, m.subject,
2547 m.id_board, m.id_member, m.approved
2548 FROM {db_prefix}messages AS m
2549 INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic)
2550 INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board AND {query_see_board})
2551 LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member)
2552 WHERE m.id_msg = {int:id_msg}' . (isset($_REQUEST['modify']) || (!empty($moderate_boards) && $moderate_boards[0] == 0) ? '' : '
2553 AND (t.locked = {int:not_locked}' . (empty($moderate_boards) ? '' : ' OR b.id_board IN ({array_int:moderation_board_list})') . ')') . '
2554 LIMIT 1',
2555 array(
2556 'current_member' => $user_info['id'],
2557 'moderation_board_list' => $moderate_boards,
2558 'id_msg' => (int) $_REQUEST['quote'],
2559 'not_locked' => 0,
2560 )
2561 );
2562 $context['close_window'] = $smcFunc['db_num_rows']($request) == 0;
2563 $row = $smcFunc['db_fetch_assoc']($request);
2564 $smcFunc['db_free_result']($request);
2565
2566 $context['sub_template'] = 'quotefast';
2567 if (!empty($row))
2568 $can_view_post = $row['approved'] || ($row['id_member'] != 0 && $row['id_member'] == $user_info['id']) || allowedTo('approve_posts', $row['id_board']);
2569
2570 if (!empty($can_view_post))
2571 {
2572 // Remove special formatting we don't want anymore.
2573 $row['body'] = un_preparsecode($row['body']);
2574
2575 // Censor the message!
2576 censorText($row['body']);
2577
2578 $row['body'] = preg_replace('~<br ?/?' . '>~i', "\n", $row['body']);
2579
2580 // Want to modify a single message by double clicking it?
2581 if (isset($_REQUEST['modify']))
2582 {
2583 censorText($row['subject']);
2584
2585 $context['sub_template'] = 'modifyfast';
2586 $context['message'] = array(
2587 'id' => $_REQUEST['quote'],
2588 'body' => $row['body'],
2589 'subject' => addcslashes($row['subject'], '"'),
2590 );
2591
2592 return;
2593 }
2594
2595 // Remove any nested quotes.
2596 if (!empty($modSettings['removeNestedQuotes']))
2597 $row['body'] = preg_replace(array('~\n?\[quote.*?\].+?\[/quote\]\n?~is', '~^\n~', '~\[/quote\]~'), '', $row['body']);
2598
2599 // Make the body HTML if need be.
2600 if (!empty($_REQUEST['mode']))
2601 {
2602 require_once($sourcedir . '/Subs-Editor.php');
2603 $row['body'] = strtr($row['body'], array('&lt;' => '#smlt#', '&gt;' => '#smgt#', '&amp;' => '#smamp#'));
2604 $row['body'] = bbc_to_html($row['body']);
2605 $lb = '<br />';
2606 }
2607 else
2608 $lb = "\n";
2609
2610 // Add a quote string on the front and end.
2611 $context['quote']['xml'] = '[quote author=' . $row['poster_name'] . ' link=topic=' . $row['id_topic'] . '.msg' . (int) $_REQUEST['quote'] . '#msg' . (int) $_REQUEST['quote'] . ' date=' . $row['poster_time'] . ']' . $lb . $row['body'] . $lb . '[/quote]';
2612 $context['quote']['text'] = strtr(un_htmlspecialchars($context['quote']['xml']), array('\'' => '\\\'', '\\' => '\\\\', "\n" => '\\n', '</script>' => '</\' + \'script>'));
2613 $context['quote']['xml'] = strtr($context['quote']['xml'], array('&nbsp;' => '&#160;', '<' => '&lt;', '>' => '&gt;'));
2614
2615 $context['quote']['mozilla'] = strtr($smcFunc['htmlspecialchars']($context['quote']['text']), array('&quot;' => '"'));
2616 }
2617 // !!! Needs a nicer interface.
2618 // In case our message has been removed in the meantime.
2619 elseif (isset($_REQUEST['modify']))
2620 {
2621 $context['sub_template'] = 'modifyfast';
2622 $context['message'] = array(
2623 'id' => 0,
2624 'body' => '',
2625 'subject' => '',
2626 );
2627 }
2628 else
2629 $context['quote'] = array(
2630 'xml' => '',
2631 'mozilla' => '',
2632 'text' => '',
2633 );
2634 }
2635
2636 function JavaScriptModify()
2637 {
2638 global $sourcedir, $modSettings, $board, $topic, $txt;
2639 global $user_info, $context, $smcFunc, $language;
2640
2641 // We have to have a topic!
2642 if (empty($topic))
2643 obExit(false);
2644
2645 checkSession('get');
2646 require_once($sourcedir . '/Subs-Post.php');
2647
2648 // Assume the first message if no message ID was given.
2649 $request = $smcFunc['db_query']('', '
2650 SELECT
2651 t.locked, t.num_replies, t.id_member_started, t.id_first_msg,
2652 m.id_msg, m.id_member, m.poster_time, m.subject, m.smileys_enabled, m.body, m.icon,
2653 m.modified_time, m.modified_name, m.approved
2654 FROM {db_prefix}messages AS m
2655 INNER JOIN {db_prefix}topics AS t ON (t.id_topic = {int:current_topic})
2656 WHERE m.id_msg = {raw:id_msg}
2657 AND m.id_topic = {int:current_topic}' . (allowedTo('approve_posts') ? '' : (!$modSettings['postmod_active'] ? '
2658 AND (m.id_member != {int:guest_id} AND m.id_member = {int:current_member})' : '
2659 AND (m.approved = {int:is_approved} OR (m.id_member != {int:guest_id} AND m.id_member = {int:current_member}))')),
2660 array(
2661 'current_member' => $user_info['id'],
2662 'current_topic' => $topic,
2663 'id_msg' => empty($_REQUEST['msg']) ? 't.id_first_msg' : (int) $_REQUEST['msg'],
2664 'is_approved' => 1,
2665 'guest_id' => 0,
2666 )
2667 );
2668 if ($smcFunc['db_num_rows']($request) == 0)
2669 fatal_lang_error('no_board', false);
2670 $row = $smcFunc['db_fetch_assoc']($request);
2671 $smcFunc['db_free_result']($request);
2672
2673 // Change either body or subject requires permissions to modify messages.
2674 if (isset($_POST['message']) || isset($_POST['subject']) || isset($_REQUEST['icon']))
2675 {
2676 if (!empty($row['locked']))
2677 isAllowedTo('moderate_board');
2678
2679 if ($row['id_member'] == $user_info['id'] && !allowedTo('modify_any'))
2680 {
2681 if ((!$modSettings['postmod_active'] || $row['approved']) && !empty($modSettings['edit_disable_time']) && $row['poster_time'] + ($modSettings['edit_disable_time'] + 5) * 60 < time())
2682 fatal_lang_error('modify_post_time_passed', false);
2683 elseif ($row['id_member_started'] == $user_info['id'] && !allowedTo('modify_own'))
2684 isAllowedTo('modify_replies');
2685 else
2686 isAllowedTo('modify_own');
2687 }
2688 // Otherwise, they're locked out; someone who can modify the replies is needed.
2689 elseif ($row['id_member_started'] == $user_info['id'] && !allowedTo('modify_any'))
2690 isAllowedTo('modify_replies');
2691 else
2692 isAllowedTo('modify_any');
2693
2694 // Only log this action if it wasn't your message.
2695 $moderationAction = $row['id_member'] != $user_info['id'];
2696 }
2697
2698 $post_errors = array();
2699 if (isset($_POST['subject']) && $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['subject'])) !== '')
2700 {
2701 $_POST['subject'] = strtr($smcFunc['htmlspecialchars']($_POST['subject']), array("\r" => '', "\n" => '', "\t" => ''));
2702
2703 // Maximum number of characters.
2704 if ($smcFunc['strlen']($_POST['subject']) > 100)
2705 $_POST['subject'] = $smcFunc['substr']($_POST['subject'], 0, 100);
2706 }
2707 elseif (isset($_POST['subject']))
2708 {
2709 $post_errors[] = 'no_subject';
2710 unset($_POST['subject']);
2711 }
2712
2713 if (isset($_POST['message']))
2714 {
2715 if ($smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['message'])) === '')
2716 {
2717 $post_errors[] = 'no_message';
2718 unset($_POST['message']);
2719 }
2720 elseif (!empty($modSettings['max_messageLength']) && $smcFunc['strlen']($_POST['message']) > $modSettings['max_messageLength'])
2721 {
2722 $post_errors[] = 'long_message';
2723 unset($_POST['message']);
2724 }
2725 else
2726 {
2727 $_POST['message'] = $smcFunc['htmlspecialchars']($_POST['message'], ENT_QUOTES);
2728
2729 preparsecode($_POST['message']);
2730
2731 if ($smcFunc['htmltrim'](strip_tags(parse_bbc($_POST['message'], false), '<img>')) === '')
2732 {
2733 $post_errors[] = 'no_message';
2734 unset($_POST['message']);
2735 }
2736 }
2737 }
2738
2739 if (isset($_POST['lock']))
2740 {
2741 if (!allowedTo(array('lock_any', 'lock_own')) || (!allowedTo('lock_any') && $user_info['id'] != $row['id_member']))
2742 unset($_POST['lock']);
2743 elseif (!allowedTo('lock_any'))
2744 {
2745 if ($row['locked'] == 1)
2746 unset($_POST['lock']);
2747 else
2748 $_POST['lock'] = empty($_POST['lock']) ? 0 : 2;
2749 }
2750 elseif (!empty($row['locked']) && !empty($_POST['lock']) || $_POST['lock'] == $row['locked'])
2751 unset($_POST['lock']);
2752 else
2753 $_POST['lock'] = empty($_POST['lock']) ? 0 : 1;
2754 }
2755
2756 if (isset($_POST['sticky']) && !allowedTo('make_sticky'))
2757 unset($_POST['sticky']);
2758
2759 if (empty($post_errors))
2760 {
2761 $msgOptions = array(
2762 'id' => $row['id_msg'],
2763 'subject' => isset($_POST['subject']) ? $_POST['subject'] : null,
2764 'body' => isset($_POST['message']) ? $_POST['message'] : null,
2765 'icon' => isset($_REQUEST['icon']) ? preg_replace('~[\./\\\\*\':"<>]~', '', $_REQUEST['icon']) : null,
2766 );
2767 $topicOptions = array(
2768 'id' => $topic,
2769 'board' => $board,
2770 'lock_mode' => isset($_POST['lock']) ? (int) $_POST['lock'] : null,
2771 'sticky_mode' => isset($_POST['sticky']) && !empty($modSettings['enableStickyTopics']) ? (int) $_POST['sticky'] : null,
2772 'mark_as_read' => true,
2773 );
2774 $posterOptions = array();
2775
2776 // Only consider marking as editing if they have edited the subject, message or icon.
2777 if ((isset($_POST['subject']) && $_POST['subject'] != $row['subject']) || (isset($_POST['message']) && $_POST['message'] != $row['body']) || (isset($_REQUEST['icon']) && $_REQUEST['icon'] != $row['icon']))
2778 {
2779 // And even then only if the time has passed...
2780 if (time() - $row['poster_time'] > $modSettings['edit_wait_time'] || $user_info['id'] != $row['id_member'])
2781 {
2782 $msgOptions['modify_time'] = time();
2783 $msgOptions['modify_name'] = $user_info['name'];
2784 }
2785 }
2786 // If nothing was changed there's no need to add an entry to the moderation log.
2787 else
2788 $moderationAction = false;
2789
2790 modifyPost($msgOptions, $topicOptions, $posterOptions);
2791
2792 // If we didn't change anything this time but had before put back the old info.
2793 if (!isset($msgOptions['modify_time']) && !empty($row['modified_time']))
2794 {
2795 $msgOptions['modify_time'] = $row['modified_time'];
2796 $msgOptions['modify_name'] = $row['modified_name'];
2797 }
2798
2799 // Changing the first subject updates other subjects to 'Re: new_subject'.
2800 if (isset($_POST['subject']) && isset($_REQUEST['change_all_subjects']) && $row['id_first_msg'] == $row['id_msg'] && !empty($row['num_replies']) && (allowedTo('modify_any') || ($row['id_member_started'] == $user_info['id'] && allowedTo('modify_replies'))))
2801 {
2802 // Get the proper (default language) response prefix first.
2803 if (!isset($context['response_prefix']) && !($context['response_prefix'] = cache_get_data('response_prefix')))
2804 {
2805 if ($language === $user_info['language'])
2806 $context['response_prefix'] = $txt['response_prefix'];
2807 else
2808 {
2809 loadLanguage('index', $language, false);
2810 $context['response_prefix'] = $txt['response_prefix'];
2811 loadLanguage('index');
2812 }
2813 cache_put_data('response_prefix', $context['response_prefix'], 600);
2814 }
2815
2816 $smcFunc['db_query']('', '
2817 UPDATE {db_prefix}messages
2818 SET subject = {string:subject}
2819 WHERE id_topic = {int:current_topic}
2820 AND id_msg != {int:id_first_msg}',
2821 array(
2822 'current_topic' => $topic,
2823 'id_first_msg' => $row['id_first_msg'],
2824 'subject' => $context['response_prefix'] . $_POST['subject'],
2825 )
2826 );
2827 }
2828
2829 if (!empty($moderationAction))
2830 logAction('modify', array('topic' => $topic, 'message' => $row['id_msg'], 'member' => $row['id_member'], 'board' => $board));
2831 }
2832
2833 if (isset($_REQUEST['xml']))
2834 {
2835 $context['sub_template'] = 'modifydone';
2836 if (empty($post_errors) && isset($msgOptions['subject']) && isset($msgOptions['body']))
2837 {
2838 $context['message'] = array(
2839 'id' => $row['id_msg'],
2840 'modified' => array(
2841 'time' => isset($msgOptions['modify_time']) ? timeformat($msgOptions['modify_time']) : '',
2842 'timestamp' => isset($msgOptions['modify_time']) ? forum_time(true, $msgOptions['modify_time']) : 0,
2843 'name' => isset($msgOptions['modify_time']) ? $msgOptions['modify_name'] : '',
2844 ),
2845 'subject' => $msgOptions['subject'],
2846 'first_in_topic' => $row['id_msg'] == $row['id_first_msg'],
2847 'body' => strtr($msgOptions['body'], array(']]>' => ']]]]><![CDATA[>')),
2848 );
2849
2850 censorText($context['message']['subject']);
2851 censorText($context['message']['body']);
2852
2853 $context['message']['body'] = parse_bbc($context['message']['body'], $row['smileys_enabled'], $row['id_msg']);
2854 }
2855 // Topic?
2856 elseif (empty($post_errors))
2857 {
2858 $context['sub_template'] = 'modifytopicdone';
2859 $context['message'] = array(
2860 'id' => $row['id_msg'],
2861 'modified' => array(
2862 'time' => isset($msgOptions['modify_time']) ? timeformat($msgOptions['modify_time']) : '',
2863 'timestamp' => isset($msgOptions['modify_time']) ? forum_time(true, $msgOptions['modify_time']) : 0,
2864 'name' => isset($msgOptions['modify_time']) ? $msgOptions['modify_name'] : '',
2865 ),
2866 'subject' => isset($msgOptions['subject']) ? $msgOptions['subject'] : '',
2867 );
2868
2869 censorText($context['message']['subject']);
2870 }
2871 else
2872 {
2873 $context['message'] = array(
2874 'id' => $row['id_msg'],
2875 'errors' => array(),
2876 'error_in_subject' => in_array('no_subject', $post_errors),
2877 'error_in_body' => in_array('no_message', $post_errors) || in_array('long_message', $post_errors),
2878 );
2879
2880 loadLanguage('Errors');
2881 foreach ($post_errors as $post_error)
2882 {
2883 if ($post_error == 'long_message')
2884 $context['message']['errors'][] = sprintf($txt['error_' . $post_error], $modSettings['max_messageLength']);
2885 else
2886 $context['message']['errors'][] = $txt['error_' . $post_error];
2887 }
2888 }
2889 }
2890 else
2891 obExit(false);
2892 }
2893
2894 ?>