Lighttpd conf file added for lighttpd webservers
[atbbs.git] / post.php
blobdc4ac26857f38e4a034e595444b4dbc9bb39a5e3
1 <?php
3 require('includes/header.php');
4 force_id();
6 if($_GET['reply'])
8 $reply = true;
9 $onload_javascript = 'focusId(\'body\'); init();';
11 if( ! ctype_digit($_GET['reply']))
13 add_error('Invalid topic ID.', true);
16 $stmt = $link->prepare('SELECT headline, author, replies FROM topics WHERE id = ?');
17 $stmt->bind_param('i', $_GET['reply']);
18 $stmt->execute();
19 $stmt->store_result();
20 if($stmt->num_rows < 1)
22 $page_title = 'Non-existent topic';
23 add_error('There is no such topic. It may have been deleted.', true);
25 $stmt->bind_result($replying_to, $topic_author, $topic_replies);
26 $stmt->fetch();
27 $stmt->close();
29 update_activity('replying', $_GET['reply']);
30 $page_title = 'New reply in topic: <a href="/topic/' . $_GET['reply'] . '">' . htmlspecialchars($replying_to) . '</a>';
32 $check_watchlist = $link->prepare('SELECT 1 FROM watchlists WHERE uid = ? AND topic_id = ?');
33 $check_watchlist->bind_param('si', $_SESSION['UID'], $_GET['reply']);
34 $check_watchlist->execute();
35 $check_watchlist->store_result();
36 if($check_watchlist->num_rows > 0)
38 $watching_topic = true;
40 $check_watchlist->close();
42 else // this is a topic
44 $reply = false;
45 $onload_javascript = 'focusId(\'headline\'); init();';
46 update_activity('new_topic');
48 $page_title = 'New topic';
50 if( ! empty($_POST['headline']))
52 $page_title .= ': ' . htmlspecialchars($_POST['headline']);
56 // If we're trying to edit and it's not disabled in the configuration ...
57 if(ALLOW_EDIT && ctype_digit($_GET['edit']))
59 $editing = true;
61 if($reply)
63 $fetch_edit = $link->prepare('SELECT author, time, body, edit_mod FROM replies WHERE id = ?');
65 else
67 $fetch_edit = $link->prepare('SELECT author, time, body, edit_mod, headline FROM topics WHERE id = ?');
70 $fetch_edit->bind_param('i', $_GET['edit']);
71 $fetch_edit->execute();
72 $fetch_edit->store_result();
73 if($fetch_edit->num_rows < 1)
75 add_error('There is no such post. It may have been deleted.', true);
78 if($reply)
80 $fetch_edit->bind_result($edit_data['author'], $edit_data['time'], $edit_data['body'], $edit_data['mod']);
81 $page_title = 'Editing <a href="/topic/' . $_GET['reply'] . '#reply_' . $_GET['edit'] . '">reply</a> to topic: <a href="/topic/' . $_GET['reply'] . '">' . htmlspecialchars($replying_to) . '</a>';
83 else
85 $fetch_edit->bind_result($edit_data['author'], $edit_data['time'], $edit_data['body'], $edit_data['mod'], $edit_data['headline']);
86 $page_title = 'Editing topic';
89 $fetch_edit->fetch();
90 $fetch_edit->close();
92 if($edit_data['author'] === $_SESSION['UID'])
94 $edit_mod = 0;
96 if( ! $administrator && ! $moderator)
98 if(TIME_TO_EDIT != 0 && ( $_SERVER['REQUEST_TIME'] - $edit_data['time'] > TIME_TO_EDIT ))
100 add_error('You can no longer edit your post.', true);
102 if($edit_data['mod'])
104 add_error('You cannot edit a post that has been edited by a moderator.');
108 else if($administrator || $moderator)
110 $edit_mod = 1;
112 else
114 add_error('You are not allowed to edit that post.', true);
117 if( ! $_POST['form_sent'])
119 $body = $edit_data['body'];
121 if( ! $reply)
123 $page_title .= ': <a href="/topic/' . $_GET['edit'] . '">' . htmlspecialchars($edit_data['headline']) . '</a>';
124 $headline = $edit_data['headline'];
127 else if( ! empty($_POST['headline']))
129 $page_title .= ': <a href="/topic/' . $_GET['edit'] . '">' . htmlspecialchars($_POST['headline']) . '</a>';
133 if($_POST['form_sent'])
135 // Trimming.
136 $headline = super_trim($_POST['headline']);
137 $body = super_trim($_POST['body']);
139 // Parse for mass quote tag ([quote]). I'm not sure about create_function, it seems kind of slow.
140 $body = preg_replace_callback(
141 '/\[quote\](.+?)\[\/quote\]/s',
142 create_function(
143 '$matches',
144 'return preg_replace(\'/.*[^\s]$/m\', \'> $0\', $matches[1]);'
146 $body
149 if($_POST['post'])
151 // Check for poorly made bots.
152 if( ! $editing && $_SERVER['REQUEST_TIME'] - $_POST['start_time'] < 3 )
154 add_error('Wait a few seconds between starting to compose a post and actually submitting it.');
156 if( ! empty($_POST['e-mail']))
158 add_error('Bot detected.');
160 if( ! is_array($_SESSION['random_posting_hashes']) )
162 add_error('Session error (no hash values stored). Try again.');
164 else foreach($_SESSION['random_posting_hashes'] as $name => $value)
166 if( ! isset($_POST[$name]) || $_POST[$name] != $value)
168 add_error('Session error (wrong hash value sent). Try again.');
169 break;
173 check_length($body, 'body', MIN_LENGTH_BODY, MAX_LENGTH_BODY);
175 if(count( explode("\n", $body) ) > MAX_LINES)
177 add_error('Your post has too many lines.');
180 // Check for UID ban.
181 $check_uid_ban = $link->prepare('SELECT filed FROM uid_bans WHERE uid = ?');
182 $check_uid_ban->bind_param('s', $_SESSION['UID']);
183 $check_uid_ban->execute();
184 $check_uid_ban->store_result();
185 if($check_uid_ban->num_rows > 0)
187 $check_uid_ban->bind_result($ban_filed);
188 $check_uid_ban->fetch();
190 $time_since_ban = $_SERVER['REQUEST_TIME'] - $ban_filed;
191 if($time_since_ban < BAN_PERIOD)
193 add_error('You are banned. Your ban will expire in ' . calculate_age( $_SERVER['REQUEST_TIME'], $ban_filed + BAN_PERIOD ) . '.');
195 else
197 remove_id_ban($_SESSION['UID']);
200 $check_uid_ban->close();
203 // Check for IP address ban.
204 $check_ip_ban = $link->prepare('SELECT expiry FROM ip_bans WHERE ip_address = ?');
205 $check_ip_ban->bind_param('s', $_SERVER['REMOTE_ADDR']);
206 $check_ip_ban->execute();
207 $check_ip_ban->store_result();
208 if($check_ip_ban->num_rows > 0)
210 $check_ip_ban->bind_result($ban_expiry);
211 $check_ip_ban->fetch();
213 if($ban_expiry == 0 | $ban_expiry > $_SERVER['REQUEST_TIME'])
215 $error_message = 'Your IP address is banned. ';
216 if($ban_expiry > 0)
218 $error_message .= 'This ban will expire in ' . calculate_age($ban_expiry) . '.';
220 else
222 $error_message .= 'This ban is not set to expire.';
224 add_error($error_message);
226 else
228 remove_ip_ban($_SERVER['REMOTE_ADDR']);
231 $check_ip_ban->close();
233 if(ALLOW_IMAGES && ! empty($_FILES['image']['name']) && ! $editing)
235 $image_data = array();
237 switch($_FILES['image']['error'])
239 case UPLOAD_ERR_OK:
240 $uploading = true;
241 break;
243 case UPLOAD_ERR_PARTIAL:
244 add_error('The image was only partially uploaded.');
245 break;
247 case UPLOAD_ERR_INI_SIZE:
248 add_error('The uploaded file exceeds the upload_max_filesize directive in php.ini.');
249 break;
251 case UPLOAD_ERR_NO_FILE:
252 add_error('No file was uploaded.');
253 break;
255 case UPLOAD_ERR_NO_TMP_DIR:
256 add_error('Missing a temporary directory.');
257 break;
259 case UPLOAD_ERR_CANT_WRITE:
260 add_error('Failed to write image to disk.');
261 break;
263 default:
264 add_error('Unable to upload image.');
267 if($uploading)
269 $uploading = false; // until we make our next checks
270 $valid_types = array
272 'jpg',
273 'gif',
274 'png'
277 $valid_name = preg_match('/(.+)\.([a-z0-9]+)$/i', $_FILES['image']['name'], $match);
278 $image_data['type'] = strtolower($match[2]);
279 $image_data['md5'] = md5_file($_FILES['image']['tmp_name']);
280 $image_data['name'] = str_replace( array('.', '/', '<', '>', '"', "'", '%') , '', $match[1]);
281 $image_data['name'] = substr( trim($image_data['name']) , 0, 35);
283 if($image_data['type'] == 'jpeg')
285 $image_data['type'] = 'jpg';
288 if(file_exists('img/' . $image_data['name'] . '.' . $image_data['type']))
290 $image_data['name'] = $_SERVER['REQUEST_TIME'] . mt_rand(0, 99);
293 if($valid_name === 0 || empty($image_data['name']))
295 add_error('The image has an invalid file name.');
297 else if( ! in_array($image_data['type'], $valid_types))
299 add_error('Only <strong>GIF</strong>, <strong>JPEG</strong> and <strong>PNG</strong> files are allowed.');
301 else if($_FILES['image']['size'] > MAX_IMAGE_SIZE)
303 add_error('Uploaded images can be no greater than ' . round(MAX_IMAGE_SIZE / 1048576, 2) . ' MB. ');
305 else
307 $uploading = true;
308 $image_data['name'] = $image_data['name'] . '.' . $image_data['type'];
313 // Set the author (internal use only)
314 $author = $_SESSION['UID'];
315 if(isset($_POST['admin']) && $administrator)
317 $author = 'admin';
320 // If this is a reply...
321 if($reply)
323 if( ! $editing)
325 //Lurk more?
326 if($_SERVER['REQUEST_TIME'] - $_SESSION['first_seen'] < REQUIRED_LURK_TIME_REPLY)
328 add_error('Lurk for at least ' . REQUIRED_LURK_TIME_REPLY . ' seconds before posting your first reply.');
331 // Flood control.
332 $too_early = $_SERVER['REQUEST_TIME'] - FLOOD_CONTROL_REPLY;
333 $stmt = $link->prepare('SELECT 1 FROM replies WHERE author_ip = ? AND time > ?');
334 $stmt->bind_param('si', $_SERVER['REMOTE_ADDR'], $too_early);
335 $stmt->execute();
337 $stmt->store_result();
338 if($stmt->num_rows > 0)
340 add_error('Wait at least ' . FLOOD_CONTROL_REPLY . ' seconds between each reply. ');
342 $stmt->close();
344 // Get letter, if applicable.
345 if($_SESSION['UID'] == $topic_author)
347 $poster_number = 0;
349 else // we are not the topic author
351 $stmt = $link->prepare('SELECT poster_number FROM replies WHERE parent_id = ? AND author = ? LIMIT 1');
352 $stmt->bind_param('is', $_GET['reply'], $author);
353 $stmt->execute();
354 $stmt->bind_result($poster_number);
355 $stmt->fetch();
356 $stmt->close();
358 // If the user has not already replied to this thread, get a new letter.
359 if(empty($poster_number))
361 // We need to lock the table to prevent others from selecting the same letter.
362 $unlock_table = true;
363 $link->real_query('LOCK TABLE replies WRITE');
365 $stmt = $link->prepare('SELECT poster_number FROM replies WHERE parent_id = ? ORDER BY poster_number DESC LIMIT 1');
366 $stmt->bind_param('i', $_GET['reply']);
367 $stmt->execute();
368 $stmt->bind_result($last_number);
369 $stmt->fetch();
370 $stmt->close();
372 if(empty($last_number))
374 $poster_number = 1;
376 else
378 $poster_number = $last_number + 1;
383 $stmt = $link->prepare('INSERT INTO replies (author, author_ip, poster_number, parent_id, body, time) VALUES (?, ?, ?, ?, ?, UNIX_TIMESTAMP())');
384 $stmt->bind_param('ssiis', $author, $_SERVER['REMOTE_ADDR'], $poster_number, $_GET['reply'], $body);
385 $congratulation = 'Reply posted.';
387 else // editing
389 $stmt = $link->prepare('UPDATE replies SET body = ?, edit_mod = ?, edit_time = UNIX_TIMESTAMP() WHERE id = ?');
390 $stmt->bind_param('sii', $body, $edit_mod, $_GET['edit']);
391 $congratulation = 'Reply edited.';
394 else { // or a topic...
395 check_length($headline, 'headline', MIN_LENGTH_HEADLINE, MAX_LENGTH_HEADLINE);
397 if( ! $editing)
399 //Lurk more?
400 if($_SERVER['REQUEST_TIME'] - $_SESSION['first_seen'] < REQUIRED_LURK_TIME_TOPIC)
402 add_error('Lurk for at least ' . REQUIRED_LURK_TIME_TOPIC . ' seconds before posting your first topic.');
405 // Flood control.
406 $too_early = $_SERVER['REQUEST_TIME'] - FLOOD_CONTROL_TOPIC;
407 $stmt = $link->prepare('SELECT 1 FROM topics WHERE author_ip = ? AND time > ?');
408 $stmt->bind_param('si', $_SERVER['REMOTE_ADDR'], $too_early);
409 $stmt->execute();
411 $stmt->store_result();
412 if($stmt->num_rows > 0)
414 add_error('Wait at least ' . FLOOD_CONTROL_TOPIC . ' seconds before creating another topic. ');
416 $stmt->close();
418 // Prepare our query...
419 $stmt = $link->prepare('INSERT INTO topics (author, author_ip, headline, body, last_post, time) VALUES (?, ?, ?, ?, UNIX_TIMESTAMP(), UNIX_TIMESTAMP())');
420 $stmt->bind_param('ssss', $author, $_SERVER['REMOTE_ADDR'], $headline, $body);
421 $congratulation = 'Topic created.';
423 else // editing
425 $stmt = $link->prepare('UPDATE topics SET headline = ?, body = ?, edit_mod = ?, edit_time = UNIX_TIMESTAMP() WHERE id = ?');
426 $stmt->bind_param('ssii', $headline, $body, $edit_mod, $_GET['edit']);
427 $congratulation = 'Topic edited.';
431 // If all is well, execute!
432 if( ! $erred) {
433 $stmt->execute();
435 if($unlock_table)
437 $link->real_query('UNLOCK TABLE');
440 if($stmt->affected_rows > 0)
442 // We did it!
443 if( ! $editing)
445 setcookie('last_bump', time(), $_SERVER['REQUEST_TIME'] + 315569260, '/');
446 if($reply)
448 // Update last bump.
449 $link->real_query("UPDATE last_actions SET time = UNIX_TIMESTAMP() WHERE feature = 'last_bump'");
451 $increment_replies = $link->prepare('UPDATE topics SET replies = replies + 1, last_post = UNIX_TIMESTAMP() WHERE id = ?');
452 $increment_replies->bind_param('i', $_GET['reply']);
453 $increment_replies->execute();
454 $increment_replies->close();
456 else // if topic
458 // Do not change the time() below to REQUEST_TIME. The script execution may have taken a second.
459 setcookie('last_topic', time(), $_SERVER['REQUEST_TIME'] + 315569260, '/');
460 //Update last topic and last bump, for people using the "date created" order option in the dashboard.
461 $link->real_query("UPDATE last_actions SET time = UNIX_TIMESTAMP() WHERE feature = 'last_topic' OR feature = 'last_bump'");
465 // Sort out what topic we're affecting and where to go next. Way too fucking long.
466 if( ! $editing)
468 $inserted_id = $stmt->insert_id;
470 if($reply)
472 $target_topic = $_GET['edit'];
473 $redir_loc = $_GET['reply'] . '#reply_' . $inserted_id;
475 else // if topic
477 $target_topic = $inserted_id;
478 $redir_loc = $inserted_id;
481 else // if editing
483 if($reply)
485 $target_topic = $_GET['reply'];
486 $redir_loc = $_GET['reply'] . '#reply_' . $_GET['edit'];
488 else // if topic
490 $target_topic = $_GET['edit'];
491 $redir_loc = $_GET['edit'];
495 // Take care of the upload.
496 if($uploading)
498 // Check if this image is already on the server.
499 $duplicate_check = $link->prepare('SELECT file_name FROM images WHERE md5 = ?');
500 $duplicate_check->bind_param('s', $image_data['md5']);
501 $duplicate_check->execute();
502 $duplicate_check->bind_result($previous_image);
503 $duplicate_check->fetch();
504 $duplicate_check->close();
506 // If the file has been uploaded before this, just link the old version.
507 if($previous_image)
509 $image_data['name'] = $previous_image;
511 // Otherwise, keep the new image and make a thumbnail.
512 else
514 thumbnail($_FILES['image']['tmp_name'], $image_data['name'], $image_data['type']);
515 move_uploaded_file($_FILES['image']['tmp_name'], 'img/' . $image_data['name']);
518 if($reply)
520 $insert_image = $link->prepare('INSERT INTO images (file_name, md5, reply_id) VALUES (?, ?, ?)');
522 else
524 $insert_image = $link->prepare('INSERT INTO images (file_name, md5, topic_id) VALUES (?, ?, ?)');
526 $insert_image->bind_param('ssi', $image_data['name'], $image_data['md5'], $inserted_id);
527 $insert_image->execute();
528 $insert_image->close();
531 // Add topic to watchlist if desired.
532 if($_POST['watch_topic'] && ! $watching_topic)
534 $add_watchlist = $link->prepare('INSERT INTO watchlists (uid, topic_id) VALUES (?, ?)');
535 $add_watchlist->bind_param('si', $_SESSION['UID'], $target_topic);
536 $add_watchlist->execute();
537 $add_watchlist->close();
540 // The random shit is only good for one post to prevent spambots from reusing the same form data again and again.
541 unset($_SESSION['random_posting_hashes']);
542 // Set the congratulation notice and redirect to affected topic or reply.
543 redirect($congratulation, 'topic/' . $redir_loc);
545 else // Our query failed ;_;
547 add_error('Database error.');
550 $stmt->close();
552 // If we erred, insert this into failed postings.
553 else
555 if($unlock_table)
557 $link->real_query('UNLOCK TABLE');
560 if($reply)
562 $add_fail = $link->prepare('INSERT INTO failed_postings (time, uid, reason, body) VALUES (UNIX_TIMESTAMP(), ?, ?, ?)');
563 $add_fail->bind_param('sss', $_SESSION['UID'], serialize($errors), substr($body, 0, MAX_LENGTH_BODY));
565 else
567 $add_fail = $link->prepare('INSERT INTO failed_postings (time, uid, reason, body, headline) VALUES (UNIX_TIMESTAMP(), ?, ?, ?, ?)');
568 $add_fail->bind_param('ssss', $_SESSION['UID'], serialize($errors), substr($body, 0, MAX_LENGTH_BODY), substr($headline, 0, MAX_LENGTH_HEADLINE));
570 $add_fail->execute();
571 $add_fail->close();
576 print_errors();
578 // For the bot check.
579 $start_time = $_SERVER['REQUEST_TIME'];
580 if( ctype_digit($_POST['start_time']) )
582 $start_time = $_POST['start_time'];
585 echo '<div>';
587 // Check if OP.
588 if($reply && ! $editing)
590 echo '<p>You <strong>are';
591 if($_SESSION['UID'] !== $topic_author)
593 echo ' not';
595 echo '</strong> recognized as the original poster of this topic.</p>';
598 // Print deadline for edit submission.
599 if($editing && TIME_TO_EDIT != 0 && ! $moderator && ! $administrator)
601 echo '<p>You have <strong>' . calculate_age( $_SERVER['REQUEST_TIME'], $edit_data['time'] + TIME_TO_EDIT ) . '</strong> left to finish editing this post.</p>';
604 // Print preview.
605 if($_POST['preview'] && ! empty($body))
607 $preview_body = parse($body);
608 $preview_body = preg_replace('/^@([0-9,]+|OP)/m', '<span class="unimportant"><a href="#">$0</a></span>', $preview_body);
609 echo '<h3 id="preview">Preview</h3><div class="body standalone">' . $preview_body . '</div>';
612 // Check if any new replies have been posted since we last viewed the topic.
613 if($reply && isset($visited_topics[ $_GET['reply'] ]) && $visited_topics[ $_GET['reply'] ] < $topic_replies)
615 $new_replies = $topic_replies - $visited_topics[$_GET['reply']];
616 echo '<p><a href="/topic/' . $_GET['reply'] . '#new"><strong>' . $new_replies . '</strong> new repl' . ($new_replies == 1 ? 'y</a> has' : 'ies</a> have') . ' been posted in this topic since you last checked!</p>';
619 // Print the main form.
623 <form action="" method="post"<?php if(ALLOW_IMAGES) echo ' enctype="multipart/form-data"' ?>>
624 <div class="noscreen">
625 <input name="form_sent" type="hidden" value="1" />
626 <input name="e-mail" type="hidden" />
627 <input name="start_time" type="hidden" value="<?php echo $start_time ?>" />
628 <?php
629 // For the bot check.
630 if( ! is_array($_SESSION['random_posting_hashes']) )
632 for($i = 0, $max = mt_rand(3, 12); $i < $max; ++$i)
634 $_SESSION['random_posting_hashes'][ dechex(mt_rand()) ] = dechex(mt_rand());
638 foreach($_SESSION['random_posting_hashes'] as $name => $value)
640 $attributes = array
642 'name="' . $name . '"',
643 'value="' . $value . '"',
644 'type="hidden"'
646 // To make life harder for bots, print the elements in a random order.
647 shuffle($attributes);
648 echo '<input ' . implode(' ', $attributes) . ' />' . "\n\t\t\t";
652 </div>
654 <?php if( ! $reply): ?>
655 <div class="row">
656 <label for="headline">Headline</label> <script type="text/javascript"> printCharactersRemaining('headline_remaining_characters', 100); </script>
657 <input id="headline" name="headline" tabindex="1" type="text" size="124" maxlength="100" onkeydown="updateCharactersRemaining('headline', 'headline_remaining_characters', 100);" onkeyup="updateCharactersRemaining('headline', 'headline_remaining_characters', 100);" value="<?php if($_POST['form_sent'] || $editing) echo htmlspecialchars($headline) ?>">
658 </div>
659 <?php endif; ?>
661 <div class="row">
662 <label for="body" class="noscreen">Post body</label>
663 <textarea name="body" cols="120" rows="18" tabindex="2" id="body"><?php
664 // If we've had an error or are previewing, print the submitted text.
665 if($_POST['form_sent'] || $editing)
667 echo sanitize_for_textarea($body);
670 // Otherwise, fetch any text we may be quoting.
671 else if(isset($_GET['quote_topic']) || ctype_digit($_GET['quote_reply']))
673 // Fetch the topic...
674 if(isset($_GET['quote_topic']))
676 $stmt = $link->prepare('SELECT body FROM topics WHERE id = ?');
677 $stmt->bind_param('i', $_GET['reply']);
679 // ... or a reply.
680 else
682 echo '@' . number_format($_GET['quote_reply']) . "\n\n";
684 $stmt = $link->prepare('SELECT body FROM replies WHERE id = ?');
685 $stmt->bind_param('i', $_GET['quote_reply']);
688 // Execute it.
689 $stmt->execute();
690 $stmt->bind_result($quoted_text);
691 $stmt->fetch();
692 $stmt->close();
694 // Snip citations from quote.
695 $quoted_text = trim( preg_replace('/^@([0-9,]+|OP)/m', '', $quoted_text) );
697 //Prefix newlines with >
698 $quoted_text = preg_replace('/^/m', '> ', $quoted_text);
700 echo sanitize_for_textarea($quoted_text) . "\n\n";
703 // If we're just citing, print the citation.
704 else if(ctype_digit($_GET['cite']))
706 echo '@' . number_format($_GET['cite']) . "\n\n";
709 echo '</textarea>';
711 if(ALLOW_IMAGES && ! $editing)
713 echo '<label for="image" class="noscreen">Image</label> <input type="file" name="image" id="image" />';
717 <p><a href="/markup_syntax">Markup syntax</a>: <kbd>''</kbd> on each side of a word or part of text = <em>emphasis</em>. <kbd>'''</kbd> = <strong>strong emphasis</strong>. <kbd>></kbd> on the beginning of a line = quote. To mass quote a long section of text, surround it with <kbd>[quote]</kbd> tags. <abbr>URL</abbr>s are automatically linkified.</p>
718 </div>
720 <?php
721 if( ! $watching_topic)
723 echo '<div class="row"><label for="watch_topic" class="inline">Watch topic</label> <input type="checkbox" name="watch_topic" id="watch_topic" class="inline"';
724 if($_POST['watch_topic'])
726 echo ' checked="checked"';
728 echo ' /></div>';
730 if($administrator && ! $editing)
732 echo '<div class="row"><label for="admin" class="inline">Post as admin</label> <input type="checkbox" name="admin" id="admin" class="inline"></div>';
737 <div class="row">
738 <input type="submit" name="preview" tabindex="3" value="Preview" class="inline"<?php if(ALLOW_IMAGES) echo ' onclick="document.getElementById(\'image\').value=\'\'"' ?> />
739 <input type="submit" name="post" tabindex="4" value="<?php echo ($editing) ? 'Update' : 'Post' ?>" class="inline">
740 </div>
741 </form>
742 </div>
744 <?php
746 // If citing, fetch and display the reply in question.
747 if(ctype_digit($_GET['cite']))
749 $stmt = $link->prepare('SELECT body, poster_number FROM replies WHERE id = ?');
750 $stmt->bind_param('i', $_GET['cite']);
751 $stmt->execute();
752 $stmt->bind_result($cited_text, $poster_number);
753 $stmt->fetch();
754 $stmt->close();
756 if( ! empty($cited_text))
758 $cited_text = parse($cited_text);
760 // Linkify citations within the text.
761 preg_match_all('/^@([0-9,]+)/m', $cited_text, $matches);
762 foreach($matches[0] as $formatted_id)
764 $pure_id = str_replace( array('@', ',') , '', $formatted_id);
766 $cited_text = str_replace($formatted_id, '<a href="/topic/' . $_GET['reply'] . '#reply_' . $pure_id . '" class="unimportant">' . $formatted_id . '</a>', $cited_text);
769 // And output it!
770 echo '<h3 id="replying_to">Replying to Anonymous ' . number_to_letter($poster_number) . '&hellip;</h3> <div class="body standalone">' . $cited_text . '</div>';
773 // If we're not citing or quoting, display the original post.
774 else if($reply && ! isset($_GET['quote_topic']) && ! isset($_GET['quote_reply']) && ! $editing)
776 $stmt = $link->prepare('SELECT body FROM topics WHERE id = ?');
777 $stmt->bind_param('i', $_GET['reply']);
778 $stmt->execute();
779 $stmt->bind_result($cited_text);
780 $stmt->fetch();
781 $stmt->close();
783 echo '<h3 id="replying_to">Original post</h3> <div class="body standalone">' . parse($cited_text) . '</div>';
786 require('includes/footer.php');