Файл: wboard/source/system/controller/board.php
Строк: 194
<?php
/**
* Wboard
* Display boards or threads. Edit/Remove board.
* @author Screamer
* @copyright 2013
*/
class Module_Board extends Module
{
/**
* Index of Board
* @return (void)
*/
public function index()
{
$this->redirect('w_action/err');
}
/**
* Display items of board or thread
* @param (string) $name Name of board
* @param (int) $thread ID of thread
* @return (void)
*/
public function view($name = '', $thread = 0)
{
$board = $this->model->get_board($name);
$thread = intval($thread);
if (!is_array($board)) {
// Board is not exists
$this->redirect('w_action/err');
}
$board['name'] = htmlspecialchars($board['name']);
$this->tpl->title = $this->settings['title'] . ' - /' . $board['name'] . '/';
// Check IP for ban
if ($this->model->check_ban_ip($this->ip) || $this->model->check_ban_ip($this->ip_via_proxy)) {
$form = $this->tpl->load('_message', array('message' => $this->lng->your_ip_banned));
}
// Path to thread
$path = $this->path . 'files' . DIRECTORY_SEPARATOR . 'boards' . DIRECTORY_SEPARATOR
. $board['name'] . DIRECTORY_SEPARATOR . 'res' . DIRECTORY_SEPARATOR;
if ($thread != 0) {// Display thread
// Get thread
$thread = $this->model->get_thread($board['name'], $thread);
if (!is_array($thread)) {
// Thread is not exists
$this->redirect('w_action/err');
}
if (is_file($path . $thread['id'] . '.json')) {
$posts = json_decode(file_get_contents($path . $thread['id'] . '.json'), TRUE);
// Check for bump limit
if (sizeof($posts) >= $board['bump_limit']) {
$form = $this->tpl->load('_message', array('message' => $this->lng->thread_closed_by_bump_limit));
}
} else {
$this->redirect('w_action/err');
}
// Deal of posts before bump-limit
$posts_remains = $board['bump_limit'] - sizeof($posts);
$posts_remains = $posts_remains < 0 ? 0 : $posts_remains;
// Set output
$output = array(
'board' => $board['name'],
'tid' => intval($thread['id']),
'list' => $this->helper->display_posts($board['name'], $thread['id'], $posts),
'delete' => $this->is_root ? 'w_action/remove/index/' . $board['name'] . '/' . $thread['id'] : '',
'posts_remains' => $posts_remains,
);
// Name of template
$tpl = 'board_view_thread';
} else { // Display board
$top_menu = array();
if ($this->is_root) {
// Admin's menu [(edit|remove) board]
$top_menu[] = anchor('w_action/panel/index/board/' . $board['name'], $this->lng->edit_board);
$top_menu[] = anchor('w_action/remove/board/' . $board['name'], $this->lng->remove_board);
}
// Set output
$output = array(
'name' => $board['name'],
'description' => htmlspecialchars($board['description']),
'rules' => nl2br(htmlspecialchars($board['rules'])),
'top_menu' => $top_menu,
'list' => $this->helper->display_threads($this->model->get_threads($board['name'])),
'board_settings' => sprintf($this->lng->board_settings, $board['thread_ph'], $board['max_threads']),
);
// Name of template
$tpl = 'board_view';
if (!isset($form)) {
// Limit threads per hour
if ($this->model->wipe_protect($board['name'], $board['thread_ph']) === FALSE) {
$form = $this->tpl->load('_message', array('message' => sprintf($this->lng->error_limit_thread_per_hour, $board['thread_ph'])));
}
}
}
// Send message; load form;
if (!isset($form)) {
$error = array();
$data = array('theme' => '', 'name' => '', 'post' => '');
if (!empty($_POST)) {
$sage = isset($_POST['sage']) ? 1 : 0; // Sage (not bump thread)
// Check captcha
if ($this->settings['captcha'] == 1) {
$captcha = isset($_POST['captcha']) ? trim($_POST['captcha']) : '';
$_SESSION['captcha'] = isset($_SESSION['captcha']) ? $_SESSION['captcha'] : '';
if (empty($captcha) || empty($_SESSION['captcha']) || ($captcha != $_SESSION['captcha'])) {
$error['captcha'] = $this->lng->wrong_captcha;
}
}
// Get data
foreach ($data as $key => $value) {
$data[$key] = isset($_POST[$key]) ? trim($_POST[$key]) : $value;
}
// Check theme
if (strlen($data['theme']) > 300) {
$error['theme'] = sprintf($this->lng->wrong_len, 0, 150);
}
if (empty($data['theme']) && $thread == 0) {
$data['theme'] = $this->lng->untitled_thread;
}
// Check name
if (strlen($data['name']) > 50) {
$error['name'] = sprintf($this->lng->wrong_len_more, 25);
}
if (empty($data['name'])) {
$data['name'] = $this->lng->anonymous;
}
// Check post
if (empty($data['post']) || strlen($data['post']) > 10000) {
$error['post'] = sprintf($this->lng->wrong_len, 1, 5000);
}
// Check file
if (isset($_FILES['file'])) {
$file = $this->helper->prepare_file($board['name'], $_FILES['file']);
if (is_string($file)) {
$error['file'] = $file;
}
if (isset($error['post']) && $file !== NULL) { // Allow write image only
unset($error['post']);
}
}
if (empty($error)) {
// ID of post
$pid = $board['posts'] + 1;
// Get posts (for set backlinks)
preg_match_all('~>>([d]+)~ius', $data['post'], $messages);
if (!empty($messages[1])) {
$messages = $messages[1];
foreach ($messages as $mid) {
if (isset($posts[$mid])) {
$posts[$mid]['answers'][] = $pid;
}
}
}
// Handle message
$db_post = mb_substr($data['post'], 0, 300) . (mb_strlen($data['post']) > 300 ? '...' : '');
$db_post = $this->helper->markup_message($db_post, $board['name'], (is_array($thread) ? $thread['id'] : $pid));
$data['post'] = $this->helper->markup_message($data['post'], $board['name'], (is_array($thread) ? $thread['id'] : $pid));
if (!is_array($thread)) {
// Create thread
$this->model->create_thread($pid, $board['name'], $data['theme'], time(), $data['name'], $db_post, $board['hidden']);
$posts = array();
$tid = $pid;
} else {
// Get ID of created thread
$tid = $thread['id'];
}
// Update counter of posts in the board
$this->model->board_post_count($board['name']);
// Bump thread
if ($sage == 0 || ($sage == 1 && !is_array($thread))) {
$this->model->bump_thread($board['name'], $tid, (!is_array($thread) ? '' : $db_post));
}
$data['name'] = htmlspecialchars($data['name'], ENT_QUOTES, 'UTF-8');
// Tripcode
if (preg_match('~[#|!](.*)~ius', $data['name'], $password)) {
// Get secure if exists
preg_match('~(.*)[#|!]{2}(.*)~ius', $password[1], $secure);
$password = isset($secure[1]) ? $secure[1] : $password[1];
$secure = isset($secure[2]) ? $secure[2] : FALSE;
$tripcode = '';
if (!empty($password)) {
// Salt
$salt = preg_replace("/[^.-z]/", ".", substr($password."H.", 1, 2));
$salt = strtr($salt, ":;<=>?@[\]^_`", "ABCDEFGabcdef");
// Gen tripcode
$tripcode = '!' . substr(crypt($password, $salt), -10);
}
// Secure
if ($secure !== FALSE) {
$tripcode .= (!empty($tripcode) ? '!' : '') . '!' . substr(str_rot13(base64_encode(md5(sha1($secure)))), 2, 10);
}
$data['name'] = preg_replace(
'~[#|!](.*)~ius',
'<span class="tripcode">' . $tripcode . '</span>',
$data['name']
);
}
if ($sage == 1) {
$data['name'] = '<span class="sage">sage</span> ' . $data['name'];
}
// Admin's sign
if ($this->is_root && !empty($_POST['admin_sign'])) {
$data['name'] .= '<span class="admin_sign">@' . htmlspecialchars($_POST['admin_sign']) . '</span>';
}
// Attach file
if (isset($file)) {
$tmp_file = $this->helper->save_file($board['name'], $file);
if (!is_array($tmp_file)) {
unset($file);
} else {
$file['size'] = $file['size'] >= 1073741824
? round($file['size'] / 1073741824 * 100) / 100 . ' Gb'
: ($file['size'] >= 1048576
? round($file['size'] / 1048576 * 100) / 100 . ' Mb'
: ($file['size'] >= 1024
? round($file['size'] / 1024 * 100) / 100 . ' Kb'
: $file['size'] . ' bytes'
)
);
$file = array(
'file' => $tmp_file['file'],
'preview' => $tmp_file['preview'],
'size' => strtoupper($file['ext']),
'ext' => $file['size'],
'resolution' => $file['width'] . 'x' . $file['height'],
);
}
}
// Add post data to list of posts
$posts[$pid] = array(
'id' => $pid,
'theme' => htmlspecialchars($data['theme'], ENT_QUOTES, 'UTF-8'),
'name' => $data['name'],
'text' => $data['post'],
'time' => $this->helper->display_time(time()),
'img' => isset($file) ? $file : array(),
'answers' => array(),
'user_data' => long2ip($this->ip)
. ($this->ip_via_proxy != 0 ? ' / ' . long2ip($this->ip_via_proxy) : '')
. ' [' . $this->user_agent . ']',
);
// Write posts
file_put_contents($path . $tid . '.json', json_encode($posts));
// Remove old threads
$this->model->remove_old_threads($board['name'], $board['max_threads']);
// Redirect to thread
$this->redirect($board['name'] . '/' . $tid . '/#down');
}
}
$form = $this->tpl->load('board_write', array(
'error' => $error,
'data' => $data,
'admin_sign' => $this->is_root,
'display_captcha' => $this->settings['captcha'],
));
}
$output['form'] = $form;
$this->tpl->set_output($this->tpl->load($tpl, $output));
}
/**
* Update thread (for AJAX request)
* Get list of posts
* @param (string) $board Name of board
* @param (int) $tid ID of thread
* @return (void)
*/
public function update_thread($board = '', $tid = 0)
{
$return = '';
$this->display = FALSE;
$tid = intval($tid);
if (!preg_match('/[^da-z]+/iu', $board)) {
$file = $this->path . 'files' . DIRECTORY_SEPARATOR . 'boards' . DIRECTORY_SEPARATOR . $board . DIRECTORY_SEPARATOR . 'res' . DIRECTORY_SEPARATOR . $tid . '.json';
if (is_file($file)) {
$return = $this->helper->display_posts($board, $tid, json_decode(file_get_contents($file), TRUE));
}
}
header("Content-type: text/plain;");
echo $return;
}
}