Файл: 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;
    }
}