bibis/common.php

199 行
4.7 KiB
PHP

<?php
if (BIBIS_DEBUG) {
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
}
define('GUEST_ID', '-');
define('NOREPLY_ID', '-');
define('GUESTNAME', 'GUEST');
define('DELETEDNAME', 'DELETED');
define('DELETEDTEXT', 'この書き込みは削除されました。');
define('ACCEPT_IMAGE_TYPE', ['image/png', 'image/jpeg', 'image/gif']);
define('SESSION_NAME', 'bibis');
date_default_timezone_set('UTC');
ini_set('zlib.output_compression', 1);
if (OPEN_BASEDIR != '') {
ini_set('open_basedir', OPEN_BASEDIR);
}
session_name(SESSION_NAME);
session_start(['cookie_httponly' => true]);
set_csrf_token();
// HTTP
function get_fp() {
return md5(
($_SERVER['HTTP_USER_AGENT'] ?? '')
. ($_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? '')
. ($_SERVER['HTTP_ACCEPT_ENCODING'] ?? '')
. ($_SERVER['HTTP_ACCEPT'] ?? '')
);
}
function has_cookie() {
return isset($_COOKIE['bibis']);
}
function on_error($code, $errors) {
http_response_code(400);
if (function_exists('bibis_http_header')) { bibis_http_header(); }
$view['errors'] = $errors;
require(__DIR__ . '/view/header.php');
exit;
}
function output_html($view, $_components) {
if (function_exists('bibis_http_header')) { bibis_http_header(); }
foreach ($_components as $_name) {
require(__DIR__ . "/view/$_name");
}
exit;
}
// CSRF token
function set_csrf_token() {
if (empty($_SESSION['csrf_token'])) {
$_SESSION["csrf_token"] = bin2hex(random_bytes(32));
}
}
function get_csrf_token() {
if (!REQUIRE_COOKIE && !isset($_SESSION['user'])) {
$date = date('YmdH');
return $date . get_fp();
}
return $_SESSION['csrf_token'] ?? null;
}
function get_csrf_token_2($force_cookie = false) {
if (!REQUIRE_COOKIE && !isset($_SESSION['user'])) {
$date = date('YmdH', strtotime('-1 hour'));
return $date . get_fp();
}
return $_SESSION['csrf_token'] ?? null;
}
function get_csrf_token_hashed($prefix = '', $token = null) {
if ($token === null) { $token = get_csrf_token(); }
if ($token === null) { return null; }
return md5($prefix . $token);
}
function check_csrf_token() {
$hashed = get_csrf_token_hashed();
$hashed_2 = get_csrf_token_hashed('', get_csrf_token_2());
if ($hashed === null || $hashed_2 === null) { return ['CSRF トークンが不正。要再試行。']; }
$token_key = get_csrf_token_hashed('csrf_token');
$csrf_token = $_POST[$token_key] ?? '';
if ($csrf_token !== $hashed && $csrf_token !== $hashed_2) { return ['CSRF トークンが不正。要再試行。']; }
return [];
}
function output_csrf_token_hidden() {
$hashed = get_csrf_token_hashed();
if ($hashed === null) { return ''; }
$token_key = get_csrf_token_hashed('csrf_token');
return '<input type="hidden" name="' . htmlspecialchars($token_key) . '" value="' . $hashed . '">';
}
// String
function url_to_link($s) {
return preg_replace(
'/((http|https):\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&amp;:\/~+#-]*[\w@?^=%&amp;\/~+#-])?)/',
'<a href="\1" rel="noopener noreferrer">\1</a>',
$s
);
}
function mbtrim($s) {
return preg_replace('/^\s+|\s+$/u', '', $s);
}
function twochan_trip($tripkey) {
// twochan_trip('atomikka') -> '◆.../5Betyws'
// Thanks: https://refirio.org/view/62
// Test data: https://trip-table.kokage.cc/sample01.php
$tripkey = mb_convert_encoding($tripkey, 'sjis-win');
$salt = substr($tripkey . 'H.', 1, 2);
$salt = preg_replace('/[^\.-z]/', '.', $salt);
$salt = strtr($salt, ':;<=>?@[\\]^_`', 'ABCDEFGabcdef');
$trip = crypt($tripkey, $salt);
$trip = substr($trip, -10);
return '◆' . $trip;
}
function parse_key_value($s, $key_list) {
$result = [];
$lines = explode(PHP_EOL, $s);
foreach ($lines as $line) {
foreach ($key_list as $key) {
if (strpos($line, "{$key}=") === 0) {
$value = explode("{$key}=", $line, 2)[1] ?? null;
$result[$key] = $value;
$value = null;
}
}
$key = null;
}
$lines = null;
$line = null;
return $result;
}
// File
function mkdir_p($path, $permission = 0700) {
if (file_exists($path)) { return true; }
return mkdir($path, $permission);
}
function get_image_type($s) {
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$type = finfo_buffer($finfo, $s);
if (isset($type) && in_array($type, ACCEPT_IMAGE_TYPE)) {
return $type;
}
return null;
}
function sitebase($path = '') {
return SITEBASE . $path;
}
function get_style_css() {
if (THEME === null || THEME === '') { return sitebase('style.css'); }
return sitebase('theme/' . THEME);
}
// Limit and permission
function can_post() {
if (!post_limited()) { return false; }
if (!ENABLE_GUEST && !isset($_SESSION['user'])) { return false; }
return true;
}
function post_limited() {
return ENABLE_POST && (count_post_today() < POST_LIMIT_PER_DAY) && (count_post() < POST_LIMIT);
}
function can_regist() {
return ENABLE_REGISTER;
}