first commit

This commit is contained in:
統計部員2 2023-09-28 02:07:30 +09:00
commit bfe5acd27b
97 changed files with 7030 additions and 0 deletions

6
.htaccess Normal file
View File

@ -0,0 +1,6 @@
<FilesMatch "\.html$">
Header set Content-Type 'text/html; charset=UTF-8'
</FilesMatch>
<FilesMatch "\.js$">
Header set Content-Type 'application/javascript; charset=UTF-8'
</FilesMatch>

13
LICENSE.txt Normal file
View File

@ -0,0 +1,13 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2023 nore <webmaster@rentalbbs.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.

4
README.md Normal file
View File

@ -0,0 +1,4 @@
Details: https://delight.rentalbbs.net/delight.html
# Lisence
The license in the LICENSE.txt file applies, unless a separate license is listed in the source code.

BIN
b1.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

24
bbsmenu.php Normal file
View File

@ -0,0 +1,24 @@
<HTML>
<HEAD>
<META http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
<TITLE>BBS MENU for <?=$_SERVER['HTTP_HOST']?></TITLE>
<BASE TARGET="_blank">
</HEAD>
<BODY BGCOLOR="SEASHELL" TEXT="#E60565" LINK="#444494" ALINK="#a99999" VLINK="#444494">
<font size="2">
<br><br><B><?=$_SERVER['HTTP_HOST']?></B><br>
<?php
$dir = './';
$list1 = glob($dir . '*', GLOB_ONLYDIR);
$count = 0;
foreach ($list1 as $dir1) {
++$count;
$dir1 = substr($dir1, 1)."/";
if ($dir1 == "/test/" || $dir1 == "/static/" || $dir1 == "/images/") continue;
echo '<A HREF="http://'.$_SERVER['HTTP_HOST'].$dir1.'">'.$dir1.'</A>';
if ($count != count($list1)) echo "<br>";
echo "\n";
}
?></FONT>
</BODY>
</HTML>

BIN
g1.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
images/btn4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
images/close.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

BIN
images/icon_close.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 B

BIN
images/loading.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

BIN
images/next.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 986 B

BIN
images/prev.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

37
index.html Normal file
View File

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
<meta name="application-name" content="delight">
<link rel="apple-touch-icon" href="icon.png">
<link rel="icon" href="favicon.ico">
<meta name="referrer" content="origin">
<script type="text/javascript" src="/static/jquery-1.11.3.min.js"></script>
<link href="/static/st.css" rel="stylesheet" type="text/css">
<link href="/static/milligram.css" rel="stylesheet" type="text/css">
<link href="/static/s.css" rel="stylesheet" type="text/css">
<link href="/static/read.css" rel="stylesheet" type="text/css">
</head>
<body>
<section class="section">
<div id="body">
<script type="text/javascript" src="/static/thread.js"></script>
<div id="followheader" class="hidden maxwidth100 height2p5 stickymenu container" style="display: block;"><div class="row noflex maxwidth100 white padding0p5 maxheight2p5 borderbottomlightgrey"><div class="topmenu" id="header"></div></div></div>
<div class="title" id="title"></div>
<div class="pagestats" id="count"></div>
<div class="search"><input type="text" id="searchInput" placeholder="スレ内検索" onchange="search()"></div>
<div class="thread" id="thread">
<noscript><p>JavaScriptを有効にしてください<br>Please turn on your JavaScript</p></noscript>
</div>
<div class="newposts"><center><a href="javascript:load()">リロード<img alt="再読み込み" loading="lazy" decoding="async" data-nimg="1" style="color: transparent;" src="/static/reload.svg" width="16" height="16"></a></center><hr></div><div class="bottommenu"></div><div class="formbox" style="display:none"><form method="POST" accept-charset="UTF-8" action="/test/post-v2.php"><div class="fbox" style="max-width: 600px;"><span class="fhead"><span class="spformhead" style="display:none;border-radius:3px 3px 0 0;color:#666;padding:3px;"><span style="padding-top: 10px;display: inline-block;" onclick="fclose()">キャンセル</span></span><span class="submitbtn"><input type="submit" value="新規投稿" name="submit" onclick="Post()"></span></span><span class="input" style="display: block;"><a id="iconlink" target="_blank"><img id="icon" class="icon" width="50" height="50" align="left"></a><input name="name" style="width:50%;" placeholder="名前"></span><span class="input"><input name="mail" size="19" value="" placeholder="E-mail"></span><div class="backmsg" style="display: inline-block;"><input value="on" type="checkbox" id="seticon" name="icon" checked><a href="/test/icon.html">アイコン</a> <a href="javascript:BackMSG()">下書きを復元</a></div><textarea rows="5" cols="70" wrap="off" name="comment"></textarea><br>画像:<input id="uploadImage" type="file" name="file" size="50" onchange="upload();"><br></div></form></div>
<div id="hidemetoo" class="side p85 slightpad nobullets">
<div style="min-height:50px" id="rule">■ ローカルルール<br></div>
<div style="min-height:50px" id="kokuti">■ 告知欄<br></div>
<p style="margin: 5rem 0"></p>
</div>
<script type="text/javascript" src="/static/read.js"></script>
<div class="footer">We're sure you'll have a good time with delight and/or 3ch. :)</div>
</div></section>
</body>
</html>

0
index2.html Normal file
View File

76
static/a.css Normal file
View File

@ -0,0 +1,76 @@
body {background: #fafafa;color: #333;font-size: 14px;word-break: break-word;overflow-wrap: break-word;overscroll-behavior-y: contain;}
.section-subtitle {font-size: 12px;font-size: 1.2rem;background: #333;padding: 6px 10px;margin: 0;color: #fff;font-weight: normal;}
.contents {padding: 10px;}
.form-control {display: block;width: 100%;margin-top: 5px;height: 34px;font-size: 14px;line-height: 1.42857143;color: #555555;background-color: #ffffff;background-image: none;border: 1px solid #cccccc;border-radius: 4px;-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);-webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;-o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;}
.notice, p.notice {font-size: 12px;color: #999;line-height: 1.4;}
.btn-primary:hover {color: #ffffff;background-color: #286090;border-color: #204d74;}
.btn:hover, .btn:focus, .btn.focus {color: #333333;text-decoration: none;}
.btn-block {display: block;width: 100%;}
.btn-lg, .btn-group-lg > .btn {padding: 10px 16px;font-size: 18px;line-height: 1.3333333;border-radius: 6px;}
.btn {display: inline-block;margin-bottom: 0;font-weight: normal;text-align: center;vertical-align: middle;-ms-touch-action: manipulation;touch-action: manipulation;cursor: pointer;background-image: none;border: 1px solid transparent;white-space: nowrap;padding: 6px 12px;font-size: 14px;line-height: 1.42857143;border-radius: 4px;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;}
.font-weight-normal {
font-weight: 400 !important;
}
.mb-3 {
margin-bottom: 1rem !important;
font-size: 1.75rem;
}
button, input, optgroup, select, textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button, input {
overflow: visible;
}
[type="button"], [type="reset"], [type="submit"], button {
-webkit-appearance: button;
}
.btn {
display: inline-block;
font-weight: 400;
color: #212529;
text-align: center;
vertical-align: middle;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-color: transparent;
border: 1px solid transparent;
padding: .375rem .75rem;
font-size: 1rem;
line-height: 1.5;
border-radius: .25rem;
transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;
}
.btn-primary {
color: #fff;
background-color: #007bff;
border-color: #007bff;
}
.btn-group-lg > .btn, .btn-lg {
padding: .5rem 1rem;
font-size: 1.25rem;
line-height: 1.5;
border-radius: .3rem;
}
.btn-block {
display: block;
width: 100%;
}
.btn-primary {
background-color: #48526b !important;
border-color: #48526b;
}
button.link-style-btn{
cursor: pointer;
border: none;
background: none;
color: #0033cc;
}
button.link-style-btn:hover{
text-decoration: underline;
color: #002080;
}

13
static/ares.svg Normal file
View File

@ -0,0 +1,13 @@
<!--?xml version="1.0" encoding="utf-8"?-->
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="_x32_" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 512 512" style="width: 16px; height: 16px; opacity: 1;" xml:space="preserve">
<style type="text/css">
.st0{fill:#4B4B4B;}
</style>
<g>
<path class="st0" d="M442.539,73.946c-44.84-37.927-108.949-60.084-187.344-60.066c-74.388,0-137.905,20.981-183.328,58.411 c-22.702,18.686-40.758,41.492-53.06,67.428C6.489,165.648-0.019,194.641,0,225.422c-0.019,37.214,7.768,71.586,23.511,101.577 c14.99,28.664,37.297,53.04,65.699,72.103c-6.715,28.269-16.157,68.67-16.157,68.689c-0.432,1.815-0.658,3.706-0.639,5.624 c-0.018,7.59,3.518,14.897,9.667,19.608l0.038,0.028v0.01c4.402,3.348,9.705,5.06,15.01,5.06c3.988,0,8.031-0.969,11.68-2.934 l0.358-0.188l0.357-0.216c0.019-0.009,5.079-3.01,12.866-7.618c11.661-6.903,29.435-17.407,45.291-26.745 c7.919-4.665,15.367-9.038,21.31-12.508c5.924-3.46,10.476-6.103,12.17-7.034l0.075-0.047l0.112-0.065 c22.1-12.527,39.705-14.634,53.849-14.709c58.702-0.085,121.212-11.464,171.13-42.62c24.902-15.602,46.57-36.413,61.806-63.056 c15.272-26.624,23.886-58.853,23.868-96.16C512.112,165.545,487.416,111.78,442.539,73.946z M454.709,301.24 c-8.822,15.376-20.37,28.316-34.232,39.282c-20.784,16.429-46.871,28.288-75.479,35.934c-28.598,7.664-59.652,11.088-89.802,11.078 c-18.508-0.075-44.369,3.414-72.752,19.684v-0.01c-3.141,1.749-10.137,5.822-19.354,11.219 c-13.222,7.759-30.62,18.019-45.14,26.614c3.536-15.094,7.656-32.576,10.721-45.413v-0.019c0.508-2.144,0.884-4.468,0.884-7.11 c0.038-3.724-0.922-8.266-3.065-12.046c-1.6-2.831-3.65-5.06-5.436-6.583c-2.746-2.285-4.796-3.273-5.944-3.903l-1.166-0.592 l-0.132-0.075c-25.147-16.204-43.655-36.329-56.18-60.188c-12.527-23.897-19.11-51.781-19.11-83.69 c0-25.401,5.285-48.526,15.084-69.187c14.708-30.94,39.667-56.605,73.786-74.896c34.082-18.254,77.398-28.937,127.805-28.937 c71.284,0.019,125.933,20.031,162.46,50.952c36.47,31.025,55.692,72.799,55.824,120.864 C473.442,255.723,466.407,280.729,454.709,301.24z" style="fill: rgb(75, 75, 75);"/>
<path class="st0" d="M135.055,197.171c-16.278,0-29.472,13.204-29.472,29.483c0,16.278,13.194,29.473,29.472,29.473 c16.288,0,29.482-13.194,29.482-29.473C164.538,210.375,151.344,197.171,135.055,197.171z" style="fill: rgb(75, 75, 75);"/>
<path class="st0" d="M250.024,197.171c-16.28,0-29.474,13.204-29.474,29.483c0,16.278,13.194,29.473,29.474,29.473 c16.288,0,29.482-13.194,29.482-29.473C279.506,210.375,266.312,197.171,250.024,197.171z" style="fill: rgb(75, 75, 75);"/>
<path class="st0" d="M365,197.171c-16.278,0-29.482,13.204-29.482,29.483c0,16.278,13.204,29.473,29.482,29.473 c16.288,0,29.484-13.194,29.484-29.473C394.484,210.375,381.288,197.171,365,197.171z" style="fill: rgb(75, 75, 75);"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

46
static/board.js Normal file
View File

@ -0,0 +1,46 @@
let threadmode = false;
path = location.pathname.split('/');
if (!path[1]) {
path = location.hash.split('/');
bbs = path[0].replace('#', '');
threadmode = true;
}else bbs = path[1];
setfile = '/'+bbs+'/setting.json';
rulefile = '/'+bbs+'/head.txt';
kokutifile = '/'+bbs+'/kokuti.txt';
const sroad = new XMLHttpRequest();
sroad.open('get', setfile);
sroad.send();
sroad.onreadystatechange = function() {
if(sroad.readyState === 4 && sroad.status === 200) {
const setting = JSON.parse(this.responseText);
if (setting['BBS_TITLE'] && !threadmode) {
if (document.getElementById('headtitle')) document.getElementById('headtitle').innerHTML = setting['BBS_TITLE'];
if (document.getElementById('subbacktitle')) document.getElementById('subbacktitle').innerHTML = setting['BBS_TITLE'];
document.title = setting['BBS_TITLE']+' | '+location.hostname;
}
if (setting['background']) {
document.body.style.background = setting['background'];
}
}
}
if (document.getElementById('rule')) {
const lroad = new XMLHttpRequest();
lroad.open('get', rulefile);
lroad.send();
lroad.onreadystatechange = function() {
if(lroad.readyState === 4 && lroad.status === 200) {
document.getElementById('rule').innerHTML += this.responseText;
}
}
}
if (document.getElementById('kokuti')) {
const kroad = new XMLHttpRequest();
kroad.open('get', kokutifile);
kroad.send();
kroad.onreadystatechange = function() {
if(kroad.readyState === 4 && kroad.status === 200) {
document.getElementById('kokuti').innerHTML += this.responseText;
}
}
}

1
static/clientid.js Normal file

File diff suppressed because one or more lines are too long

96
static/dark.css Normal file
View File

@ -0,0 +1,96 @@
body {
background: #262626 !important;
color: #fff !important;
}
#body {
background-color: #262626;
}
.post_hover,.rep-comment {
background: #262626 !important;
color: #fff !important;
border: 1px solid #808080 !important;
}
.treeView {
background: #262626 !important;
color: #fff !important;
}
.message,.title,.number,#postForm,.t,.menulink,.option_style_2,.option_style_5,.tlnotice,#rule,#kokuti {
color: #fff !important;
}
ins {
background: #262626 !important;
color: #fff !important;
}
body > .topmenu a {
color: darkgoldenrod !important;
}
body > .bottommenu a {
color: darkgoldenrod !important;
}
.date,.created {
color: #808080 !important;
}
.id {
color: #999999 !important;
}
.menu {
background: #262626 !important;
}
.bbs-textarea {
background: #262626 !important;
color: #fff !important;
}
input {
background: #262626 !important;
color: #fff !important;
}
textarea {
background: #262626 !important;
color: #fff !important;
}
#rModal > div {
background: #262626 !important;
color: #fff !important;
}
.box,.side {
background: #262626 !important;
color: #fff !important;
}
.thread {
background: #262626 !important;
color: #fff;
}
table {
background: #262626 !important;
color: #fff !important;
}
#sp-header {
background: #262626 !important;
color: #fff !important;
border: 1px solid #808080 !important;
}
body > .newposts a[href] {
color: darkgoldenrod !important;
}
.search-header, .wi {
background: #262626 !important;
}
.fbox {
background: #262626 !important;
}
.rclose,.mclose,.rcount,.fas,.back-link,.mbutton {
color: #808080 !important;
}
.post {
border-bottom: .5px solid #333;
}
.asetting_5 {
border-top: .5px solid #333;
border-left: .5px solid #333;
}
.threads {
border-bottom: .5px solid #333;
}
#hidemetoo a {
color: darkgoldenrod !important;
}

1
static/inactive.js Normal file

File diff suppressed because one or more lines are too long

85
static/index.css Normal file

File diff suppressed because one or more lines are too long

8
static/index.js Normal file
View File

@ -0,0 +1,8 @@
document.body.innerHTML = '';
const mode = new URLSearchParams(window.location.search);
let request;
if (mode.get('m') == "subback") request = 'subback.js';
else request = 'timeline.js';
let requestjs = document.createElement("script");
requestjs.src = "/static/"+request;
document.body.appendChild(requestjs);

5
static/jquery-1.11.3.min.js vendored Normal file

File diff suppressed because one or more lines are too long

204
static/lightbox.css Normal file
View File

@ -0,0 +1,204 @@
body.lb-disable-scrolling {
overflow: hidden;
}
.lightboxOverlay {
position: absolute;
top: 0;
left: 0;
z-index: 9999;
background-color: black;
filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80);
opacity: 0.8;
display: none;
}
.lightbox {
position: absolute;
left: 0;
width: 100%;
z-index: 10000;
text-align: center;
line-height: 0;
font-weight: normal;
outline: none;
}
.lightbox .lb-image {
display: block;
height: auto;
max-width: inherit;
max-height: none;
border-radius: 3px;
/* Image border */
border: 4px solid white;
}
.lightbox a img {
border: none;
}
.lb-outerContainer {
position: relative;
*zoom: 1;
width: 250px;
height: 250px;
margin: 0 auto;
border-radius: 4px;
/* Background color behind image.
This is visible during transitions. */
background-color: white;
}
.lb-outerContainer:after {
content: "";
display: table;
clear: both;
}
.lb-loader {
position: absolute;
top: 43%;
left: 0;
height: 25%;
width: 100%;
text-align: center;
line-height: 0;
}
.lb-cancel {
display: block;
width: 32px;
height: 32px;
margin: 0 auto;
background: url(../images/loading.gif) no-repeat;
}
.lb-nav {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
z-index: 10;
}
.lb-container > .nav {
left: 0;
}
.lb-nav a {
outline: none;
background-image: url('data:image/gif;base64,R0lGODlhAQABAPAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==');
}
.lb-prev, .lb-next {
height: 100%;
cursor: pointer;
display: block;
}
.lb-nav a.lb-prev {
width: 34%;
left: 0;
float: left;
background: url(../images/prev.png) left 48% no-repeat;
filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0);
opacity: 0;
-webkit-transition: opacity 0.6s;
-moz-transition: opacity 0.6s;
-o-transition: opacity 0.6s;
transition: opacity 0.6s;
}
.lb-nav a.lb-prev:hover {
filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
opacity: 1;
}
.lb-nav a.lb-next {
width: 64%;
right: 0;
float: right;
background: url(../images/next.png) right 48% no-repeat;
filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0);
opacity: 0;
-webkit-transition: opacity 0.6s;
-moz-transition: opacity 0.6s;
-o-transition: opacity 0.6s;
transition: opacity 0.6s;
}
.lb-nav a.lb-next:hover {
filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
opacity: 1;
}
.lb-dataContainer {
margin: 0 auto;
padding-top: 5px;
*zoom: 1;
width: 100%;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
}
.lb-dataContainer:after {
content: "";
display: table;
clear: both;
}
.lb-data {
padding: 0 4px;
color: #ccc;
}
.lb-data .lb-details {
width: 85%;
float: left;
text-align: left;
line-height: 1.1em;
}
.lb-data .lb-caption {
font-size: 13px;
font-weight: bold;
line-height: 1em;
}
.lb-data .lb-caption a {
color: #4ae;
}
.lb-data .lb-number {
display: block;
clear: left;
padding-bottom: 1em;
font-size: 12px;
color: #999999;
}
.lb-data .lb-close {
display: block;
float: right;
width: 30px;
height: 30px;
background: url(../images/close.png) top right no-repeat;
text-align: right;
outline: none;
filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=70);
opacity: 0.7;
-webkit-transition: opacity 0.2s;
-moz-transition: opacity 0.2s;
-o-transition: opacity 0.2s;
transition: opacity 0.2s;
}
.lb-data .lb-close:hover {
cursor: pointer;
filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
opacity: 1;
}

554
static/lightbox.js Normal file
View File

@ -0,0 +1,554 @@
/*!
* Lightbox v2.11.3
* by Lokesh Dhakar
*
* More info:
* http://lokeshdhakar.com/projects/lightbox2/
*
* Copyright Lokesh Dhakar
* Released under the MIT license
* https://github.com/lokesh/lightbox2/blob/master/LICENSE
*
* @preserve
*/
// Uses Node, AMD or browser globals to create a module.
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module.exports = factory(require('jquery'));
} else {
// Browser globals (root is window)
root.lightbox = factory(root.jQuery);
}
}(this, function ($) {
function Lightbox(options) {
this.album = [];
this.currentImageIndex = void 0;
this.init();
// options
this.options = $.extend({}, this.constructor.defaults);
this.option(options);
}
// Descriptions of all options available on the demo site:
// http://lokeshdhakar.com/projects/lightbox2/index.html#options
Lightbox.defaults = {
albumLabel: 'Image %1 of %2',
alwaysShowNavOnTouchDevices: false,
fadeDuration: 600,
fitImagesInViewport: true,
imageFadeDuration: 600,
// maxWidth: 800,
// maxHeight: 600,
positionFromTop: 50,
resizeDuration: 700,
showImageNumberLabel: true,
wrapAround: false,
disableScrolling: false,
/*
Sanitize Title
If the caption data is trusted, for example you are hardcoding it in, then leave this to false.
This will free you to add html tags, such as links, in the caption.
If the caption data is user submitted or from some other untrusted source, then set this to true
to prevent xss and other injection attacks.
*/
sanitizeTitle: false
};
Lightbox.prototype.option = function(options) {
$.extend(this.options, options);
};
Lightbox.prototype.imageCountLabel = function(currentImageNum, totalImages) {
return this.options.albumLabel.replace(/%1/g, currentImageNum).replace(/%2/g, totalImages);
};
Lightbox.prototype.init = function() {
var self = this;
// Both enable and build methods require the body tag to be in the DOM.
$(document).ready(function() {
self.enable();
self.build();
});
};
// Loop through anchors and areamaps looking for either data-lightbox attributes or rel attributes
// that contain 'lightbox'. When these are clicked, start lightbox.
Lightbox.prototype.enable = function() {
var self = this;
$('body').on('click', 'a[rel^=lightbox], area[rel^=lightbox], a[data-lightbox], area[data-lightbox]', function(event) {
self.start($(event.currentTarget));
return false;
});
};
// Build html for the lightbox and the overlay.
// Attach event handlers to the new DOM elements. click click click
Lightbox.prototype.build = function() {
if ($('#lightbox').length > 0) {
return;
}
var self = this;
// The two root notes generated, #lightboxOverlay and #lightbox are given
// tabindex attrs so they are focusable. We attach our keyboard event
// listeners to these two elements, and not the document. Clicking anywhere
// while Lightbox is opened will keep the focus on or inside one of these
// two elements.
//
// We do this so we can prevent propogation of the Esc keypress when
// Lightbox is open. This prevents it from intefering with other components
// on the page below.
//
// Github issue: https://github.com/lokesh/lightbox2/issues/663
$('<div id="lightboxOverlay" tabindex="-1" class="lightboxOverlay"></div><div id="lightbox" tabindex="-1" class="lightbox"><div class="lb-outerContainer"><div class="lb-container"><img class="lb-image" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" alt=""/><div class="lb-nav"><a class="lb-prev" aria-label="Previous image" href="" ></a><a class="lb-next" aria-label="Next image" href="" ></a></div><div class="lb-loader"><a class="lb-cancel"></a></div></div></div><div class="lb-dataContainer"><div class="lb-data"><div class="lb-details"><span class="lb-caption"></span><span class="lb-number"></span></div><div class="lb-closeContainer"><a class="lb-close"></a></div></div></div></div>').appendTo($('body'));
// Cache jQuery objects
this.$lightbox = $('#lightbox');
this.$overlay = $('#lightboxOverlay');
this.$outerContainer = this.$lightbox.find('.lb-outerContainer');
this.$container = this.$lightbox.find('.lb-container');
this.$image = this.$lightbox.find('.lb-image');
this.$nav = this.$lightbox.find('.lb-nav');
// Store css values for future lookup
this.containerPadding = {
top: parseInt(this.$container.css('padding-top'), 10),
right: parseInt(this.$container.css('padding-right'), 10),
bottom: parseInt(this.$container.css('padding-bottom'), 10),
left: parseInt(this.$container.css('padding-left'), 10)
};
this.imageBorderWidth = {
top: parseInt(this.$image.css('border-top-width'), 10),
right: parseInt(this.$image.css('border-right-width'), 10),
bottom: parseInt(this.$image.css('border-bottom-width'), 10),
left: parseInt(this.$image.css('border-left-width'), 10)
};
// Attach event handlers to the newly minted DOM elements
this.$overlay.hide().on('click', function() {
self.end();
return false;
});
this.$lightbox.hide().on('click', function(event) {
if ($(event.target).attr('id') === 'lightbox') {
self.end();
}
});
this.$outerContainer.on('click', function(event) {
if ($(event.target).attr('id') === 'lightbox') {
self.end();
}
return false;
});
this.$lightbox.find('.lb-prev').on('click', function() {
if (self.currentImageIndex === 0) {
self.changeImage(self.album.length - 1);
} else {
self.changeImage(self.currentImageIndex - 1);
}
return false;
});
this.$lightbox.find('.lb-next').on('click', function() {
if (self.currentImageIndex === self.album.length - 1) {
self.changeImage(0);
} else {
self.changeImage(self.currentImageIndex + 1);
}
return false;
});
/*
Show context menu for image on right-click
There is a div containing the navigation that spans the entire image and lives above of it. If
you right-click, you are right clicking this div and not the image. This prevents users from
saving the image or using other context menu actions with the image.
To fix this, when we detect the right mouse button is pressed down, but not yet clicked, we
set pointer-events to none on the nav div. This is so that the upcoming right-click event on
the next mouseup will bubble down to the image. Once the right-click/contextmenu event occurs
we set the pointer events back to auto for the nav div so it can capture hover and left-click
events as usual.
*/
this.$nav.on('mousedown', function(event) {
if (event.which === 3) {
self.$nav.css('pointer-events', 'none');
self.$lightbox.one('contextmenu', function() {
setTimeout(function() {
this.$nav.css('pointer-events', 'auto');
}.bind(self), 0);
});
}
});
this.$lightbox.find('.lb-loader, .lb-close').on('click', function() {
self.end();
return false;
});
};
// Show overlay and lightbox. If the image is part of a set, add siblings to album array.
Lightbox.prototype.start = function($link) {
var self = this;
var $window = $(window);
$window.on('resize', $.proxy(this.sizeOverlay, this));
this.sizeOverlay();
this.album = [];
var imageNumber = 0;
function addToAlbum($link) {
self.album.push({
alt: $link.attr('data-alt'),
link: $link.attr('href'),
title: $link.attr('data-title') || $link.attr('title')
});
}
// Support both data-lightbox attribute and rel attribute implementations
var dataLightboxValue = $link.attr('data-lightbox');
var $links;
if (dataLightboxValue) {
$links = $($link.prop('tagName') + '[data-lightbox="' + dataLightboxValue + '"]');
for (var i = 0; i < $links.length; i = ++i) {
addToAlbum($($links[i]));
if ($links[i] === $link[0]) {
imageNumber = i;
}
}
} else {
if ($link.attr('rel') === 'lightbox') {
// If image is not part of a set
addToAlbum($link);
} else {
// If image is part of a set
$links = $($link.prop('tagName') + '[rel="' + $link.attr('rel') + '"]');
for (var j = 0; j < $links.length; j = ++j) {
addToAlbum($($links[j]));
if ($links[j] === $link[0]) {
imageNumber = j;
}
}
}
}
// Position Lightbox
var top = $window.scrollTop() + this.options.positionFromTop;
var left = $window.scrollLeft();
this.$lightbox.css({
top: top + 'px',
left: left + 'px'
}).fadeIn(this.options.fadeDuration);
// Disable scrolling of the page while open
if (this.options.disableScrolling) {
$('body').addClass('lb-disable-scrolling');
}
this.changeImage(imageNumber);
};
// Hide most UI elements in preparation for the animated resizing of the lightbox.
Lightbox.prototype.changeImage = function(imageNumber) {
var self = this;
var filename = this.album[imageNumber].link;
var filetype = filename.split('.').slice(-1)[0];
var $image = this.$lightbox.find('.lb-image');
// Disable keyboard nav during transitions
this.disableKeyboardNav();
// Show loading state
this.$overlay.fadeIn(this.options.fadeDuration);
$('.lb-loader').fadeIn('slow');
this.$lightbox.find('.lb-image, .lb-nav, .lb-prev, .lb-next, .lb-dataContainer, .lb-numbers, .lb-caption').hide();
this.$outerContainer.addClass('animating');
// When image to show is preloaded, we send the width and height to sizeContainer()
var preloader = new Image();
preloader.onload = function() {
var $preloader;
var imageHeight;
var imageWidth;
var maxImageHeight;
var maxImageWidth;
var windowHeight;
var windowWidth;
$image.attr({
'alt': self.album[imageNumber].alt,
'src': filename
});
$preloader = $(preloader);
$image.width(preloader.width);
$image.height(preloader.height);
windowWidth = $(window).width();
windowHeight = $(window).height();
// Calculate the max image dimensions for the current viewport.
// Take into account the border around the image and an additional 10px gutter on each side.
maxImageWidth = windowWidth - self.containerPadding.left - self.containerPadding.right - self.imageBorderWidth.left - self.imageBorderWidth.right - 20;
maxImageHeight = windowHeight - self.containerPadding.top - self.containerPadding.bottom - self.imageBorderWidth.top - self.imageBorderWidth.bottom - self.options.positionFromTop - 70;
/*
Since many SVGs have small intrinsic dimensions, but they support scaling
up without quality loss because of their vector format, max out their
size.
*/
if (filetype === 'svg') {
$image.width(maxImageWidth);
$image.height(maxImageHeight);
}
// Fit image inside the viewport.
if (self.options.fitImagesInViewport) {
// Check if image size is larger then maxWidth|maxHeight in settings
if (self.options.maxWidth && self.options.maxWidth < maxImageWidth) {
maxImageWidth = self.options.maxWidth;
}
if (self.options.maxHeight && self.options.maxHeight < maxImageHeight) {
maxImageHeight = self.options.maxHeight;
}
} else {
maxImageWidth = self.options.maxWidth || preloader.width || maxImageWidth;
maxImageHeight = self.options.maxHeight || preloader.height || maxImageHeight;
}
// Is the current image's width or height is greater than the maxImageWidth or maxImageHeight
// option than we need to size down while maintaining the aspect ratio.
if ((preloader.width > maxImageWidth) || (preloader.height > maxImageHeight)) {
if ((preloader.width / maxImageWidth) > (preloader.height / maxImageHeight)) {
imageWidth = maxImageWidth;
imageHeight = parseInt(preloader.height / (preloader.width / imageWidth), 10);
$image.width(imageWidth);
$image.height(imageHeight);
} else {
imageHeight = maxImageHeight;
imageWidth = parseInt(preloader.width / (preloader.height / imageHeight), 10);
$image.width(imageWidth);
$image.height(imageHeight);
}
}
self.sizeContainer($image.width(), $image.height());
};
// Preload image before showing
preloader.src = this.album[imageNumber].link;
this.currentImageIndex = imageNumber;
};
// Stretch overlay to fit the viewport
Lightbox.prototype.sizeOverlay = function() {
var self = this;
/*
We use a setTimeout 0 to pause JS execution and let the rendering catch-up.
Why do this? If the `disableScrolling` option is set to true, a class is added to the body
tag that disables scrolling and hides the scrollbar. We want to make sure the scrollbar is
hidden before we measure the document width, as the presence of the scrollbar will affect the
number.
*/
setTimeout(function() {
self.$overlay
.width($(document).width())
.height($(document).height());
}, 0);
};
// Animate the size of the lightbox to fit the image we are showing
// This method also shows the the image.
Lightbox.prototype.sizeContainer = function(imageWidth, imageHeight) {
var self = this;
var oldWidth = this.$outerContainer.outerWidth();
var oldHeight = this.$outerContainer.outerHeight();
var newWidth = imageWidth + this.containerPadding.left + this.containerPadding.right + this.imageBorderWidth.left + this.imageBorderWidth.right;
var newHeight = imageHeight + this.containerPadding.top + this.containerPadding.bottom + this.imageBorderWidth.top + this.imageBorderWidth.bottom;
function postResize() {
self.$lightbox.find('.lb-dataContainer').width(newWidth);
self.$lightbox.find('.lb-prevLink').height(newHeight);
self.$lightbox.find('.lb-nextLink').height(newHeight);
// Set focus on one of the two root nodes so keyboard events are captured.
self.$overlay.focus();
self.showImage();
}
if (oldWidth !== newWidth || oldHeight !== newHeight) {
this.$outerContainer.animate({
width: newWidth,
height: newHeight
}, this.options.resizeDuration, 'swing', function() {
postResize();
});
} else {
postResize();
}
};
// Display the image and its details and begin preload neighboring images.
Lightbox.prototype.showImage = function() {
this.$lightbox.find('.lb-loader').stop(true).hide();
this.$lightbox.find('.lb-image').fadeIn(this.options.imageFadeDuration);
this.updateNav();
this.updateDetails();
this.preloadNeighboringImages();
this.enableKeyboardNav();
};
// Display previous and next navigation if appropriate.
Lightbox.prototype.updateNav = function() {
// Check to see if the browser supports touch events. If so, we take the conservative approach
// and assume that mouse hover events are not supported and always show prev/next navigation
// arrows in image sets.
var alwaysShowNav = false;
try {
document.createEvent('TouchEvent');
alwaysShowNav = (this.options.alwaysShowNavOnTouchDevices) ? true : false;
} catch (e) {}
this.$lightbox.find('.lb-nav').show();
if (this.album.length > 1) {
if (this.options.wrapAround) {
if (alwaysShowNav) {
this.$lightbox.find('.lb-prev, .lb-next').css('opacity', '1');
}
this.$lightbox.find('.lb-prev, .lb-next').show();
} else {
if (this.currentImageIndex > 0) {
this.$lightbox.find('.lb-prev').show();
if (alwaysShowNav) {
this.$lightbox.find('.lb-prev').css('opacity', '1');
}
}
if (this.currentImageIndex < this.album.length - 1) {
this.$lightbox.find('.lb-next').show();
if (alwaysShowNav) {
this.$lightbox.find('.lb-next').css('opacity', '1');
}
}
}
}
};
// Display caption, image number, and closing button.
Lightbox.prototype.updateDetails = function() {
var self = this;
// Enable anchor clicks in the injected caption html.
// Thanks Nate Wright for the fix. @https://github.com/NateWr
if (typeof this.album[this.currentImageIndex].title !== 'undefined' &&
this.album[this.currentImageIndex].title !== '') {
var $caption = this.$lightbox.find('.lb-caption');
if (this.options.sanitizeTitle) {
$caption.text(this.album[this.currentImageIndex].title);
} else {
$caption.html(this.album[this.currentImageIndex].title);
}
$caption.fadeIn('fast');
}
if (this.album.length > 1 && this.options.showImageNumberLabel) {
var labelText = this.imageCountLabel(this.currentImageIndex + 1, this.album.length);
this.$lightbox.find('.lb-number').text(labelText).fadeIn('fast');
} else {
this.$lightbox.find('.lb-number').hide();
}
this.$outerContainer.removeClass('animating');
this.$lightbox.find('.lb-dataContainer').fadeIn(this.options.resizeDuration, function() {
return self.sizeOverlay();
});
};
// Preload previous and next images in set.
Lightbox.prototype.preloadNeighboringImages = function() {
if (this.album.length > this.currentImageIndex + 1) {
var preloadNext = new Image();
preloadNext.src = this.album[this.currentImageIndex + 1].link;
}
if (this.currentImageIndex > 0) {
var preloadPrev = new Image();
preloadPrev.src = this.album[this.currentImageIndex - 1].link;
}
};
Lightbox.prototype.enableKeyboardNav = function() {
this.$lightbox.on('keyup.keyboard', $.proxy(this.keyboardAction, this));
this.$overlay.on('keyup.keyboard', $.proxy(this.keyboardAction, this));
};
Lightbox.prototype.disableKeyboardNav = function() {
this.$lightbox.off('.keyboard');
this.$overlay.off('.keyboard');
};
Lightbox.prototype.keyboardAction = function(event) {
var KEYCODE_ESC = 27;
var KEYCODE_LEFTARROW = 37;
var KEYCODE_RIGHTARROW = 39;
var keycode = event.keyCode;
if (keycode === KEYCODE_ESC) {
// Prevent bubbling so as to not affect other components on the page.
event.stopPropagation();
this.end();
} else if (keycode === KEYCODE_LEFTARROW) {
if (this.currentImageIndex !== 0) {
this.changeImage(this.currentImageIndex - 1);
} else if (this.options.wrapAround && this.album.length > 1) {
this.changeImage(this.album.length - 1);
}
} else if (keycode === KEYCODE_RIGHTARROW) {
if (this.currentImageIndex !== this.album.length - 1) {
this.changeImage(this.currentImageIndex + 1);
} else if (this.options.wrapAround && this.album.length > 1) {
this.changeImage(0);
}
}
};
// Closing time. :-(
Lightbox.prototype.end = function() {
this.disableKeyboardNav();
$(window).off('resize', this.sizeOverlay);
this.$lightbox.fadeOut(this.options.fadeDuration);
this.$overlay.fadeOut(this.options.fadeDuration);
if (this.options.disableScrolling) {
$('body').removeClass('lb-disable-scrolling');
}
};
return new Lightbox();
}));

5
static/milligram.css Normal file

File diff suppressed because one or more lines are too long

4
static/read.css Normal file
View File

@ -0,0 +1,4 @@
@font-face {font-family: "Saitamaar";src: url("/static/Saitamaar.woff2") format("woff2"),url("/static/Saitamaar.woff") format("woff"),url("/static/Saitamaar.ttf") format("ttf");font-display: swap;}html{overflow: auto;}body{color:#333;font-family:ArialMT, "Hiragino Kaku Gothic ProN", "ヒラギノ角ゴ ProN W3";background-color: #fafafa;font-size:14px}#body{background-color: rgba(250,250,250,0.65)}body>.bottommenu a[href]{color:#00f}body>.bottommenu a[href]:visited{color:#00f}body>.topmenu a[href]{font-family:hiragino sans;color:#00f}body>.topmenu a[href]:visited{font-family:hiragino sans;color:#00f}body>.newposts a[href]{color:#00f}body>.newposts a[href]:visited{color:#00f}.title{margin-top:1em}.be{margin-left:5px;display:inline-block}.r2BP{text-decoration:none}.r2BP a[href]{font-family:arial,arial,sans-serif}.r2BP a[href]{text-decoration:none}.r2BP a[href]{color:teal}.r2BP a[href]:visited{color:teal}.r2BP a[href]{background:#f0f8ff}.rBRZ{text-decoration:none}.rBRZ a[href]{font-family:arial,arial,sans-serif}.rBRZ a[href]{color:#000}.rBRZ a[href]:visited{color:#333}.rBRZ a[href]{background:#d2691e}.rPLT a[href]{font-family:arial,arial,sans-serif}.rPLT a[href]{text-decoration:none}.rPLT a[href]{color:#f0e60e}.rPLT a[href]:visited{color:khaki}.rPLT a[href]{background:#483d8b}.rDIA{text-decoration:none}.rDIA a[href]{font-family:arial,arial,sans-serif}.rDIA a[href]{color:khaki}.rDIA a[href]:visited{color:khaki}.rDIA a[href]{background:brown}.rS{text-decoration:none}.rS a[href]{font-family:arial,arial,sans-serif}.rS a[href]{color:red}.rS a[href]:visited{color:#f00f00}.rS a[href]{background:gold}hr{margin:0}.post,hr{border-bottom:.5px solid #DCDCDC}div.number{display:inline-block;}div.name{display:inline-block;}div.email{display:inline-block;}div.date{display:inline-block;}.number{color:rgb(87, 111, 118);text-decoration:none;}.name{color:rgb(87, 111, 118);font-size:15px;margin-left:6px}.date{color:rgb(87, 111, 118);}.newposts a[href],.message a[href],.backmsg a[href]{text-decoration: none;color: #1a98ff !important;}.message a[href]:visited{color:#9b4dca !important}#hidemetoo a[href]:focus, #hidemetoo a[href]:hover ,.message a[href]:focus, .message a[href]:hover {color: #23527c !important}.message{color:#000;margin-left:8px}.message a[href]:active{color:red !important}.cLength{font-weight:700;font-family:arial,arial,sans-serif;font-size:.94999em;color:red}.back-links a{margin-left:5px;font-size:.625em;color:#34345c}.hoverAppend{display:none;position:absolute;background-color:#ccc;padding-top:5px;padding-left:5px;padding-right:5px;padding-bottom:5px;border:solid 1px #000;z-index:1}.newpostbutton{margin-left:25%}.orange{text-decoration:none;color:#fe642e;font-weight:700}.orange a[href]:visited{color:#fe642e}.orange a[href]:active{color:#fe642e}.green{text-decoration:none;color:green;font-weight:700}.green a[href]:visited{color:green}.green a[href]:active{color:green}.menuitem{margin-left:6px !important;display:inline-block}.thread{word-wrap:break-word}#banner{margin-left:40px}#bannerLeft{width:300px;display:inline-block;padding-right:10px}#bannerRight{width:300px;display:inline-block}.stoplight{margin:1px;padding:1px;color: #fff;padding: 5px;font-size: 12px;background: #ff7773;}.stopyellow{background-color:#ff0}.stopred{background-color:red;color:#fff}.stopdone{line-height:3em}.option_container{position:fixed;top:0;left:0;right:0;bottom:0;width:100%;height:100%;z-index:11;display:none;text-align:center}.option_bg{background-color:rgba(0,0,0,.4688);position:fixed;top:0;left:0;right:0;bottom:0;width:100%;height:100%;z-index:12;display:inline-block}.option_view{padding:15px;margin-top:20px;position:relative;height:auto;width:350px;background:#fff;z-index:13;display:inline-block;text-align:left;border:solid 1px #979797;border-radius:4px}.option_view span{float:right}.option_view a{text-decoration:none}.option_text{top:10px;right:10px;position:fixed;z-index:2}.option_text a{text-decoration:none}#optionView{display:none}
nav .container{width:100%;margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px;padding-top:10px;padding-bottom:10px}.navbar-fixed-top{z-index:2!important}.option_container_style{position:fixed;top:0;left:0;right:0;bottom:0;width:100%;height:100%;z-index:11;display:none;text-align:center}.option_container_bg{background-color:rgba(0,0,0,.4688);position:fixed;top:0;left:0;right:0;bottom:0;width:100%;height:100%;z-index:12;display:inline-block}.option_container_view{margin-top:20px;position:relative;height:auto;width:350px;background:#fff;z-index:13;display:inline-block;text-align:left;border:solid 1px #979797;border-radius:4px}.option_container_view span{float:right}.option_container_view a{text-decoration:none}.option_style_1{background-color:#efefef;border:1px solid #979797;border-radius:4px 4px 0 0;padding-top:10px;padding-bottom:10px;padding-left:15px;margin-left:-1px;margin-right:-1px}.option_style_2{float:left;font-size:16px;letter-spacing:0;color:#000}.option_style_3{margin-left:92%}.option_style_4{padding-left:30px;padding-right:20px;padding-top:20px;padding-bottom:10px;font-size:15px;position:relative}.option_style_5{margin-bottom:10px}.option_style_6{margin-right:10px!important;transform:scale(1.2)}.option_style_7{position:relative;margin-bottom:10px}.option_style_8{margin-bottom:20px}.option_style_9{width:50px;margin-right:5px;background:#fff;border:1px solid #ccc;box-shadow:inset 0 1px 0 0 #ececec;border-radius:5px;text-align:center;height:35px}.option_style_10{position:absolute;top:0;left:0;right:0;bottom:1px;background-color:rgba(255,255,255,.7)}.option_style_11{padding-left:30px;padding-bottom:20px;font-size:15px;text-align:right;padding-right:30px}.option_style_12{font-size:12px;background:#4d9bdd;border:1px solid #4b91cf;border-radius:4px;color:#fff;height:40px;width:80px;vertical-align:middle}.option_style_13{font-size:12px;background:#f3f3f3;border:1px solid #ccc;border-radius:4px;height:40px;width:80px;margin-left:5px;vertical-align:middle}.option_style_14{font-size:12px;color:#dfce00;letter-spacing:-.34px;text-align:center;margin-bottom:15px}.option_noti_1{display:none;position:fixed;top:5%;width:100%;z-index:20;font-weight:700;color:#ff0;pointer-events:none}.option_noti_2{background-color:#404040;width:18%;margin:0 auto;border-radius:15px;text-align:center}.irlog_1{text-decoration:none;color:#485269}.irlog_2{height:22px;width:auto;margin-right:2px;vertical-align:middle}.irlog_3{font-size:13px;color:#b8aa00;letter-spacing:-.35px;text-decoration:none;font-weight:300}.irlog_4{height:28px;width:auto;vertical-align:middle;margin-right:4px}.irlog_5{font-weight:700;background:#fff;border:1px solid #b8aa00;border-radius:4px;padding-left:3px;padding-bottom:3px;padding-top:4px;padding-right:4px}.asetting_1{text-decoration:none;color:#fff;pointer-events:auto}.asetting_2{font-size:.625em}.asetting_3{font-size:.7em;margin-left:5px}.asetting_4{display:none;padding-left:10px;}.asetting_5{border-top:.5px solid #DCDCDC;border-left:.5px solid #DCDCDC}.asetting_6{display:block;padding-left:50px;background-color:#d9d9d9}.asetting_7{text-align:right;padding-right:30px}.ahead_1{height:12px;width:12px;margin-right:3px}.ahead_2{margin-right:2px;vertical-align:middle;height:22px;width:auto}.ahead_3{margin-left:5px;margin-bottom:2px}.ahead_4{font-size:14px;color:#000}.arrow-triangle{display:none;background:url(/images/icon_triangle.png) no-repeat scroll right -1px transparent;height:8px;position:absolute;width:100%;bottom:-30px;z-index:20;margin-right:20px}.show{display:block}.magni{height:12px;width:12px;margin-right:3px;margin-top:-2px}.optsetting{font-size:14px;color:#000}.post .number:hover{color:red !important;cursor:pointer}
.number:hover{text-decoration:underline;}.id{color:#697699;text-decoration:none;}.id:hover{text-decoration:underline;}.thread{overflow-wrap: break-word;}.image{max-width: 560px;height: auto;width: auto;}.option_noti_1{position:fixed;top:5%;width:100%;z-index:20;font-weight:700;color:#ff0}.option_noti_2{background-color:#404040;width:18%;margin:0 auto;border-radius:15px;text-align:center}.menu{background-color:#fefefe;padding:5px;border:1px solid #888;width:150px;margin-left:20px}.bottomlink{text-decoration:none;color:#fff}.mclose{text-decoration:none;}.menulink{color:black !important;}a{word-break: break-all;}body{word-break: break-word; overflow-wrap: break-word; overscroll-behavior-y: contain;}.AA{font-family: saitamaar, ,ms pgothic,ipamonapgothic; font-size: 1em;line-height: 18px;white-space: pre;overflow-x:scroll;display:block}.formbox{color:#333}.rep-comment{background-color: lavender; border: 1px outset lavender; color: black; opacity: 0.95; position: absolute; text-decoration: none; left: 5em; padding-top: 5px; padding-left: 5px; padding-right: 5px;}blockquote{display:none;}.back-links{display:none;}video{max-width: 100%;}iframe{max-width: 100%;}
#headline{margin-bottom:10px;overflow-y:scroll;height:150px;padding:5px}.hhead-bg{background:rgba(150,150,150,.1);padding-left:2px;}.topmenu{z-index:2;position:relative}.topmenu, .bottommenu, textarea{font-size:16px}.post_hover{z-index:50}.back-link{margin-left:5px;font-size:.7em;color:#34345c}.rcount{margin-left:3px;color:#000;}.icon{padding: 3px; margin-right: 3px; border-radius: 45px; display: block;padding-bottom: 5px;margin-left: -.1em;}._mfm_blur_{filter:blur(10px);transition:filter .3s;}._mfm_blur_:hover{filter:blur(0px);}.quote{display:block;color:gray;margin-left:8px;padding:6px 0px 6px 12px;border-left:solid 3px rgb(103, 103, 103);opacity:0.7;}

1115
static/read.js Normal file

File diff suppressed because it is too large Load Diff

4
static/reload.svg Normal file
View File

@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.0127 6.2312H14.0127V3.2312" stroke="#0187E8" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M11.8877 11.8875C11.1187 12.6571 10.1387 13.1814 9.07172 13.394C8.0047 13.6066 6.8986 13.4979 5.89335 13.0818C4.88809 12.6656 4.02885 11.9607 3.4243 11.0561C2.81975 10.1515 2.49707 9.08799 2.49707 8C2.49707 6.91201 2.81975 5.84847 3.4243 4.9439C4.02885 4.03933 4.88809 3.33439 5.89335 2.91824C6.8986 2.50209 8.0047 2.39343 9.07172 2.60601C10.1387 2.81859 11.1187 3.34286 11.8877 4.1125L14.0127 6.23125" stroke="#0187E8" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 732 B

1
static/s.css Normal file

File diff suppressed because one or more lines are too long

36
static/sp.css Normal file
View File

@ -0,0 +1,36 @@
.desktop{display:none;}a:visited{color:#9b4dca;}a:hover{color:#FF0000;}#postForm{display:none;}.spformhead{display:inline !important;}.fhead{border-radius:3px 3px 0 0;color:#666; padding:3px;}a{text-decoration: none;color: #1a98ff}.post{word-break: break-all;white-space: normal}details{color:#4d4d4d;}.number{color:#4d4d4d;font-size:80%;font-weight:bold;}.name{color:#4d4d4d !important;font-size: 80%;}.id2{color:#4d4d4d !important;}.date{display:block;color:#ccc;font-size:80%;padding-left:0}.id{right:10px;position:absolute;color:#9ba1a8;color:#9ba1a8;}.message{margin-top:1px;margin-bottom:1px;max-height:500px;overflow-y:scroll}.date>ins{text-align:left;}ins{word-break: break-all;border:0 !important;border-radius: 5px 5px 5px 5px;background-color: #fafafa !important;white-space: normal;box-shadow: 5px 3px 5px rgba(0, 0, 0, .3);}.rep-comment{word-break: break-all;border:0 !important;border-radius: 5px 5px 5px 5px;background-color: #fafafa !important;box-shadow: 5px 3px 5px rgba(0, 0, 0, .3);}.menuitem{color:#646464 !important;font-size: 80%;text-decoration:underline;}.anka{left: 0.5em;right: 0.5em;}.image{max-width: 95%;}.formbox{display: block;}#postForm{position:fixed;top:0px;left:0px;z-index:2000;width:100%;height:100%;text-align:center;background-color:rgba(0, 0, 0, 0.4) !important}.fbox{padding:10px;margin-top:10px;border-radius:3px;background:#eeeeee;box-shadow: 1px 1px 2px gray;width:90%;display:inline-block;text-align:left}#bbs-textarea{font-variant: inherit;font-weight: inherit;font-stretch: inherit;border-radius: 0px 0px 5px 5px;padding: 0px;word-break: break-all;overflow: auto;width: 100%;margin: 2px;height: auto}.input input{margin: 2px;}.backmsg{display:block !important;text-align: center;}.submitbtn{color:#000;float:right;font-size:28px;font-weight:bold;cursor:pointer;display:inline-block;padding-right:5px;}input[type="submit"]{cursor: pointer;border: none; background: rgb(29, 155, 240);color: #ffffff;}#postForm label{display:none}.asetting_4{display: none;}.newposts{font-size:14px}.AA {padding-top: 2px;font-family: saitamaar, ,ms pgothic,ipamonapgothic;word-wrap: normal;font-size: 10pt;line-height: 11pt;}.input{display:block;}#modal_text .id{right:20px;}
.postbutton {
z-index:1500;
display: block !important;
border: 0px solid black;
right: 10px;
bottom: 10px;
position: fixed;
margin-bottom: 10px;
background: rgb(29, 155, 240);
border-radius: 30px 30px 30px 30px;
box-sizing: border-box;
box-shadow: 5px 3px 2px rgba(0, 0, 0, .3);
}
.postbutton a {
width: 3.5em;
display: block;
height: 3.5em;
color: rgb(255, 255, 255) !important;
box-sizing: content-box !important;
}
.postopen {
fill: currentcolor;
width: 1.5em;
height: 1.5em;
padding: 13px 0px 0px 13px;
}
.postopen g {
color: rgb(255, 255, 255) !important;
}
path {
color: rgb(255, 255, 255) !important;
}
.option_noti_1 {
z-index: 150000;
}

1
static/st.css Normal file
View File

@ -0,0 +1 @@
.post{padding-left:.2em;padding-right:.2em;padding-top:.5em;padding-bottom:.5em;border-bottom:1px solid #eee}.post-header{color:#0e0e6e;font-size:.75em}.post-footer{color:#0e0e6e;font-size:.8em}.post-content{color:#000;font-size:1em}.logo{text-align:center;margin:0 auto}.logoimg{max-height:2em}body{color:#000!important;font-family:ArialMT,hiragino kaku gothic pron, pron w3!important}footer{color:#000!important;font-family:ArialMT,hiragino kaku gothic pron, pron w3!important;font-size:.8em;margin:0 auto;text-align:center;width:100%}.noflex{flex-direction:initial!important}.darkblue{color:#364951!important}.borderbottomblue{border-bottom:1px solid #0e52b3}.borderbottomgrey{border-bottom:1px solid #364951}.borderbottomlightgrey{border-bottom:1px solid #eee}.center{text-align:center;margin:0 auto}.orangefont{color:#ff8114!important}.paddingtop0p5{padding-top:.5em!important}.paddingbottom0p5{padding-bottom:.5em!important}.paddingtop0p3{padding-top:.3em!important}.paddingbottom0p3{padding-bottom:.3em!important}.pointer{cursor:pointer}.menumargin{margin:1.5rem 0 0!important}.vertcenter30{margin:0 auto;text-align:center;position:absolute;top:30%;left:50%;-ms-transform:translate(-50%,-30%);transform:translate(-50%,-30%)}.vertcenter50{margin:0 auto;text-align:center;position:absolute;top:50%;left:50%;-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.padding0p5{padding:.5em!important}div.sticky{position:-webkit-sticky!important;position:sticky!important;top:0!important}.stickymenu{bottom:0;position:fixed!important;width:100%;z-index:2}.white{background-color:#fff}.purple{background-color:#4a2a7f}.maxheight1{max-height:1em}.maxheight1p5{max-height:1.5em}.maxheight2{max-height:2em}.maxheight2p5{max-height:2.5em}.maxheight3{max-height:3em}.maxheight2p7{max-height:2.7em}#followheader{width:100%!important;max-width:100%!important}#rocketfollow{width:100%!important;max-width:100%!important}#searchfollow{width:100%!important;max-width:100%!important}.hidden{display:none}.hide{display:none!important}#hideme{display:none}.width100{width:100%!important}.maxwidth100{width:100%!important}.maxwidth90{width:90%!important}.maxwidth80{width:80%!important}.paddinglr1{padding-left:1em;padding-right:1em}@media(min-width:40rem){.stickymenu{bottom:unset;top:0;position:fixed!important;width:100%;z-index:2}.paddinglr1{padding-left:10em;padding-right:10em}#threads{width:50%;max-width:1000px;margin:0 auto}#hidemetoo{display:block!important}#hideme{display:block!important}}#threads{overflow-wrap:break-word;border:1px solid #eee;padding-left:20px;padding-right:20px}.font0p8{font-size:.8em}.textright{text-align:right!important}.height1{height:1em}.height2{height:2em}.height2p5{height:2.5em}.height3{height:3em}.icon{font-size:1.2em}.hovergrey:hover{background-color:#eee}.sitelist,.categorylist,.boardlist{list-style-type:none;padding:0}.boardlist{display:none}.bluegrey{color:#647192}.hideoverflow{overflow:hidden!important}.pink{background-color:#ff94b8!important;color:#fff!important;border-color:#eee!important}.pinkoutline{color:rgba(51,51,51,.8)!important;border-color:#ff94b8!important}.marginbottom1{margin-bottom:1em!important}.uid{float:right}.clear{clear:both}#threadstitle{font-size:1.1em;font-weight:700;border-bottom:1px solid #eee;padding-bottom:.5em;padding-top:.5em}.postusername{padding-left:1em}.click{cursor:pointer}#boardname{font-size:.8em}.spanner{padding-left:1em;padding-right:1em}.date{padding-left:1em}.redrocket{color:red!important}.pagestats{font-size:.8em;text-align:left}.metastats{padding-left:2em}.nobullets{list-style:none}.slightpad{padding-left:.1em;padding-right:.1em;padding-top:.1em;padding-bottom:.1em}.bottompad{padding-bottom:.1em}.bold{font-weight:700}#hideme a{color:#330!important}#hideme li:nth-child(even){background-color:#f8f9fa!important}#hideme li:nth-child(odd){background-color:#fff!important}#hideme li:hover{background-color:#eee!important}#hidemetoo a{color: rgb(87, 111, 118) !important;font-weight: bold;}#hidemetoo li:nth-child(even){background-color:#f8f9fa!important}#hidemetoo li:nth-child(odd){background-color:#fff!important}#hidemetoo li:hover{background-color:#eee!important}.p85{font-size:.85em}.goldoutline{border:.1rem solid #b8aa00!important}.stickit{position:sticky;top:4em}.me310{width:310px!important;min-width:310px!important;max-width:310px!important}#Leaderboard{padding-top:12px;padding-bottom:12px}#overright{overflow-x:hidden}

456
static/subback.js Normal file
View File

@ -0,0 +1,456 @@
let ls = new URLSearchParams(window.location.search);
let spcheck = '';
let kakolog,archive;
if (isSmartPhone() == true) spcheck = 'checked';
let LINENUM,reloadbutton,getprev,preved;
if (localStorage.getItem('ghide') === null) localStorage.setItem('ghide', 'auto');
if (localStorage.getItem('areload') === null) localStorage.setItem('areload', false);
if (localStorage.getItem('darkmode') === null) localStorage.setItem('darkmode', false);
if (localStorage.getItem('autodark') === null) localStorage.setItem('autodark', true);
if (localStorage.getItem('autoscroll') === null) localStorage.setItem('autoscroll', false);
localStorage.setItem('autoPost', true);
localStorage.setItem('backlinkOpen', false);
localStorage.setItem('ankfixed', true);
if (localStorage.getItem('text2') === null) localStorage.setItem('text2', '');
sessionStorage.removeItem('text');
ghide = localStorage.getItem('ghide');
areload = localStorage.getItem('areload');
ankfixed = localStorage.getItem('ankfixed');
darkmode = localStorage.getItem('darkmode');
autodark = localStorage.getItem('autodark');
autoscroll = localStorage.getItem('autoscroll');
if (autodark == "true" && window.matchMedia('(prefers-color-scheme: dark)').matches === true) darkmode = "true";
let mutejson;
let mutelist = [];
mutejson = localStorage.getItem('mutelist');
if (mutejson) {
mutelist = JSON.parse(mutejson);
mutelist = mutelist.filter(Boolean);
}
let ngjson;
let nglist = [];
ngjson = localStorage.getItem('nglist');
if (ngjson) {
nglist = JSON.parse(ngjson);
nglist = nglist.filter(Boolean);
}
let ntjson;
let ntlist = [];
ntjson = localStorage.getItem('ngtitle');
if (ntjson) {
ntlist = JSON.parse(ntjson);
ntlist = ntlist.filter(Boolean);
}
function time() {
var date = new Date();
var a = date.getTime();
return Math.floor(a / 1000);
}
if (!ls.has('archive')) kakolog = String(time()).substring(0, 4);
else kakolog = ls.get('archive');
let path = location.pathname.split('/');
let bbs = path[1];
let requestURL = '';
if (ls.get('mode') != 'archive') requestURL = '/'+bbs+'/subject.json?'+time();
else requestURL = '/'+bbs+'/thread/'+kakolog+'/subject.json';
let n = 0;
document.head.innerHTML += '<link href="/static/st.css" rel="stylesheet" type="text/css"><link href="/static/milligram.css" rel="stylesheet" type="text/css"><link href="/static/s.css" rel="stylesheet" type="text/css"><link href="/static/index.css" rel="stylesheet" type="text/css"><link href="/static/read.css" rel="stylesheet" type="text/css">';
document.body.innerHTML = '<section class="section"><div id="body"><div id="followheader" class="hidden maxwidth100 height2p5 stickymenu container" style="display: block;"><div class="row noflex maxwidth100 white padding0p5 maxheight2p5 borderbottomlightgrey"><div class="topmenu" id="header"><a class="menuitem" href="/'+bbs+'/">TL</a><a class="menuitem" href="/'+bbs+'/?m=subback">スレ一覧</a><a class="menuitem" href="/'+bbs+'/?m=subback&mode=history">履歴</a><a class="menuitem" href="/'+bbs+'/?m=subback&mode=unread">未読</a><a class="menuitem" href="/test/createthread.php?bbs='+bbs+'">スレ作成</a><a class="menuitem" href="javascript:Menu()">メニュー</a><a href="javascript:MenuClick(\'setting\')" class="menuitem">設定</a><div id="headtitle" class="menuitem" style="text-decoration: none;"></div></div></div></div><div id="subbacktitle"></div><div class="tlnotice" id="ntxt" style="margin-top:3rem"></div><div class="search"><input type="text" id="searchInput" placeholder="スレッドタイトル検索" onchange="search()"></div><div class="newposts"><center><a href="javascript:load()">リロード<img alt="再読み込み" loading="lazy" decoding="async" data-nimg="1" style="color: transparent;" src="/static/reload.svg" width="16" height="16"></a></center><hr></div><div id="main"></div><div id="hidemetoo" class="side p85 slightpad nobullets"><div style="min-height:50px" id="rule">■ ローカルルール<br></div><div style="min-height:50px" id="kokuti">■ 告知欄<br></div><p style="margin:5rem 0;color:#333">We\'re sure you\'ll have a good time with delight and/or 3ch. :)</p></div></div></section>';
if (localStorage.getItem('css') === null) localStorage.setItem('css', '');
document.body.innerHTML += "<style>"+localStorage.getItem('css')+"</style>";
let threadjs = document.createElement("script");
threadjs.src = "/static/thread.js";
document.body.appendChild(threadjs);
let boardjs = document.createElement("script");
boardjs.src = "/static/board.js";
document.body.appendChild(boardjs);
if (isSmartPhone() == false) document.getElementById('body').innerHTML += '<style>a{color:#485269 !important;}#headtitle,b{color:rgb(87, 111, 118) !important}</style>';
else document.getElementById('body').innerHTML += '<style>.title{margin-top:.5em;}</style>';
document.getElementById('body').innerHTML += '<style>div.postbutton{display: none !important;}#main{border-top:.5px solid #DCDCDC}</style>';
function load(target) {
document.getElementById('main').innerHTML = '';
request = new XMLHttpRequest();
request.open('GET', requestURL);
request.responseType = 'json';
request.setRequestHeader('Pragma', 'no-cache');
request.setRequestHeader('Cache-Control', 'no-cache');
request.send();
request.onload = function() {
if (request.response) {
let listJSON = JSON.parse(JSON.stringify(request.response));
listJSON.forEach(function(post) {
let NG = false;
n++;
let t,create,created,nres,css,ncount;
let key = post['thread'];
let number = post['number'];
let title = post['title'];
let date = post['date'];
if (title && !ls.has('mode')) {
if (title.indexOf("[stop] ") != -1) return;
}
if (title && target) {
if (title.search(target) == -1) return;
}
if (date && date != "archive") {
t = time() - date;
if (t < 60) t += "秒";
else if (t < 3600) {
t = Math.floor(t / 60);
t += "分";
}else if (t < 86400) {
t = Math.floor(t / 3600);
t += "時間";
}else {
t = Math.floor(t / 86400);
t += "日";
}
}
if (key) {
create = new Date(key * 1000);
created = create.toLocaleDateString()+' '+create.toLocaleTimeString();
}
if (ls.get('mode') != 'archive' && localStorage.getItem(bbs+key) && number > localStorage.getItem(bbs+key)) {
ncount = number - localStorage.getItem(bbs+key);
if (isSmartPhone() == false) nres = '/未読:'+ncount;
else nres = '<span class="new">'+ncount+'</span>';
}else {
if (ls.get('mode') == "unread") return;
else if (ls.get('mode') == "history" && !localStorage.getItem(bbs+key)) return;
nres = '';
}
if (localStorage.getItem(bbs+key)) css = 'font-weight: bold;';
if (!NG) NG = TitleCheck(title);
if (NG) return;
let newpost = document.createElement("div");
newpost.className = 'threads';
if (isSmartPhone() == false) newpost.innerHTML = '<a class="t" href="/#'+bbs+'/'+key+'/"><span class="title" style="'+css+'">'+title+'</span><small>(レス:'+number+nres+')</small><span class="date"><span class="created">'+created+'</span> <span class="speed">'+t+'</span></span></a>';
else newpost.innerHTML = '<a class="t" href="/#'+bbs+'/'+key+'/"><span class="right">'+number+'</span>'+nres+'<div class="title" style="'+css+'">'+title+'</div><span class="date"><span class="right"><span class="speed">'+t+'</span></span><span class="created">'+created+'</span></span></a>';
document.getElementById('main').appendChild(newpost);
});
}
if (ls.get('mode') != 'archive') document.getElementById('main').innerHTML += '<div class="m threads"><b><a href="/'+bbs+'/?m=subback&mode=archive">過去ログ倉庫はこちら</a></b></div>';
else {
archive = kakolog - 1;
document.getElementById('main').innerHTML += '<div class="m threads"><b><a href="/'+bbs+'/?m=subback&mode=archive&archive='+archive+'">次へ('+archive+')</a></b></div>';
}
}
}
load();
let modal = document.createElement('div');
modal.innerHTML = '<div id="Modal" style="background-color:#fafafa;margin:auto;padding:20px;border:1px solid #888;width:500px;max-width:95%;"><span style="color:#000;float:right;font-size:28px;font-weight:bold;cursor:pointer;" class="rclose" onclick="rclose()">×</span><div id="modal_text" style="width: 100%;color:#808080;font-family: arial,helvetica,sans-serif;font-size:10pt;margin: 2em 4px 0 0;">'+
'</div></div>';
modal.id = 'rModal';
modal.style.cssText = 'position: fixed; z-index: 20; left: 0px; top: 0px; width: 100%; height: 100%; overflow: auto; background-color: rgba(0, 0, 0, 0.4);';
modal.style.display = 'none';
document.getElementById('body').appendChild(modal);
document.getElementById('body').onclick = function (event) {
let x = event.clientX;
let y = event.clientY;
let e = document.elementsFromPoint(x, y);
let repid,menid,rt,ri;
e.forEach(function(el) {
if (el.className == "rep-comment") {
repid = el.id;
}
else if (el.id == "Modal") {
menid = el.id;
}
if (el.className == "number" || el.className == "menuitem") rt = true;
if (el.className == "id" || el.className == "ank2" || el.className == "id id2") ri = true;
});
let reps = document.querySelectorAll(".rep-comment");
if (!reps) return;
reps.forEach(function(v) {
var timer = setTimeout(function(){
if (v.id == repid) return;
v.style.display = 'none';
},100);
});
let mens = document.querySelectorAll("#Modal");
if (!mens) return;
mens.forEach(function(v) {
var timer = setTimeout(function(){
if (v.id == menid || rt || ri) return;
document.getElementById('rModal').style.display = 'none';
},100);
});
}
function isSmartPhone() {
let v = false;
if (navigator.userAgent.match(/iPhone|Android.+Mobile/)) {
v = true;
} else {
v = false;
}
if (localStorage.getItem('viewer') == 'sp') v = true;
else if (localStorage.getItem('viewer') == 'pc') v = false;
if (location.search.indexOf('v=sp') != -1) v = true;
if (location.search.indexOf('v=pc') != -1) v = false;
return v;
}
function mute(target) {
if (target == 'list') {
let mlisthtml = '<div style="font-weight:bold;">ミュートするID</div><input type="text" id="addmute"><button onclick="AddM()">追加</button>&emsp;<button onclick="mute(\'reset\')">リセット</button><br>※クリックで解除<br>';
for (let i = 0; i < mutelist.length; i++) {
mlisthtml += '<a class="menulink" href="javascript:unmute(\''+mutelist[i]+'\')">'+mutelist[i]+'</a>&emsp;';
}
document.getElementById('modal_text').innerHTML = mlisthtml;
document.getElementById('rModal').style.display = 'block';
return;
}
if (target == 'reset') {
mutelist = [];
mutejson = JSON.stringify(mutelist, undefined, 1);
localStorage.setItem('mutelist', mutejson);
document.getElementById('ntxt').innerHTML = 'リセットしました';
return;
}
let a;
for (let i = 0; i < mutelist.length; i++) {
if (target == mutelist[i]) {
a = true;
break;
}
}
if (a == true) return;
let mutecount = mutelist.length + 1;
mutelist[mutecount-1] = target;
mutejson = JSON.stringify(mutelist, undefined, 1);
localStorage.setItem('mutelist', mutejson);
document.getElementById('ntxt').innerHTML = 'ミュートしました';
}
function AddM() {
let target = document.getElementById('addmute').value;
let a;
for (let i = 0; i < mutelist.length; i++) {
if (target == mutelist[i]) {
a = true;
break;
}
}
if (a == true) return;
let mutecount = mutelist.length + 1;
mutelist[mutecount-1] = target;
mutejson = JSON.stringify(mutelist, undefined, 1);
localStorage.setItem('mutelist', mutejson);
document.getElementById('ntxt').innerHTML = '追加しました';
}
function unmute(target) {
let a;
for (let i = 0; i < mutelist.length; i++) {
if (target == mutelist[i]) {
mutelist[i] = '';
break;
}
}
mutejson = JSON.stringify(mutelist, undefined, 1);
localStorage.setItem('mutelist', mutejson);
document.getElementById('ntxt').innerHTML = 'ミュートを解除しました';
}
function MuteCheck(target) {
let N;
for (let i = 0; i < mutelist.length; i++) {
if (!mutelist[i]) continue;
let NG = target.match(mutelist[i]);
if (NG) {
N = mutelist[i];
break;
}
}
if (N) return true;
}
function WordCheck(target) {
let N;
for (let i = 0; i < nglist.length; i++) {
if (!nglist[i]) continue;
let NG = target.match(nglist[i]);
if (NG) {
N = nglist[i];
break;
}
}
if (N) return true;
}
function TitleCheck(target) {
let N;
for (let i = 0; i < ntlist.length; i++) {
if (!ntlist[i]) continue;
let NG = false;
if (target.search(ntlist[i]) != -1) NG = true;
if (NG) {
N = ntlist[i];
break;
}
}
if (N) return true;
}
function NGWORD() {
let target = document.getElementById('addngword').value;
let a;
for (let i = 0; i < nglist.length; i++) {
if (target == nglist[i]) {
a = true;
break;
}
}
if (a == true) return;
let ngcount = nglist.length + 1;
nglist[ngcount-1] = target;
ngjson = JSON.stringify(nglist, undefined, 1);
localStorage.setItem('nglist', ngjson);
document.getElementById('ntxt').innerHTML = '追加しました';
notice();
}
function NGTITLE() {
let target = document.getElementById('addngtitle').value;
let a;
for (let i = 0; i < ntlist.length; i++) {
if (target == ntlist[i]) {
a = true;
break;
}
}
if (a == true) return;
let ntcount = ntlist.length + 1;
ntlist[ntcount-1] = target;
ntjson = JSON.stringify(ntlist, undefined, 1);
localStorage.setItem('ngtitle', ntjson);
document.getElementById('ntxt').innerHTML = '追加しました';
notice();
}
function unngword(target) {
if (target == 'reset') {
nglist = [];
ngjson = JSON.stringify(nglist, undefined, 1);
localStorage.setItem('nglist', ngjson);
document.getElementById('ntxt').innerHTML = 'リセットしました';
notice();
return;
}
let a;
for (let i = 0; i < nglist.length; i++) {
if (target == nglist[i]) {
nglist[i] = '';
break;
}
}
ngjson = JSON.stringify(nglist, undefined, 1);
localStorage.setItem('nglist', ngjson);
document.getElementById('ntxt').innerHTML = '解除しました';
notice();
}
function unngtitle(target) {
if (target == 'reset') {
ntlist = [];
ntjson = JSON.stringify(ntlist, undefined, 1);
localStorage.setItem('ngtitle', ntjson);
document.getElementById('ntxt').innerHTML = 'リセットしました';
notice();
return;
}
let a;
for (let i = 0; i < ntlist.length; i++) {
if (target == ntlist[i]) {
ntlist[i] = '';
break;
}
}
ntjson = JSON.stringify(ntlist, undefined, 1);
localStorage.setItem('ntlist', ngjson);
document.getElementById('ntxt').innerHTML = '解除しました';
notice();
}
function rclose() {
document.getElementById('rModal').style.display = 'none';
document.getElementById('modal_text').innerHTML = '';
}
function Menu() {
document.getElementById('modal_text').innerHTML = '<div style="font-weight:bold;">ミュート設定</div><a class="menulink" href="javascript:mute(\'list\')">ID</a>&emsp;<a class="menulink" href="javascript:MenuClick(\'ngword\')">Word</a>&emsp;<a class="menulink" href="javascript:MenuClick(\'ngtitle\')">タイトル</a><div style="font-weight:bold;">その他</div><a class="menulink" href="javascript:MenuClick(\'setting\')">閲覧設定</a>&emsp;<a class="menulink" href="/test/backimg.html">背景画像</a>&emsp;<a class="menulink" href="/test/css.html">カスタムcss</a><br><a class="menulink" href="javascript:setclear()">全ログを削除</a>&emsp;<a class="menulink" href="/test/auth.php">認証</a>';
document.getElementById('rModal').style.display = 'block';
}
function MenuClick(val) {
if (val == "ngword") {
let nlisthtml = '<div style="font-weight:bold;">ミュートするワード</div>※クリックで解除<br>';
nlisthtml += '<input type="text" id="addngword"><button onclick="NGWORD()">追加</button>&emsp;<button onclick="unngword(\'reset\')">リセット</button><br>'
for (let i = 0; i < nglist.length; i++) {
nlisthtml += '<a class="menulink" href="javascript:unngword(\''+nglist[i]+'\')">'+nglist[i]+'</a>&emsp;';
}
document.getElementById('modal_text').innerHTML = nlisthtml;
document.getElementById('rModal').style.display = 'block';
return;
}
if (val == "ngtitle") {
let nlisthtml = '<div style="font-weight:bold;">ミュートするタイトル</div>※クリックで解除<br>';
nlisthtml += '<input type="text" id="addngtitle"><button onclick="NGTITLE()">追加</button>&emsp;<button onclick="unngtitle(\'reset\')">リセット</button><br>'
for (let i = 0; i < ntlist.length; i++) {
nlisthtml += '<a class="menulink" href="javascript:unngtitle(\''+ntlist[i]+'\')">'+ntlist[i]+'</a>&emsp;';
}
document.getElementById('modal_text').innerHTML = nlisthtml;
document.getElementById('rModal').style.display = 'block';
return;
}
if (val == "setting") {
let arecheck,gurocheck,autocheck,gcheck,darkcheck,adarkcheck;
if (areload == "true") arecheck = 'checked';
if (autoscroll == "true") autocheck = 'checked';
if (ghide == "all") gcheck = 'checked';
if (ghide == "auto") gurocheck = 'checked';
if (localStorage.getItem('darkmode') == "true") darkcheck = 'checked';
if (autodark == "true") adarkcheck = 'checked';
document.getElementById('modal_text').innerHTML = '<div class="option_style_2">閲覧設定</div><div class="option_style_3">&emsp;</div><div class="option_style_4"><div class="option_style_5"><input class="option_style_6" '+spcheck+' id="spmode" type="checkbox">スマホ用表示</div><div class="option_style_5"><input class="option_style_6" '+darkcheck+' id="darkmode" type="checkbox">ダークモード</div><div class="option_style_5"><input class="option_style_6" '+adarkcheck+' id="autodark" type="checkbox">デバイスのダークモードと同期する</div><div class="option_style_5"><input class="option_style_6" '+arecheck+' id="arecheck" type="checkbox">5秒間隔で自動更新する</div><div class="option_style_5"><input class="option_style_6" '+autocheck+' id="autoscroll" type="checkbox">新着投稿の位置まで自動スクロール</div><div class="option_style_5"><input class="option_style_6" '+gurocheck+' id="g_hide" type="checkbox">注意のある画像を自動的に非表示</div><div class="option_style_5"><input class="option_style_6" '+gcheck+' id="a_hide" type="checkbox">画像のサムネイル表示をオフにする</div></div><div class="option_style_11"><button id="saveOptions" class="option_style_12" onclick="setoption()">変更を保存</button><button id="cancelOptions" class="option_style_13" onclick="rclose()">キャンセル</button></div>';
document.getElementById('rModal').style.display = 'block';
return;
}
}
function setoption() {
let ghide,ngword;
if (document.getElementById('g_hide').checked == true) ghide = 'auto';
if (document.getElementById('a_hide').checked == true) ghide = 'all';
localStorage.setItem('ghide', ghide);
if (document.getElementById('arecheck').checked == true) areload = true;
else areload = false;
localStorage.setItem('areload', areload);
if (document.getElementById('darkmode').checked == true) darkmode = true;
else darkmode = false;
localStorage.setItem('darkmode', darkmode);
if (document.getElementById('autodark').checked == true) autodark = true;
else autodark = false;
localStorage.setItem('autodark', autodark);
if (document.getElementById('spmode').checked == true) viewer = 'sp';
else viewer = 'pc';
localStorage.setItem('viewer', viewer);
if (document.getElementById('autoscroll').checked == true) autoscroll = true;
else autoscroll = false;
localStorage.setItem('autoscroll', autoscroll);
rclose();
}
function setclear() {
localStorage.clear();
sessionStorage.clear();
document.getElementById('ntxt').innerHTML = '完了';
}
function search() {
load(document.getElementById('searchInput').value);
}

1
static/t2.js Normal file
View File

@ -0,0 +1 @@
!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof exports?module.exports=a(require("jquery")):a(jQuery)}(function(a){function i(){var b,c,d={height:f.innerHeight,width:f.innerWidth};return d.height||(b=e.compatMode,(b||!a.support.boxModel)&&(c="CSS1Compat"===b?g:e.body,d={height:c.clientHeight,width:c.clientWidth})),d}function j(){return{top:f.pageYOffset||g.scrollTop||e.body.scrollTop,left:f.pageXOffset||g.scrollLeft||e.body.scrollLeft}}function k(){if(b.length){var e=0,f=a.map(b,function(a){var b=a.data.selector,c=a.$element;return b?c.find(b):c});for(c=c||i(),d=d||j();e<b.length;e++)if(a.contains(g,f[e][0])){var h=a(f[e]),k={height:h[0].offsetHeight,width:h[0].offsetWidth},l=h.offset(),m=h.data("inview");if(!d||!c)return;l.top+k.height>d.top&&l.top<d.top+c.height&&l.left+k.width>d.left&&l.left<d.left+c.width?m||h.data("inview",!0).trigger("inview",[!0]):m&&h.data("inview",!1).trigger("inview",[!1])}}}var c,d,h,b=[],e=document,f=window,g=e.documentElement;a.event.special.inview={add:function(c){b.push({data:c,$element:a(this),element:this}),!h&&b.length&&(h=setInterval(k,250))},remove:function(a){for(var c=0;c<b.length;c++){var d=b[c];if(d.element===this&&d.data.guid===a.guid){b.splice(c,1);break}}b.length||(clearInterval(h),h=null)}},a(f).on("scroll resize scrollstop",function(){c=d=null}),!g.addEventListener&&g.attachEvent&&g.attachEvent("onfocusin",function(){d=null})});

3
static/textarea.js Normal file
View File

@ -0,0 +1,3 @@
const placeholders = ["あなたが書くのを待っています...", "何をお考えですか?", "言いたいことは?", "ここに書いてください", "何かありましたか?", "コメントする..."];
let get = placeholders[Math.floor(Math.random() * placeholders.length)];
document.getElementById("bbs-textarea").placeholder = get;

31
static/thread.js Normal file
View File

@ -0,0 +1,31 @@
if (isSmartPhone() == true) {
let postbutton = '';
postbutton += '<div class="postbutton" style="display:none">'+
'<a href="javascript:void(0);" onclick="fopen()"> '+
'<svg viewBox="0 0 24 24" aria-hidden="true" class="postopen"><g><path d="M23 3c-6.62-.1-10.38 2.421-13.05 6.03C7.29 12.61 6 17.331 6 22h2c0-1.007.07-2.012.19-3H12c4.1 0 7.48-3.082 7.94-7.054C22.79 10.147 23.17 6.359 23 3zm-7 8h-1.5v2H16c.63-.016 1.2-.08 1.72-.188C16.95 15.24 14.68 17 12 17H8.55c.57-2.512 1.57-4.851 3-6.78 2.16-2.912 5.29-4.911 9.45-5.187C20.95 8.079 19.9 11 16 11zM4 9V6H1V4h3V1h2v3h3v2H6v3H4z"></path></g></svg>'+
' </a>'+
'</div>';
document.getElementById('body').innerHTML += '<link href="/static/sp.css" rel="stylesheet">'+postbutton;
}
if (localStorage.getItem('darkmode') == "true" || (localStorage.getItem('autodark') == "true" && window.matchMedia('(prefers-color-scheme: dark)').matches === true)) {
document.getElementById('body').innerHTML += '<link href="/static/dark.css" rel="stylesheet">';
if (isSmartPhone() == false) document.getElementById('body').innerHTML += '<style>#postForm{background: #262626 !important;}</style>';
}
if (localStorage.getItem('backimg')) {
if (localStorage.getItem('darkmode') == "true") document.getElementById('body').innerHTML += '<style>#body{position: relative;background-color: rgba(38,38,38,0.75) !important}.section {position: relative;} .section:before { content: ""; display: block; position: fixed; top: 0; left: 0; width: 100%; height: 100vh; background: url('+localStorage.getItem('backimg')+') center top no-repeat; background-size: 100% auto;}.asetting_4,.topmenu,.title,.thread,.cLength,.newposts,.bottommenu{background-color: transparent !important;}</style>';
else document.getElementById('body').innerHTML += '<style>#body{position: relative;}.section {position: relative;} .section:before { content: ""; display: block; position: fixed; top: 0; left: 0; width: 100%; height: 100vh; background: url('+localStorage.getItem('backimg')+') center top no-repeat; background-size: 100% auto;}.asetting_4,.topmenu,.title,.thread,.cLength,.newposts,.bottommenu{background-color: transparent !important;}</style>';
}
function isSmartPhone() {
let v = false;
if (navigator.userAgent.match(/iPhone|Android.+Mobile/)) {
v = true;
} else {
v = false;
}
if (localStorage.getItem('viewer') == 'sp') v = true;
else if (localStorage.getItem('viewer') == 'pc') v = false;
if (location.search.indexOf('v=sp') != -1) v = true;
if (location.search.indexOf('v=pc') != -1) v = false;
return v;
}

617
static/timeline.js Normal file
View File

@ -0,0 +1,617 @@
let imgurkey = '';
let spcheck = '';
let loaded = false;
if (isSmartPhone() == true) spcheck = 'checked';
let LINENUM,reloadbutton,getprev,preved;
if (localStorage.getItem('ghide') === null) localStorage.setItem('ghide', 'auto');
if (localStorage.getItem('areload') === null) localStorage.setItem('areload', false);
if (localStorage.getItem('darkmode') === null) localStorage.setItem('darkmode', false);
if (localStorage.getItem('autodark') === null) localStorage.setItem('autodark', true);
if (localStorage.getItem('autoscroll') === null) localStorage.setItem('autoscroll', false);
if (localStorage.getItem('origdate') === null) localStorage.setItem('origdate', false);
localStorage.setItem('autoPost', true);
localStorage.setItem('backlinkOpen', false);
localStorage.setItem('ankfixed', true);
if (localStorage.getItem('text2') === null) localStorage.setItem('text2', '');
sessionStorage.removeItem('text');
ghide = localStorage.getItem('ghide');
areload = localStorage.getItem('areload');
ankfixed = localStorage.getItem('ankfixed');
darkmode = localStorage.getItem('darkmode');
autodark = localStorage.getItem('autodark');
autoscroll = localStorage.getItem('autoscroll');
origdate = localStorage.getItem('origdate');
if (autodark == "true" && window.matchMedia('(prefers-color-scheme: dark)').matches === true) darkmode = "true";
let mutejson;
let mutelist = [];
mutejson = localStorage.getItem('mutelist');
if (mutejson) {
mutelist = JSON.parse(mutejson);
mutelist = mutelist.filter(Boolean);
}
let ngjson;
let nglist = [];
ngjson = localStorage.getItem('nglist');
if (ngjson) {
nglist = JSON.parse(ngjson);
nglist = nglist.filter(Boolean);
}
let ntjson;
let ntlist = [];
ntjson = localStorage.getItem('ngtitle');
if (ntjson) {
ntlist = JSON.parse(ntjson);
ntlist = ntlist.filter(Boolean);
}
let target;
if (localStorage.getItem('timeline')) target = localStorage.getItem('timeline');
const ls = new URLSearchParams(window.location.search);
let path = location.pathname.split('/');
let bbs = path[1];
let requestURL = '/'+bbs+'/index.json?'+time();
let n = 0;
document.head.innerHTML += '<link href="/static/st.css" rel="stylesheet" type="text/css"><link href="/static/milligram.css" rel="stylesheet" type="text/css"><link href="/static/s.css" rel="stylesheet" type="text/css"><link href="/static/read.css" rel="stylesheet" type="text/css"><link href="/static/lightbox.css" rel="stylesheet">';
document.body.innerHTML = '<section class="section"><div id="body"><div id="followheader" class="hidden maxwidth100 height2p5 stickymenu container" style="display: block;"><div class="row noflex maxwidth100 white padding0p5 maxheight2p5 borderbottomlightgrey"><div class="topmenu" id="header"><b class="menuitem">TL</b><a class="menuitem" href="/'+bbs+'/?m=subback">スレ一覧</a><a class="menuitem" href="/'+bbs+'/?m=subback&mode=history">履歴</a><a class="menuitem" href="/'+bbs+'/?m=subback&mode=unread">未読</a><a class="menuitem" href="/test/createthread.php?bbs='+bbs+'">スレ作成</a><a class="menuitem" href="javascript:Menu()">メニュー</a><a href="javascript:MenuClick(\'setting\')" class="menuitem">設定</a><div id="headtitle" class="menuitem" style="text-decoration: none;"></div></div></div></div><div id="subbacktitle"></div><div class="formbox" style="margin-top: 3rem;"><form method="POST" id="Form" accept-charset="UTF-8" action="/test/post-v2.php" style="display: block;margin-top: 2rem;"> <span class="fhead" style="border-radius: 3px 3px 0 0;color: #666;padding: 3px;text-align: left;"><span class="spformhead" style="display:inline !important;border-radius:3px 3px 0 0;color:#666;padding:3px;"><a id="iconlink" target="_blank"><img id="icon" class="icon" width="50" height="50" align="left"></a><input name="name" placeholder="名前" class="formelem maxwidth" style="width:50%;margin-top:.5rem;"></span><span class="submitbtn" style="color: #000;float: right;font-size: 28px;font-weight: bold;cursor: pointer;display: inline-block;padding-right: 5px;"><input type="submit" value="新規投稿" name="submit" onclick="Post()"></span></span><input name="mail" size="19" value="" placeholder="E-mail" class="formelem maxwidth"><div class="backmsg" style="display: inline-block;"><input value="on" type="checkbox" id="seticon" name="icon" checked=""><a href="/test/icon.html">アイコン</a> <a href="javascript:BackMSG()">下書きを復元</a></div><textarea rows="5" cols="70" name="comment" id="bbs-textarea" onchange="MSG()" class="formelem maxwidth" wrap="off"></textarea><br>画像:<input id="uploadImage" type="file" name="file" size="50" onchange="upload();"><br><input type="hidden" name="board" value="'+bbs+'"></form></div><div class="tlnotice" id="ntxt"></div><div class="newposts"><center><a href="javascript:load()">リロード<img alt="再読み込み" loading="lazy" decoding="async" data-nimg="1" style="color: transparent;" src="/static/reload.svg" width="16" height="16"></a></center><hr></div><div id="thread" class="thread"></div><div id="hidemetoo" class="side p85 slightpad nobullets"><div style="min-height:50px" id="rule">■ ローカルルール<br></div><div style="min-height:50px" id="kokuti">■ 告知欄<br></div><p style="margin: 5rem 0"></p></div><div class="footer">We\'re sure you\'ll have a good time with delight and/or 3ch. :)</div></div></section>';
if (localStorage.getItem('css') === null) localStorage.setItem('css', '');
document.body.innerHTML += "<style>"+localStorage.getItem('css')+"</style>";
let threadjs = document.createElement("script");
threadjs.src = "/static/thread.js";
document.body.appendChild(threadjs);
let boardjs = document.createElement("script");
boardjs.src = "/static/board.js";
document.body.appendChild(boardjs);
let textareajs = document.createElement("script");
textareajs.src = "/static/textarea.js";
document.body.appendChild(textareajs);
let jqueryjs = document.createElement("script");
jqueryjs.src = "/static/jquery-1.11.3.min.js";
document.body.appendChild(jqueryjs);
if (isSmartPhone() == false) document.getElementById('body').innerHTML += '<style>body{color:rgb(87, 111, 118) !important;}a{color:#485269 !important;}.thread,.title,.pagestats,.newposts,.formbox,.topmenu{padding-left:15px;padding-right:15px}.post{padding:1em 0}.number,span.name,span.date,span.ids,details{font-size:12px;color:rgb(87, 111, 118) !important;margin-right:5px;padding-left:0;margin-left:0}.thread,.newposts,.formbox{width: 75%;}a.id{color:rgb(87, 111, 118) !important;}.message{padding:10px 0;font-size:16px;min-height:4em}.side{display: block;border: .5px solid #DCDCDC; position: fixed; right: 0em; top: 0em; bottom: auto; width: 25%; height: 100%; z-index: 1; margin: 0; padding: 0; color: #333; padding-top: 10em; overflow: auto;scrollbar-width: none;}.side::-webkit-scrollbar{display: none;}#headtitle, b {color: rgb(87, 111, 118) !important;}</style>';
document.getElementById('body').innerHTML += '<style>.subject {background: gray;color: #fff;}div.postbutton{display: none !important;}</style>';
function load() {
document.getElementById('thread').innerHTML = '';
n = 0;
request = new XMLHttpRequest();
request.open('GET', requestURL);
request.responseType = 'json';
request.setRequestHeader('Pragma', 'no-cache');
request.setRequestHeader('Cache-Control', 'no-cache');
request.send();
request.onload = function() {
let listJSON = JSON.parse(JSON.stringify(request.response));
listJSON.forEach(function(post) {
let NG = false;
n++;
let name = post['name'];
let mail = post['mail'];
let date = TimeDiff(post['date']);
let id = post['id'];
let comment = post['comment'];
let thread = post['thread'];
let title = post['title'];
if (!thread) title = '';
if (title && target) {
if (title.search(target) == -1) return;
}
id = id.replace('ID:', '@');
if (isSmartPhone() == true) {
name = name.replace('<b>', '');
name = name.replace('</b>', '');
}
if (!NG) NG = MuteCheck(id);
if (!NG) NG = WordCheck(name+mail+comment);
if (!NG) NG = TitleCheck(title);
if (NG) return;
let newpost = document.createElement("div");
newpost.className = 'post '+mail;
if (id) newpost.className += ' '+id;
newpost.id = n;
if (isSmartPhone() == false) newpost.innerHTML = '<a class="number" href="javascript:reply(\''+mail+'\')">'+n+'</a><span class="name"><b>'+name+'</b></span><span class="date">'+date+' <a class="id" href="javascript:IdClick(\''+id+'\')">'+id+'</a> ['+mail+']</span><div class="message">'+comment+'</div><a href="/#'+bbs+'/'+thread+'/"><div class="subject">'+title+'</div></a>';
else newpost.innerHTML = '<a class="number" href="javascript:reply(\''+mail+'\')">'+n+'</a><span class="name">'+name+'</span><div class="message">'+comment+'</div><span class="date"><a class="id" href="javascript:IdClick(\''+id+'\')">'+id+'</a>'+date+' ['+mail+']</span><a href="/#'+bbs+'/'+thread+'/"><div class="subject">'+title+'</div></a>';
document.getElementById('thread').appendChild(newpost);
});
if (!loaded && ls.has('id')) IdClick(ls.get('id'));
loaded = true;
}
}
load();
loadready();
let modal = document.createElement('div');
modal.innerHTML = '<div id="Modal" style="background-color:#fafafa;margin:auto;padding:20px;border:1px solid #888;width:500px;max-width:95%;"><span style="color:#000;float:right;font-size:28px;font-weight:bold;cursor:pointer;" class="rclose" onclick="rclose()">×</span><div id="modal_text" style="width: 100%;color:#808080;font-family: arial,helvetica,sans-serif;font-size:10pt;margin: 2em 4px 0 0;">'+
'</div></div>';
modal.id = 'rModal';
modal.style.cssText = 'position: fixed; z-index: 20; left: 0px; top: 0px; width: 100%; height: 100%; overflow: auto; background-color: rgba(0, 0, 0, 0.4);';
modal.style.display = 'none';
document.getElementById('body').appendChild(modal);
function Post() {
let cookname = escape(document.getElementsByName("name")[0].value);
document.cookie = "NAME="+cookname+"; Max-Age=7776000; path=/";
let cookmail = escape(document.getElementsByName("mail")[0].value);
document.cookie = "MAIL="+cookmail+"; Max-Age=7776000; path=/";
}
function l(e){
var N=getCookie("NAME"),M=getCookie("MAIL"),i;
with(document) for(i=0;i<forms.length;i++)if(forms[i].name&&forms[i].mail)with(forms[i]){
name.value=N;
mail.value=M;
}
}
onload=l;
function getCookie(key, tmp1, tmp2, xx1, xx2, xx3) {
tmp1 = " " + document.cookie + ";";
while(tmp1.match(/\+/)) {tmp1 = tmp1.replace("+", " ");};
xx1 = xx2 = 0;
len = tmp1.length;
while (xx1 < len) {
xx2 = tmp1.indexOf(";", xx1);
tmp2 = tmp1.substring(xx1 + 1, xx2);
xx3 = tmp2.indexOf("=");
if (tmp2.substring(0, xx3) == key) {return(unescape(tmp2.substring(xx3 + 1, xx2 - xx1 - 1)));}
xx1 = xx2 + 1;
}
return("");
}
if (!getCookie("WrtAgreementKey")) document.getElementById('Form').innerHTML = '<div><a href="/test/auth.php">投稿時に使用する同意鍵がありません。<br>投稿を行うには投稿前確認画面での同意が必要です。</a></div>'+document.getElementById('Form').innerHTML;
function loadready() {
if (typeof jQuery === 'undefined') {
setTimeout(loadready, 50);
return;
}
let lightbox = document.createElement("script");
lightbox.src = "/static/lightbox.js";
document.getElementById('body').appendChild(lightbox);
let t2 = document.createElement("script");
t2.src = "/static/t2.js";
document.getElementById('body').appendChild(t2);
$(document).ready(function(){
$('#linkToTop').on('click',function(e){
e.preventDefault();
$('html,body').scrollTop(0);
});
$(document).on("click",".up",function(e){
$("html,body").animate({scrollTop:$(".topmenu").scrollTop()},{duration:500});
e.preventDefault();
});
$(document).on("click",".down",function(e){
$("html,body").animate({scrollTop:$(".footer").position().top},{duration:500});
e.preventDefault();
});
$("body").append(
'<div class="up_down_div" style="z-index:10000;position: fixed; bottom: 220px; right: 10px; top: 333px;">'+
'<div style="position:relative">'+
'<div style="font-size:16px;position:absolute;top:-30px;right:0px">'+
'<a href="#" class="up" style="color: rgba(0, 0, 0, 0.3) !important; "><div class="fas fa-chevron-circle-up">▲</div></a>'+
'</div>'+
'<div style="font-size:16px;position:absolute;top:+30px;right:0px">'+
'<a href="#" class="down" style="color: rgba(0, 0, 0, 0.3) !important; "><div class="fas fa-chevron-circle-down">▼</div></a>'+
'</div>'+
'</div>'+
'</div>'
);
});
}
if (!getCookie("icon") && document.getElementById('seticon')) document.getElementById('seticon').style.display = 'none';
if (getCookie("icon")) document.getElementById("icon").src = getCookie("icon");
if (getCookie("homepage")) document.getElementById("iconlink").href = getCookie("homepage");
document.getElementById('body').onclick = function (event) {
let x = event.clientX;
let y = event.clientY;
let e = document.elementsFromPoint(x, y);
let repid,menid,rt,ri;
e.forEach(function(el) {
if (el.className == "rep-comment") {
repid = el.id;
}
else if (el.id == "Modal") {
menid = el.id;
}
if (el.className == "number" || el.className == "menuitem") rt = true;
if (el.className == "id" || el.className == "reply" || el.className == "ank2" || el.className == "id id2") ri = true;
});
let reps = document.querySelectorAll(".rep-comment");
if (!reps) return;
reps.forEach(function(v) {
var timer = setTimeout(function(){
if (v.id == repid) return;
v.style.display = 'none';
},100);
});
let mens = document.querySelectorAll("#Modal");
if (!mens) return;
mens.forEach(function(v) {
var timer = setTimeout(function(){
if (v.id == menid || rt || ri) return;
document.getElementById('rModal').style.display = 'none';
},100);
});
}
function isSmartPhone() {
let v = false;
if (navigator.userAgent.match(/iPhone|Android.+Mobile/)) {
v = true;
} else {
v = false;
}
if (localStorage.getItem('viewer') == 'sp') v = true;
else if (localStorage.getItem('viewer') == 'pc') v = false;
if (location.search.indexOf('v=sp') != -1) v = true;
if (location.search.indexOf('v=pc') != -1) v = false;
return v;
}
function mute(target) {
if (target == 'list') {
let mlisthtml = '<div style="font-weight:bold;">ミュートするID</div><input type="text" id="addmute"><button onclick="AddM()">追加</button>&emsp;<button onclick="mute(\'reset\')">リセット</button><br>※クリックで解除<br>';
for (let i = 0; i < mutelist.length; i++) {
mlisthtml += '<a class="menulink" href="javascript:unmute(\''+mutelist[i]+'\')">'+mutelist[i]+'</a>&emsp;';
}
document.getElementById('modal_text').innerHTML = mlisthtml;
document.getElementById('rModal').style.display = 'block';
return;
}
if (target == 'reset') {
mutelist = [];
mutejson = JSON.stringify(mutelist, undefined, 1);
localStorage.setItem('mutelist', mutejson);
document.getElementById('ntxt').innerHTML = 'リセットしました';
return;
}
let a;
for (let i = 0; i < mutelist.length; i++) {
if (target == mutelist[i]) {
a = true;
break;
}
}
if (a == true) return;
let mutecount = mutelist.length + 1;
mutelist[mutecount-1] = target;
mutejson = JSON.stringify(mutelist, undefined, 1);
localStorage.setItem('mutelist', mutejson);
document.getElementById('ntxt').innerHTML = 'ミュートしました';
}
function AddM() {
let target = document.getElementById('addmute').value;
let a;
for (let i = 0; i < mutelist.length; i++) {
if (target == mutelist[i]) {
a = true;
break;
}
}
if (a == true) return;
let mutecount = mutelist.length + 1;
mutelist[mutecount-1] = target;
mutejson = JSON.stringify(mutelist, undefined, 1);
localStorage.setItem('mutelist', mutejson);
document.getElementById('ntxt').innerHTML = '追加しました';
}
function unmute(target) {
let a;
for (let i = 0; i < mutelist.length; i++) {
if (target == mutelist[i]) {
mutelist[i] = '';
break;
}
}
mutejson = JSON.stringify(mutelist, undefined, 1);
localStorage.setItem('mutelist', mutejson);
document.getElementById('ntxt').innerHTML = 'ミュートを解除しました';
}
function MuteCheck(target) {
target = target.replace('ID:', '@');
let N;
for (let i = 0; i < mutelist.length; i++) {
if (!mutelist[i]) continue;
let NG = false;
if (target.search(mutelist[i]) != -1) NG = true;
if (NG) {
N = mutelist[i];
break;
}
}
if (N) return N;
}
function WordCheck(target) {
let N;
for (let i = 0; i < nglist.length; i++) {
if (!nglist[i]) continue;
let NG = false;
if (target.search(nglist[i]) != -1) NG = true;
if (NG) {
N = nglist[i];
break;
}
}
if (N) return 'Word:'+N;
}
function TitleCheck(target) {
let N;
for (let i = 0; i < ntlist.length; i++) {
if (!ntlist[i]) continue;
let NG = false;
if (target.search(ntlist[i]) != -1) NG = true;
if (NG) {
N = ntlist[i];
break;
}
}
if (N) return true;
}
function NGWORD() {
let target = document.getElementById('addngword').value;
let a;
for (let i = 0; i < nglist.length; i++) {
if (target == nglist[i]) {
a = true;
break;
}
}
if (a == true) return;
let ngcount = nglist.length + 1;
nglist[ngcount-1] = target;
ngjson = JSON.stringify(nglist, undefined, 1);
localStorage.setItem('nglist', ngjson);
document.getElementById('ntxt').innerHTML = '追加しました';
notice();
}
function NGTITLE() {
let target = document.getElementById('addngtitle').value;
let a;
for (let i = 0; i < ntlist.length; i++) {
if (target == ntlist[i]) {
a = true;
break;
}
}
if (a == true) return;
let ntcount = ntlist.length + 1;
ntlist[ntcount-1] = target;
ntjson = JSON.stringify(ntlist, undefined, 1);
localStorage.setItem('ngtitle', ntjson);
document.getElementById('ntxt').innerHTML = '追加しました';
notice();
}
function unngword(target) {
if (target == 'reset') {
nglist = [];
ngjson = JSON.stringify(nglist, undefined, 1);
localStorage.setItem('nglist', ngjson);
document.getElementById('ntxt').innerHTML = 'リセットしました';
notice();
return;
}
let a;
for (let i = 0; i < nglist.length; i++) {
if (target == nglist[i]) {
nglist[i] = '';
break;
}
}
ngjson = JSON.stringify(nglist, undefined, 1);
localStorage.setItem('nglist', ngjson);
document.getElementById('ntxt').innerHTML = '解除しました';
notice();
}
function unngtitle(target) {
if (target == 'reset') {
ntlist = [];
ntjson = JSON.stringify(ntlist, undefined, 1);
localStorage.setItem('ngtitle', ntjson);
document.getElementById('ntxt').innerHTML = 'リセットしました';
notice();
return;
}
let a;
for (let i = 0; i < ntlist.length; i++) {
if (target == ntlist[i]) {
ntlist[i] = '';
break;
}
}
ntjson = JSON.stringify(ntlist, undefined, 1);
localStorage.setItem('ntlist', ngjson);
document.getElementById('ntxt').innerHTML = '解除しました';
notice();
}
function rclose() {
document.getElementById('rModal').style.display = 'none';
document.getElementById('modal_text').innerHTML = '';
}
function Menu() {
document.getElementById('modal_text').innerHTML = '<a class="menulink" href="/test/TL.html">タイムライン絞り込み設定</a><div style="font-weight:bold;">ミュート設定</div><a class="menulink" href="javascript:mute(\'list\')">ID</a>&emsp;<a class="menulink" href="javascript:MenuClick(\'ngword\')">Word</a>&emsp;<a class="menulink" href="javascript:MenuClick(\'ngtitle\')">タイトル</a><div style="font-weight:bold;">その他</div><a class="menulink" href="javascript:MenuClick(\'setting\')">閲覧設定</a>&emsp;<a class="menulink" href="/test/backimg.html">背景画像</a>&emsp;<a class="menulink" href="/test/css.html">カスタムcss</a><br><a class="menulink" href="javascript:setclear()">全ログを削除</a>&emsp;<a class="menulink" href="/test/auth.php">認証</a>';
document.getElementById('rModal').style.display = 'block';
}
function MenuClick(val) {
if (val == "ngword") {
let nlisthtml = '<div style="font-weight:bold;">ミュートするワード</div>※クリックで解除<br>';
nlisthtml += '<input type="text" id="addngword"><button onclick="NGWORD()">追加</button>&emsp;<button onclick="unngword(\'reset\')">リセット</button><br>'
for (let i = 0; i < nglist.length; i++) {
nlisthtml += '<a class="menulink" href="javascript:unngword(\''+nglist[i]+'\')">'+nglist[i]+'</a>&emsp;';
}
document.getElementById('modal_text').innerHTML = nlisthtml;
document.getElementById('rModal').style.display = 'block';
return;
}
if (val == "ngtitle") {
let nlisthtml = '<div style="font-weight:bold;">ミュートするタイトル</div>※クリックで解除<br>';
nlisthtml += '<input type="text" id="addngtitle"><button onclick="NGTITLE()">追加</button>&emsp;<button onclick="unngtitle(\'reset\')">リセット</button><br>'
for (let i = 0; i < ntlist.length; i++) {
nlisthtml += '<a class="menulink" href="javascript:unngtitle(\''+ntlist[i]+'\')">'+ntlist[i]+'</a>&emsp;';
}
document.getElementById('modal_text').innerHTML = nlisthtml;
document.getElementById('rModal').style.display = 'block';
return;
}
if (val == "setting") {
let arecheck,gurocheck,autocheck,gcheck,darkcheck,adarkcheck,dcheck;
if (areload == "true") arecheck = 'checked';
if (autoscroll == "true") autocheck = 'checked';
if (ghide == "all") gcheck = 'checked';
if (ghide == "auto") gurocheck = 'checked';
if (localStorage.getItem('darkmode') == "true") darkcheck = 'checked';
if (autodark == "true") adarkcheck = 'checked';
if (origdate == "true") dcheck = 'checked';
document.getElementById('modal_text').innerHTML = '<div class="option_style_2">閲覧設定</div><div class="option_style_3">&emsp;</div><div class="option_style_4"><div class="option_style_5"><input class="option_style_6" '+spcheck+' id="spmode" type="checkbox">スマホ用表示</div><div class="option_style_5"><input class="option_style_6" '+darkcheck+' id="darkmode" type="checkbox">ダークモード</div><div class="option_style_5"><input class="option_style_6" '+adarkcheck+' id="autodark" type="checkbox">デバイスのダークモードと同期する</div><div class="option_style_5"><input class="option_style_6" '+arecheck+' id="arecheck" type="checkbox">5秒間隔で自動更新する</div><div class="option_style_5"><input class="option_style_6" '+autocheck+' id="autoscroll" type="checkbox">新着投稿の位置まで自動スクロール</div><div class="option_style_5"><input class="option_style_6" '+gurocheck+' id="g_hide" type="checkbox">注意のある画像を自動的に非表示</div><div class="option_style_5"><input class="option_style_6" '+gcheck+' id="a_hide" type="checkbox">画像のサムネイル表示をオフにする</div><div class="option_style_5"><input class="option_style_6" '+dcheck+' id="origdate" type="checkbox">投稿日時表記の短縮を行わない</div></div><div class="option_style_11"><button id="saveOptions" class="option_style_12" onclick="setoption()">変更を保存</button><button id="cancelOptions" class="option_style_13" onclick="rclose()">キャンセル</button></div>';
document.getElementById('rModal').style.display = 'block';
return;
}
}
function setoption() {
let ghide,ngword;
if (document.getElementById('g_hide').checked == true) ghide = 'auto';
if (document.getElementById('a_hide').checked == true) ghide = 'all';
localStorage.setItem('ghide', ghide);
if (document.getElementById('arecheck').checked == true) areload = true;
else areload = false;
localStorage.setItem('areload', areload);
if (document.getElementById('darkmode').checked == true) darkmode = true;
else darkmode = false;
localStorage.setItem('darkmode', darkmode);
if (document.getElementById('autodark').checked == true) autodark = true;
else autodark = false;
localStorage.setItem('autodark', autodark);
if (document.getElementById('spmode').checked == true) viewer = 'sp';
else viewer = 'pc';
localStorage.setItem('viewer', viewer);
if (document.getElementById('autoscroll').checked == true) autoscroll = true;
else autoscroll = false;
localStorage.setItem('autoscroll', autoscroll);
if (document.getElementById('origdate').checked == true) origdate = true;
else origdate = false;
localStorage.setItem('origdate', origdate);
rclose();
}
function setclear() {
localStorage.clear();
sessionStorage.clear();
document.getElementById('ntxt').innerHTML = '完了';
}
function upload() {
const preview = document.querySelector('img');
const file = document.querySelector('input[type=file]').files[0];
const reader = new FileReader();
reader.addEventListener("load", () => {
base64Url = reader.result;
base64 = base64Url.replace(new RegExp('data.*base64,'), '');
imgur();
}, false);
if (file) {
reader.readAsDataURL(file);
}
/// APIに渡すときは先頭の data:~~~base64 を除外
function imgur() {
document.getElementById('ntxt').innerHTML = '通信中';
$.ajax({
url: 'https://api.imgur.com/3/image',
method: 'POST',
headers: {
"Authorization": 'Client-ID '+imgurkey
},
data: {
image: base64,
type: 'base64'
},
success: function(r){
imgurlink = r.data.link
document.getElementById('bbs-textarea').value += '\n'+imgurlink;
document.getElementById('ntxt').innerHTML = '画像をアップロードしました';
},
error: function () {
document.getElementById('ntxt').innerHTML = 'アップロードできません';
}
});
}
}
function IdClick(value) {
if (!document.getElementsByClassName(value)) return;
let idcount = document.getElementsByClassName(value).length;
let ins = '<div><span style="font-weight:bold;">'+value+'</span> '+idcount+'レス</div><div><a class="mbutton" href="javascript:mute(\''+value+'\')" style="color:black;">ミュートする</a></div>'
for (let i = 0; i < idcount; i++) {
ins += '<div class="post">'+document.getElementsByClassName(value)[i].innerHTML+'</div>';
}
document.getElementById('modal_text').innerHTML = ins;
document.getElementById('rModal').style.display = 'block';
}
function MSG() {
if (document.getElementById('bbs-textarea').value) {
sessionStorage.setItem('text', document.getElementById('bbs-textarea').value);
localStorage.setItem('text2', document.getElementById('bbs-textarea').value);
}
}
function BackMSG() {
document.getElementById('bbs-textarea').value = localStorage.getItem('text2');
}
function TimeDiff(postDay) {
if (!postDay) return 'NG';
if (origdate == "true") return postDay; // 投稿日時を変換しない設定の場合はそのまま返す
let posted = new Date(postDay);
let diff = new Date().getTime() - posted.getTime();
let progress = new Date(diff);
if (progress.getUTCFullYear() - 1970) {
return progress.getUTCFullYear() - 1970 + '年前';
}else if (progress.getUTCMonth()) {
return progress.getUTCMonth() + 'ヶ月前';
}else if (progress.getUTCDate() - 1) {
return progress.getUTCDate() - 1 + '日前';
}else if (progress.getUTCHours()) {
return progress.getUTCHours() + '時間前';
}else if (progress.getUTCMinutes()) {
return progress.getUTCMinutes() + '分前';
}else if (progress.getUTCSeconds() >= 10) {
return progress.getUTCSeconds() + '秒前';
}else if (progress.getUTCSeconds() >= 0) {
return 'たった今'; // 10秒未満
}else {
return postDay; // 未対応の形式の場合はマイナスの値になるのでそのまま返す
}
}
function time() {
var date = new Date();
var a = date.getTime();
return Math.floor(a / 1000);
}
function reply(n) {
document.getElementById('bbs-textarea').value += '>'+n+'\n';
}

7
test/.htaccess Normal file
View File

@ -0,0 +1,7 @@
<Files ~ "^(bbs-main\.php|createcode\.cgi)$">
deny from all
</Files>
RewriteEngine on
RewriteRule read.cgi read.php
RewriteRule bbs.cgi bbs.php
SetEnvIf Request_URI "bbs.php$" CONTENT_TYPE=application/x-www-form-urlencoded

2
test/.user.ini Normal file
View File

@ -0,0 +1,2 @@
error_reporting = E_COMPILE_ERROR | E_RECOVERABLE_ERROR | E_ERROR | E_CORE_ERROR | E_PARSE
display_errors="1"

1
test/HAP/.htaccess Normal file
View File

@ -0,0 +1 @@
deny from all

15
test/TL.html Normal file
View File

@ -0,0 +1,15 @@
<!DOCTYPE html><html lang="ja"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"><title>タイムライン絞り込み設定</title><link href="/static/a.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="/static/jquery-1.11.3.min.js"></script></head><body><div id="container"><section><h1 class="section-title">タイムライン絞り込み設定</h1><div class="contents"><input id="css" type="text" class="form-control" name="css" placeholder="絞り込むスレッドタイトル(正規表現可)"></div><div class="contents"><button onclick="setcss()" class="btn btn-primary btn-block">設定</button><br><br><button onclick="delcss()" class="btn btn-primary btn-block">削除</button><h3 id="ntxt"></h3></div></section></div>
<hr><a href="#" onclick="window.history.go(-1);">前ページに戻る</a><br><a href="#" onclick="window.history.go(-2);">2つ前のページに戻る</a><br><a href="https://rentalbbs.net/">トップページに戻る</a>
<script>
if (localStorage.getItem('timeline')) document.getElementById('css').value = localStorage.getItem('timeline');
function setcss() {
localStorage.setItem('timeline', document.getElementById('css').value);
document.getElementById('ntxt').innerHTML = '設定完了';
}
function delcss() {
localStorage.removeItem('timeline');
document.getElementById('ntxt').innerHTML = '削除完了';
}
</script>
</body></html>

61
test/admin.php Normal file
View File

@ -0,0 +1,61 @@
<?php
error_reporting(E_COMPILE_ERROR | E_RECOVERABLE_ERROR | E_ERROR | E_CORE_ERROR | E_PARSE);
header('Content-Type: text/html; charset=UTF-8');
if (!isset($_REQUEST['bbs'])) $_REQUEST['bbs'] = '';
if (!isset($_REQUEST['mode'])) $_REQUEST['mode'] = '';
if (!isset($_REQUEST['key'])) $_REQUEST['key'] = '';
$PATH = "../".$_REQUEST['bbs']."/";
$passfile = $PATH."passfile.cgi";
$admin = @file_get_contents($passfile);
if (!isset($_POST['password'])) $_POST['password'] = '';
if (!$_REQUEST['bbs'] || !$_POST['password']) {
?><!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content>
<meta name="author" content>
<title>管理ページ</title>
<link rel="stylesheet" href="/static/a.css">
</head>
<body>
<form class="form-signin" method="post" action="?bbs=<?=$_REQUEST['bbs']?>&mode=<?=$_REQUEST['mode']?>&key=<?=$_REQUEST['key']?>">
<h1 class="font-weight-normal mb-3">ログイン</h1>
<input name="bbs" class="form-control" placeholder="ディレクトリ名" value="<?=$_REQUEST['bbs']?>" required="">
<input type="password" name="password" class="form-control" placeholder="パスワード" value="<?=$_POST['password']?>" required="">
<p class="mb-3"></p>
<input name="login_be_normal_user" class="btn btn-primary btn-block" type="submit" value="ログイン">
</form>
</body>
</html>
<?php
exit;
}elseif (!password_verify($_POST['password'], $admin)) {
Finish('<b>パスワードが違います</b><div class="back"><a href="'.$_SERVER['HTTP_REFERER'].'">← 戻る</a></div>');
}
// 設定ファイルを読む
$setfile = $PATH."setting.json";
$settxt = $PATH."SETTING.TXT";
$SET = '';
if (is_file($setfile)) {
$SETTING = json_decode(file_get_contents($setfile), true);
}else Finish('<b>設定ファイルがありません</b><div class="back"><a href="'.$_SERVER['HTTP_REFERER'].'">← 戻る</a></div>');
// 設定の一覧ページ
require './operate/settinglist.php';
function Finish($value) {
?><!DOCTYPE HTML>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link href="/static/a.css" rel="stylesheet" type="text/css">
</head>
<body>
<?=$value?>
</body>
</html>
<?php exit; }

250
test/auth.php Normal file
View File

@ -0,0 +1,250 @@
<?php
error_reporting(E_COMPILE_ERROR | E_RECOVERABLE_ERROR | E_ERROR | E_CORE_ERROR | E_PARSE);
# Google reCAPTCHA sitekey,secretkey
$sitekey = '';
$secretkey = '';
$FORCESSL = true; #https未対応の場合はfalseにすること
$NOWTIME = time();
$HOST = gethostbyaddr($_SERVER['REMOTE_ADDR']);
$area = [];
$area["district"] = $area['proxy'] = $area['hosting'] = $area['regionName'] = $area['city'] = $area['countryCode'] = $area['mobile'] = $area["asname"] = '';
if (!isset($_SERVER['HTTP_SEC_CH_UA'])) $_SERVER['HTTP_SEC_CH_UA'] = '';
if (!isset($_SERVER['HTTP_SEC_CH_UA_PLATFORM'])) $_SERVER['HTTP_SEC_CH_UA_PLATFORM'] = '';
if (!isset($_SERVER['HTTP_SEC_CH_UA_PLATFORM_VERSION'])) $_SERVER['HTTP_SEC_CH_UA_PLATFORM_VERSION'] = '';
if (!isset($_SERVER['HTTP_SEC_CH_UA_BITNESS'])) $_SERVER['HTTP_SEC_CH_UA_BITNESS'] = '';
if (!isset($_SERVER['HTTP_SEC_CH_UA_ARCH'])) $_SERVER['HTTP_SEC_CH_UA_ARCH'] = '';
if (!isset($_SERVER['HTTP_SEC_CH_UA_MODEL'])) $_SERVER['HTTP_SEC_CH_UA_MODEL'] = '';
if (!isset($_SERVER['HTTP_SEC_CH_UA_MOBILE'])) $_SERVER['HTTP_SEC_CH_UA_MOBILE'] = '';
if (!isset($_SERVER['HTTP_SEC_CH_UA_FULL_VERSION_LIST'])) $_SERVER['HTTP_SEC_CH_UA_FULL_VERSION_LIST'] = '';
// IPv6に対応したサーバ用
$count_semi = substr_count($_SERVER['REMOTE_ADDR'], ':');
$count_dot = substr_count($_SERVER['REMOTE_ADDR'], '.');
if ($count_semi > 0 && $count_dot == 0) $ipv6 = $_SERVER['REMOTE_ADDR'];
else $ipv6 = '';
// IPアドレス範囲
if ($ipv6) {
$d = explode(":", $_SERVER['REMOTE_ADDR']);
// IPv6では後半を切り捨て
$IP_ADDR = $d[0].":".$d[1].":".$d[2].":".$d[3];
$range = $d[0].":".$d[1].":".substr($d[2], 0, 2);
}else {
$IP_ADDR = $_SERVER['REMOTE_ADDR'];
$d = explode(".", $_SERVER['REMOTE_ADDR']);
// IPアドレスの先端一部を取り出す
$range = $d[0];
}
$target = array(':', '.');
$fileipaddr = str_replace($target, '', $IP_ADDR);
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === "https") {
$_SERVER['HTTPS'] = 'on';
}
if ($FORCESSL && empty($_SERVER['HTTPS'])) {
header("Location: https://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}");
exit;
}
header("Accept-CH: Sec-CH-UA-Arch, Sec-CH-UA-Bitness, Sec-CH-UA-Full-Version-List, Sec-CH-UA-Mobile, Sec-CH-UA-Model, Sec-CH-UA-Platform, Sec-CH-UA-Platform-Version");
header("Content-type: text/html; charset=UTF-8");
if ($_SERVER["REQUEST_METHOD"] == "POST") {
# UAチェック
if (strlen($_SERVER['HTTP_USER_AGENT']) != mb_strlen($_SERVER['HTTP_USER_AGENT'],"UTF-8") || strlen($_SERVER['HTTP_USER_AGENT']) < 7 || strlen($_SERVER['HTTP_USER_AGENT']) > 384 || preg_match("/[^a-zA-Z0-9\-\/\.\(\):;,_\s]/", $_SERVER['HTTP_USER_AGENT'])) exit('認証エラー');
if (strpos($_SERVER['HTTP_USER_AGENT'], 'Mozilla/5.0') === false) exit('専ブラからは認証できません。Webブラウザを使用してください');
// refererが無い
if (empty($_SERVER['HTTP_REFERER'])) exit('認証エラー');
else {
if (!stristr($_SERVER['HTTP_REFERER'], $_SERVER['HTTP_HOST'])) exit('認証エラー');
if ($_SERVER['HTTP_HOST'] != $_SERVER['SERVER_NAME']) exit('認証エラー');
}
// 簡易PROXYチェック
$PROXY = false;
if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && $_SERVER['REMOTE_ADDR'] != $_SERVER['HTTP_X_FORWARDED_FOR']) $PROXY = true;
if (isset($_SERVER['HTTP_VIA'])) $PROXY = true;
if (isset($_SERVER['HTTP_FORWARDED'])) $PROXY = true;
if (isset($_SERVER['HTTP_CACHE_INFO'])) $PROXY = true;
if (isset($_SERVER['HTTP_CLIENT_IP'])) $PROXY = true;
if (isset($_SERVER['HTTP_PROXY_CONNECTION'])) $PROXY = true;
if (isset($_SERVER['HTTP_SP_HOST'])) $PROXY = true;
if (isset($_SERVER['HTTP_X_LOCKING'])) $PROXY = true;
#if ($PROXY) exit('認証エラー'); // 環境によっては誤判定が起きるので使わない
if (isset($_POST['g-recaptcha-response'])) {
$url = 'https://www.google.com/recaptcha/api/siteverify';
$param = array(
'secret' => $secretkey,
'response' => $_POST['g-recaptcha-response']
);
$context = array(
'http' => array(
'method' => 'POST',
'header' => 'Content-Type: application/x-www-form-urlencoded\r\n',
'content' => http_build_query($param)
)
);
$json = file_get_contents($url, false, stream_context_create($context));
$results = json_decode($json,true);
$success = $results["success"];
$error = $results["error-codes"];
if (strlen($_POST['ClientID']) != 32 || $success == false || $error) {
exit("認証に失敗しました。再度やりなおしてください");
}
// smart phone marks
$admin = false;
$SLIP_NAME = 'JP';
$slip = "0";
$SLIP_SP = $MM = $WF = false;
@include './extend/smartphonemarks.php';
$options =array(
'http' =>array(
'method' => "GET",
)
);
$url = "http://ip-api.com/json/".$_SERVER['REMOTE_ADDR']."?fields=countryCode,regionName,city,asname,mobile,proxy,hosting&lang=ja";
$cp = curl_init();
/*オプション:リダイレクトされたらリダイレクト先のページを取得する*/
curl_setopt($cp, CURLOPT_RETURNTRANSFER, 1);
/*オプション:URLを指定する*/
curl_setopt($cp, CURLOPT_URL, $url);
/*オプション:タイムアウト時間を指定する*/
curl_setopt($cp, CURLOPT_TIMEOUT, 2000);
/*オプション:ユーザーエージェントを指定する*/
curl_setopt($cp, CURLOPT_USERAGENT, "Mozilla/5.0 P2/2.5 (iPad; CPU OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/87.0.4280.77 Mobile/15E148 Safari/604.1");
curl_setopt($cp, CURLOPT_HEADER, true);
$source = curl_exec($cp);
$curlInfo = curl_getinfo($cp);
// ヘッダを一緒に出力したときは分割させる
$headerSize = false;
if ( isset($curlInfo["header_size"]) && $curlInfo["header_size"]!="" ) {
$headerSize = $curlInfo["header_size"];
}
$head = substr($source, 0, $headerSize); // ヘッダ部
$head = str_replace(["\r\n", "\r", "\n"], "\n", $head);
$header = explode("\n", $head);
foreach ($header as $tmp) {
list($key, $value) = explode(": ", $tmp);
$HTTP[$key] = $value;
}
$data = substr($source, $headerSize); // ボディ部
curl_close($cp);
$area = json_decode($data, true);
// 国名取得(CFを通さないサーバの場合)
if (empty($_SERVER['HTTP_CF_IPCOUNTRY'])) {
if ($area["countryCode"]) $_SERVER['HTTP_CF_IPCOUNTRY'] = $area["countryCode"];
else $_SERVER['HTTP_CF_IPCOUNTRY'] = "JP";
}
// モバイルを検出
if ($area['mobile'] == true && $slip == "0" && strpos($HOST, 'bbtec.net') === false && strpos($HOST, 'ocn.ne.jp') === false && strpos($HOST, 'dion.ne.jp') === false) {
$slip = "S";
$SLIP_SP = true;
$SLIP_NAME = $area["asname"];
}
// User-Agent Client Hints
if ($_SERVER['HTTP_SEC_CH_UA_FULL_VERSION_LIST']) $_SERVER['HTTP_SEC_CH_UA'] = $_SERVER['HTTP_SEC_CH_UA_FULL_VERSION_LIST'];
$CH_UA = $_SERVER['HTTP_SEC_CH_UA'].$_SERVER['HTTP_SEC_CH_UA_PLATFORM'].$_SERVER['HTTP_SEC_CH_UA_PLATFORM_VERSION'].$_SERVER['HTTP_SEC_CH_UA_BITNESS'].$_SERVER['HTTP_SEC_CH_UA_ARCH'].$_SERVER['HTTP_SEC_CH_UA_MODEL'].$_SERVER['HTTP_SEC_CH_UA_MOBILE'];
if (!$CH_UA) $CH_UA = $_SERVER['HTTP_USER_AGENT'];
$ACCEPT = $_SERVER['HTTP_ACCEPT'].$_SERVER['HTTP_ACCEPT_LANGUAGE'].$_SERVER['CONTENT_TYPE'];
if (!preg_match("/\.jp$/i", $HOST) && !preg_match("/\.bbtec\.net$/", $HOST) && !$ipv6 && !$SLIP_SP && !$MM && !$WF) $slip = "H";
# 鍵を生成する(ClientIDから生成される8桁の数値)
$WrtAgreementKey = substr(preg_replace("/[^0-9]/", "", md5($_POST['ClientID'])), 0, 8);
# 記録ファイルが設置された場所。
$HAP_PATH = './HAP/';
$ip_file = $HAP_PATH.'ip_'.hash('sha256', $fileipaddr).'.cgi';
$kr_file = $HAP_PATH.'kr_'.md5($range.$area["asname"].$CH_UA.$ACCEPT).'.cgi';
$nokr = $noip = false;
if (is_file($kr_file)) {
if (filemtime($kr_file) + 2592000 > $NOWTIME) $WrtAgreementKey = file_get_contents($kr_file);
else $nokr = true;
}else $nokr = true;
if (is_file($ip_file)) {
if (filemtime($ip_file) + 2592000 > $NOWTIME) $WrtAgreementKey = file_get_contents($ip_file);
else $noip = true;
}else $noip = true;
if ($noip) file_put_contents($ip_file, $WrtAgreementKey, LOCK_EX);
if ($nokr) file_put_contents($kr_file, $WrtAgreementKey, LOCK_EX);
$clientid = hash('sha256', hash('sha256', md5($WrtAgreementKey).preg_replace("/[^0-9]/", "", md5($WrtAgreementKey))));
$file = $HAP_PATH.$clientid.'.cgi';
if (!is_file($file)) {
$HAP = ["first"=>$NOWTIME,
"last"=>'',
"comment"=>'',
"HOST"=>$HOST,
"REMOTE_ADDR"=>$IP_ADDR,
"USER_AGENT"=>$_SERVER['HTTP_USER_AGENT'],
"CH_UA"=>$CH_UA,
"ACCEPT"=>$ACCEPT,
"range"=>$range,
"provider"=>$area["asname"],
"country"=>$_SERVER['HTTP_CF_IPCOUNTRY'],
"region"=>$area["regionName"].$area["city"].$area["district"],
"proxy"=>$area["proxy"],
"hosting"=>$area["hosting"],
"slip"=>$slip,
"SLIP_NAME"=>$SLIP_NAME,
"SLIP_SP"=>$SLIP_SP,
"MM"=>$MM,
"WF"=>$WF,
];
file_put_contents($file, json_encode($HAP, JSON_UNESCAPED_UNICODE), LOCK_EX);
}
setcookie("WrtAgreementKey", $WrtAgreementKey, $NOWTIME+31536000, "/");
exit('認証に成功しました。Web版をご利用の場合はそのまま投稿できます<br>2ch専用ブラウザでの投稿時やCookie失効時は以下のキーをE-mail欄に入力してご利用ください<br>※E-mail欄は外部には表示されません<input name="mcode" onfocus="this.select()" value="#'.$WrtAgreementKey.'" style="display:block;margin:auto;width:95%;" readonly=""><hr><a href="#" onclick="window.history.go(-1);">前ページに戻る</a><br><a href="#" onclick="window.history.go(-2);">2つ前のページに戻る</a>');
}else exit("認証データがありません");
}
?>
<HTML>
<HEAD>
<title>投稿前確認</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<META HTTP-EQUIV="pragma" CONTENT="no-cache">
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
<script src="/static/clientid.js"></script>
<script src="https://www.google.com/recaptcha/api.js"></script>
<script>
function onSubmit(token) {
document.getElementById('postForm').submit();
}
</script>
</HEAD><body>
<h4>法的な投稿前確認画面</h4>
<form method="POST" accept-charset="Shift_JIS" id="postForm" action=""><b><div>投稿を行うには下記に同意し、「同意する」をクリックする必要があります。</div>
<div>
・投稿者は、投稿に際して、利用する掲示板のローカルルールに同意することを承諾します。また、この投稿規定と利用する掲示板のローカルルールが相反する場合、利用する掲示板のローカルルールが優先されます。<br>
・投稿者は、全ての投稿に際し、発生する責任が投稿者に帰すことを承諾します。なお、本サービスでは利用する掲示板の削除規定に該当する場合などを除き、一度投稿したコンテンツを削除することはできません。<br>
・投稿者が本サービス上に投稿したコンテンツに関する知的財産権やその他の権利、義務については投稿者に帰属するものとします。<br>
・投稿者は、話題と無関係な広告の投稿に関して、相応の費用を支払うことを承諾します<br>
・投稿者は、掲示板運営者が本サービス上に投稿したコンテンツを自由に使用、コピー、複製、削除、処理、改変、修正、公衆送信、頒布、翻訳、表示および配信することに対し、無償かつ非独占的に使用することを許諾します。また、投稿内容を共有している掲示板の運営者が本サービス上に投稿したコンテンツを掲示板運営者が認める範囲内で削除、処理、改変、修正、公衆送信、頒布、翻訳、表示、配信などを行うことを許諾します。<br>
・投稿者は、掲示板運営者あるいはその指定する者および投稿内容を共有している掲示板の運営者に対して、掲示板運営者の指定が無い限り著作者人格権を一切行使しないことを承諾します。また、投稿者は掲示板運営者の指定が無い限り、第三者に対して、一切の権利(第三者に対して再許諾する権利を含みます)を許諾しないことを承諾します。 <br>
・投稿者は投稿時およびこの投稿前確認において、スパムや迷惑投稿の防止等を目的とし、掲示板運営者が次のデータを収集することに同意します。[発信元IPアドレス、Cookie、ユーザーエージェント、その他発信元を識別するための情報]<br>
・この投稿前確認では、スパム投稿を防止するためにreCAPTCHAを使用しています。
</div>
</b>
<div>上記に同意できない場合は前ページ等へ戻ってください。なお同意しない場合は投稿することはできません。</div>
<input type=hidden name=time value=<?php echo time(); ?>>
<input type=hidden name=HOST value=<?=$HOST?>>
<input type=hidden name=recaptcha_challenge_field>
<input type=hidden name=recaptcha_response_field>
<input type=hidden name=ClientID id=ClientID>
<button class="g-recaptcha" data-sitekey="<?=$sitekey?>" data-callback="onSubmit" error-callback="onReCaptchaError">上記全てに同意する</button>
</form>
<script>
const getclientid = clientid.load()
getclientid
.then(fp => fp.get())
.then(result => document.getElementById('ClientID').value = result.visitorId)
</script>
</body>
</HTML>
<?
exit;

56
test/backimg.html Normal file
View File

@ -0,0 +1,56 @@
<!DOCTYPE html><html lang="ja"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"><title>スレッド背景画像の設定</title><link href="/static/a.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="/static/jquery-1.11.3.min.js"></script></head><body><div id="container"><section><h1 class="section-title">スレッド背景画像の設定</h1><div class="contents"><input id="imgurl" type="text" class="form-control" name="key" placeholder="画像URL"><p class="notice mt5">背景画像に設定するURLを入力してください</p></div><div class="contents">直接画像を選択:<input id="uploadImage" type="file" name="file" size="50" onchange="upload();"><p class="notice mt5">こちらでファイルを選択すると自動的にURLが入力されます。※imgur.comにアップロードされます</p></div><div class="contents"><button onclick="setimg()" class="btn btn-primary btn-block">設定</button><br><br><button onclick="delimg()" class="btn btn-primary btn-block">削除</button><h3 id="ntxt"></h3></div></section></div>
<hr><a href="#" onclick="window.history.go(-1);">前ページに戻る</a><br><a href="#" onclick="window.history.go(-2);">2つ前のページに戻る</a><br><a href="https://rentalbbs.net/">トップページに戻る</a>
<script>
if (localStorage.getItem('backimg')) document.getElementById('imgurl').value = localStorage.getItem('backimg');
function setimg() {
localStorage.setItem('backimg', document.getElementById('imgurl').value);
document.getElementById('ntxt').innerHTML = '設定完了';
}
function delimg() {
localStorage.removeItem('backimg');
document.getElementById('ntxt').innerHTML = '削除完了';
}
function upload() {
const preview = document.querySelector('img');
const file = document.querySelector('input[type=file]').files[0];
const reader = new FileReader();
reader.addEventListener("load", () => {
base64Url = reader.result;
base64 = base64Url.replace(new RegExp('data.*base64,'), '');
imgur();
}, false);
if (file) {
reader.readAsDataURL(file);
}
/// APIに渡すときは先頭の data:~~~base64 を除外
function imgur() {
let imgurkey = '34ee59e33373302';
$.ajax({
url: 'https://api.imgur.com/3/image',
method: 'POST',
headers: {
"Authorization": 'Client-ID '+imgurkey
},
data: {
image: base64,
type: 'base64'
},
success: function(r){
imgurlink = r.data.link
document.getElementById('imgurl').value = imgurlink;
},
error: function () {
document.getElementById('ntxt').innerHTML = '画像アップロードに失敗 ページをリロードしてください';
}
});
}
}
</script>
</body></html>

1091
test/bbs-main.php Normal file

File diff suppressed because it is too large Load Diff

93
test/bbs.php Normal file
View File

@ -0,0 +1,93 @@
<?php
error_reporting(E_COMPILE_ERROR | E_RECOVERABLE_ERROR | E_ERROR | E_CORE_ERROR | E_PARSE);
ob_start();
if (function_exists('sys_getloadavg')) {
$loadavg = sys_getloadavg(); //LoadAverageを取得
if ($loadavg !== false) {
// LA200以上は拒否
if ($loadavg[0] > 200) Error2("現在高負荷のため、bbs.cgiを一時的に停止しています。お手数ですが、Web版からの投稿をお願いします。 -> LoadAverage:".$loadavg[0]);
if ($loadavg[0] > 50 && (empty($_POST['mail']) || strlen($_POST['mail']) !== 9) && (empty($_COOKIE['WrtAgreementKey']) || strlen($_COOKIE['WrtAgreementKey']) !== 8)) finish();
}
}
// 専ブラ用なのでShift_JISで出力
header('Content-Type: text/html; charset=Shift_JIS');
if (!isset($_POST['bbs'])) $_POST['bbs'] = '';
if (!isset($_POST['key'])) $_POST['key'] = '';
if (!isset($_POST['MESSAGE'])) $_POST['MESSAGE'] = '';
if (!isset($_POST['FROM'])) $_POST['name'] = '';
if (!isset($_POST['mail'])) $_POST['mail'] = '';
if (!isset($_POST['subject'])) $_POST['subject'] = '';
$PATH = "../".$_POST['bbs']."/";
$NOWTIME = time();
// 一部特殊なアプリが有るためv2ではMonazilla以外のUAも許容する。
// 投稿先の掲示板設定を取得
$setfile = $PATH."setting.json";
if (!is_file($setfile)) Error2("This board does not exist.");
$SETTING = json_decode(file_get_contents($setfile), true);
// 専ブラ投稿が許可されていない場合はここで拒否
if ($SETTING['2ch_dedicate_browsers'] != "enable") Error2("invalid:2ch dedicate browsers is forbidden.");
// 専ブラなのにtimeなし
if (!$_POST['time']) Error2("invalid");
// Shift_JISからUTF-8へ
mb_convert_variables('UTF-8','SJIS-win',$_POST);
$_POST['comment'] = $_POST['MESSAGE'];
$_POST['title'] = $_POST['subject'];
$_POST['name'] = $_POST['FROM'];
$_POST['board'] = $_POST['bbs'];
$_POST['thread'] = $_POST['key'];
require "bbs-main.php";
// 投稿完了画面
function finish() {
?><html><head><title>書きこみました。</title><meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS"></head><body>書きこみが終わりました。<br><br>画面を切り替えるまでしばらくお待ち下さい。</body></html>
<?php exit;
}
// 各種規制など(専ブラ向けに整形)
function Error($error) {
global $PATH,$HOST,$DATE,$ID,$WrtAgreementKey,$number,$CH_UA,$ACCEPT,$accountid,$LV,$info;
// エラーログに保存
if (is_file($PATH."errors.cgi")) $EROG = file($PATH."errors.cgi");
else $EROG = [];
array_unshift($EROG, $error."<>".$_POST['name']."<>".$_POST['mail']."<>".$DATE." ".$ID."<>".$_POST['comment']."<>".$_POST['title']."<>".$_POST['thread']."<>".$number."<>".$HOST."<>".$_SERVER['REMOTE_ADDR']."<>".$_SERVER['HTTP_USER_AGENT']."<>".$CH_UA."<>".$ACCEPT."<>".$WrtAgreementKey."<>".$LV."<>".$info."\n");
// 500 個以内に調整して保存
while (count($EROG) > 500) array_pop($EROG);
$EROG = array_unique($EROG);
$fp = @fopen($PATH."errors.cgi", "w");
foreach($EROG as $tmp) fputs($fp, $tmp);
fclose($fp);
?><head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
</head>
<body bgcolor="#FFFFFF">
<font size=+1 color=#FF0000><b>ERROR: <?php echo mb_convert_encoding($error, "SJIS-win", "UTF-8"); ?></b></font>
</body>
</html>
<?php exit;
}
// その他のエラー
function Error2($error) {
?><head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
</head>
<body bgcolor="#FFFFFF">
<font size=+1 color=#FF0000><b>ERROR: <?=$error?></b></font>
</body>
</html>
<?php exit;
}
function makeDir($path) {
return is_dir($path) || mkdir($path, 0777, true);
}

1
test/board/.htaccess Normal file
View File

@ -0,0 +1 @@
deny from all

75
test/board/SETTING.TXT Normal file
View File

@ -0,0 +1,75 @@
BBS_TITLE=掲示板
background=#fafafa
BBS_NONAME_NAME=名無しさん
DELETED_TEXT=にゃんぷっぷー
use_capture=checked
ip_geolocation=checked
capture_authorize=checked
use_account_lv=
auto_authorize_lv=
cookie_enable=checked
trip_enable=checked
trip_authorize=
account_enable=checked
auto_authorize=
g_auto_authorize=checked
DISABLE_ICON=
DISABLE_NAME=
DISABLE_TRIP=
FORCE_DISP_TRIP=
NAME_ARR=
Create_Authentication_required=
Create_cap_only=
Authentication_required=
cap_only=
2ch_dedicate_browsers=enable
disable_kakolog=
BBS_THREADS_LIMIT=100
LTL_LIMIT=200
MAX_RES=1000
BBS_FORCE_SAGE=
thread_supervisor=
aa_check=checked
commands=
LOG_LIMIT=
BBS_FR_SECOND=
timeinterval=
BBS_UNICODE=checked
Samba24=checked
BBS_SAMBA24=5
saidai=5
timeinterval=5
timecheck=checked
timelimit=86400
timecount=120
timeclose=40
BBS_LINE_NUMBER=20
BBS_SUBJECT_COUNT=48
BBS_NAME_COUNT=48
BBS_MAIL_COUNT=48
BBS_MESSAGE_COUNT=1000
newthread_check=checked
threadcheck=checked
threadlimit=86400
threadcount=50
timecover=20
THREAD_JUNBAN=8
JUNBAN_LIMIT=86400
THREAD_INTERVAL=3600
authorized_denypass=
BBS_FOREIGN_PASS=
BBS_BBX_PASS=
change_sakujyo=checked
NANASHI_CHECK=
BBS_PROXY_CHECK=checked
JAPANESE_CHECK=checked
NOPIC=
DISABLE_LINK=
id=checked
ID_RESET=day
disp_accountid=
disp_slipname=
slip=
fusianasan=
createid=checked
BBS_JP_CHECK=

0
test/board/authorize.cgi Normal file
View File

0
test/board/cap.cgi Normal file
View File

View File

0
test/board/deny_area.cgi Normal file
View File

0
test/board/deny_host.cgi Normal file
View File

0
test/board/deny_ip.cgi Normal file
View File

0
test/board/deny_ua.cgi Normal file
View File

0
test/board/head.txt Normal file
View File

26
test/board/index.html Normal file
View File

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
<meta name="application-name" content="delight">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<link rel="apple-touch-icon" href="../icon.png">
<link rel="icon" href="../favicon.ico">
<meta name="referrer" content="origin">
<title><BBS></title>
</head>
<body>
<table width="95%" cellspacing="7" cellpadding="3" border="1" bgcolor="#CCFFCC" align="center"><tbody><tr><td align="center">
<table width="100%" cellpadding="1" border="0">
<tbody><tr>
<td><font size="+1"><b><BBS></b></font></td>
<td width="5%" valign="top" nowrap="" align="right"><a href="#menu"></a> <a href="#t-1"></a></td>
</tr>
<tr><td colspan="3"><noscript><p>JavaScriptを有効にしてください<br>Please turn on your JavaScript</p></noscript></td></tr>
</tbody>
</table>
</body>
<script type="text/javascript" src="/static/index.js"></script>
</html>

0
test/board/kokuti.txt Normal file
View File

View File

View File

View File

View File

View File

1
test/board/setting.json Normal file
View File

@ -0,0 +1 @@
{"BBS_TITLE":"掲示板","background":"#fafafa","BBS_NONAME_NAME":"名無しさん","DELETED_TEXT":"にゃんぷっぷー","use_capture":"checked","capture_authorize":"checked","ip_geolocation":"checked","use_account_lv":"","auto_authorize_lv":"","cookie_enable":"checked","trip_enable":"checked","trip_authorize":"","account_enable":"checked","auto_authorize":"","g_auto_authorize":"checked","DISABLE_ICON":"","DISABLE_NAME":"","DISABLE_TRIP":"","FORCE_DISP_TRIP":"","NAME_ARR":"","Create_Authentication_required":"","Create_cap_only":"","Authentication_required":"","cap_only":"","2ch_dedicate_browsers":"enable","disable_kakolog":"","BBS_THREADS_LIMIT":"100","LTL_LIMIT":"200","MAX_RES":"1000","BBS_FORCE_SAGE":"","thread_supervisor":"","aa_check":"checked","commands":"","LOG_LIMIT":"","BBS_FR_SECOND":"","timeinterval":"5","BBS_UNICODE":"checked","Samba24":"checked","BBS_SAMBA24":"5","saidai":"5","timecheck":"checked","timelimit":"86400","timecount":"100","timeclose":"20","BBS_LINE_NUMBER":"20","BBS_SUBJECT_COUNT":"48","BBS_NAME_COUNT":"48","BBS_MAIL_COUNT":"48","BBS_MESSAGE_COUNT":"1000","newthread_check":"checked","threadcheck":"checked","threadlimit":"86400","threadcount":"50","timecover":"20","THREAD_JUNBAN":"8","JUNBAN_LIMIT":"86400","THREAD_INTERVAL":"3600","authorized_denypass":"","BBS_FOREIGN_PASS":"","BBS_BBX_PASS":"","change_sakujyo":"checked","NANASHI_CHECK":"","BBS_PROXY_CHECK":"checked","JAPANESE_CHECK":"checked","NOPIC":"","DISABLE_LINK":"","id":"checked","ID_RESET":"day","disp_accountid":"","disp_slipname":"","slip":"","fusianasan":"","createid":"checked","BBS_JP_CHECK":""}

1
test/board/subject.txt Normal file
View File

@ -0,0 +1 @@
1000000000.dat<>TL (1)

View File

@ -0,0 +1,3 @@
<FilesMatch "\.dat$">
Header set Content-Type 'text/plain; charset=utf-8'
</FilesMatch>

44
test/create.php Normal file
View File

@ -0,0 +1,44 @@
<?php
error_reporting(E_COMPILE_ERROR | E_RECOVERABLE_ERROR | E_ERROR | E_CORE_ERROR | E_PARSE);
header('Content-Type: text/html; charset=UTF-8');
$file = "createcode.cgi";
$code = @file_get_contents($file);
?><!DOCTYPE HTML>
<html lang="ja">
<head>
<meta charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>新規掲示板作成</title>
<link href="/static/a.css" rel="stylesheet" type="text/css">
</head>
<body>
<div id="container">
<section>
<h1 class="section-title">新規掲示板作成</h1>
<form class="form-basic" method="POST" accept-charset="UTF-8" action="kanri2.php">
<h2 class="section-subtitle">ディレクトリ名</h2>
<div class="contents">
<input type="text" class="form-control" id="registerMailAddressCheck" name="directory">
<p class="notice mt5">掲示板のディレクトリ名(フォルダ名)を16文字以下半角英数小文字で記入してください。</p>
</div>
<h2 class="section-subtitle">管理パスワード</h2>
<div class="contents">
<input type="text" class="form-control" id="password" name="password">
<p class="notice mt5">掲示板の管理画面で使用するパスワードを入力してください。</p>
</div>
<?php if (strlen($code) > 0) { ?>
<h2 class="section-subtitle">作成コード</h2>
<div class="contents">
<input type="text" class="form-control" id="code" name="code">
<p class="notice mt5 mt20">掲示板を作成するためには作成コードを記入する必要があります</p>
</div>
<?php } ?>
<div class="contents">
<button type="submit" class="btn btn-primary btn-block">新規掲示板作成</button>
<p class="notice mt5 mt20">詳細な設定は掲示板作成後、管理メニューから行えます。</p>
</div>
</form>
</section>
</div>
</body>
</html>

0
test/createcode.cgi Normal file
View File

186
test/createthread.php Normal file
View File

@ -0,0 +1,186 @@
<?php
error_reporting(E_COMPILE_ERROR | E_RECOVERABLE_ERROR | E_ERROR | E_CORE_ERROR | E_PARSE);
$msg = $subject = '';
if (!$_GET['bbs']) exit;
if ($_GET['key']) {
$thread_file = "../".$_GET['bbs']."/thread/".substr($_GET['key'], 0, 4)."/".$_GET['key'].".dat";
if (is_file($thread_file)) {
$LOG = file($thread_file);
list(,,,$msg,$subject) = explode("<>",$LOG[0]);
$msg = str_replace("<br>", "\n", $msg);
$msg = strip_tags($msg, ['details', 'summary']);
$msg .= "\n\n前スレ\n".$subject."https://".$_SERVER['HTTP_HOST']."/#".$_GET['bbs']."/".$_GET['key']."/";
}
}
// 次スレ作成処理
?><!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
<meta name="application-name" content="delight">
<meta name="referrer" content="origin">
<title>新規スレッド作成</title>
<link href="/static/st.css" rel="stylesheet" type="text/css"><link href="/static/milligram.css" rel="stylesheet" type="text/css"><link href="/static/s.css" rel="stylesheet" type="text/css"><link href="/static/read.css" rel="stylesheet" type="text/css"></head>
</head>
<body>
<div id="followheader" class="hidden maxwidth100 height2p5 stickymenu container" style="display: block;"><div class="row noflex maxwidth100 white padding0p5 maxheight2p5 borderbottomlightgrey"><div class="topmenu" id="header"><a class="menuitem" href="/<?=$_GET['bbs']?>/">TL</a><a class="menuitem" href="/<?=$_GET['bbs']?>/?m=subback">スレ一覧</a><a class="menuitem" href="/<?=$_GET['bbs']?>/?m=subback&mode=history">履歴</a><a class="menuitem" href="/<?=$_GET['bbs']?>/?m=subback&mode=unread">未読</a><b class="menuitem">スレ作成</b><div id="headtitle" class="menuitem" style="text-decoration: none;"></div></div></div></div>
<div id="subbacktitle"></div>
<div style="min-height:50px;margin-top: 3rem;" id="rule"> ローカルルール<br></div>
<div style="min-height:50px" id="kokuti"> 告知欄<br></div>
<div class="formbox" style="margin-top: 4rem;"><form method="POST" id="Form" accept-charset="UTF-8" action="/test/post-v2.php" style="display: block;margin-top: 2rem;"> <span class="fhead" style="border-radius: 3px 3px 0 0;color: #666;padding: 3px;text-align: left;"><span class="spformhead" style="display:inline !important;border-radius:3px 3px 0 0;color:#666;padding:3px;"><a id="iconlink" target="_blank" href="<?=$_COOKIE['homepage']?>"><img id="icon" class="icon" src="<?=$_COOKIE['icon']?>" width="50" height="50" align="left"></a><input name="name" placeholder="名前" class="formelem maxwidth" style="width:50%;margin-top:.5rem;"></span><span class="submitbtn" style="color: #000;float: right;font-size: 28px;font-weight: bold;cursor: pointer;display: inline-block;padding-right: 5px;"><input type="submit" value="新規投稿" name="submit" onclick="Post()"></span></span><input name="mail" size="19" value="" placeholder="E-mail" class="formelem maxwidth"><div class="backmsg" style="display: inline-block;"><input value="on" type="checkbox" id="seticon" name="icon" checked="" <?php if (!$_COOKIE['icon']) echo 'style="display:none"'; ?>><a href="/test/icon.html">アイコン</a> <a href="javascript:BackMSG()">下書きを復元</a></div><textarea rows="5" cols="70" name="comment" id="bbs-textarea" onchange="MSG()" class="formelem maxwidth" wrap="off"><?=$msg?></textarea><input name="title" size="19" value="<?=$subject?>" placeholder="スレッドタイトル" class="formelem maxwidth"><br>画像:<input id="uploadImage" type="file" name="file" size="50" onchange="upload();"><br><input type="hidden" name="board" value="<?=$_GET['bbs']?>"></form></div>
<div class="tlnotice" id="ntxt"></div>
<p style="margin:5rem 0;color:#333">We're sure you'll have a good time with delight and/or 3ch. :)</p>
<style>div.postbutton{display: none !important;}</style>
<script src="/static/textarea.js"></script>
<script src="/static/jquery-1.11.3.min.js"></script>
<script>
if (localStorage.getItem('css') === null) localStorage.setItem('css', '');
document.body.innerHTML += "<style>"+localStorage.getItem('css')+"</style>";
function isSmartPhone() {
let v = false;
if (navigator.userAgent.match(/iPhone|Android.+Mobile/)) {
v = true;
} else {
v = false;
}
if (localStorage.getItem('viewer') == 'sp') v = true;
else if (localStorage.getItem('viewer') == 'pc') v = false;
if (location.search.indexOf('v=sp') != -1) v = true;
if (location.search.indexOf('v=pc') != -1) v = false;
return v;
}
if (isSmartPhone() == true) document.body.innerHTML += '<link href="/static/sp.css" rel="stylesheet">';
if (localStorage.getItem('darkmode') == "true" || (localStorage.getItem('autodark') == "true" && window.matchMedia('(prefers-color-scheme: dark)').matches === true)) {
document.body.innerHTML += '<link href="/static/dark.css" rel="stylesheet"><style>#header{color:#333}</style>';
}
let imgurkey = '';
if (localStorage.getItem('text2') === null) localStorage.setItem('text2', '');
let bbs = "<?=$_GET['bbs']?>";
setfile = '/'+bbs+'/setting.json';
rulefile = '/'+bbs+'/head.txt';
kokutifile = '/'+bbs+'/kokuti.txt';
if (document.getElementById('headtitle')) {
const sroad = new XMLHttpRequest();
sroad.open('get', setfile);
sroad.send();
sroad.onreadystatechange = function() {
if(sroad.readyState === 4 && sroad.status === 200) {
const setting = JSON.parse(this.responseText);
if (setting['BBS_TITLE']) {
document.getElementById('headtitle').innerHTML = setting['BBS_TITLE'];
document.getElementById('subbacktitle').innerHTML = setting['BBS_TITLE'];
}
}
}
}
if (document.getElementById('rule')) {
const lroad = new XMLHttpRequest();
lroad.open('get', rulefile);
lroad.send();
lroad.onreadystatechange = function() {
if(lroad.readyState === 4 && lroad.status === 200) {
document.getElementById('rule').innerHTML += this.responseText;
}
}
}
if (document.getElementById('kokuti')) {
const kroad = new XMLHttpRequest();
kroad.open('get', kokutifile);
kroad.send();
kroad.onreadystatechange = function() {
if(kroad.readyState === 4 && kroad.status === 200) {
document.getElementById('kokuti').innerHTML += this.responseText;
}
}
}
function l(e){
var N=getCookie("NAME"),M=getCookie("MAIL"),i;
with(document) for(i=0;i<forms.length;i++)if(forms[i].name&&forms[i].mail)with(forms[i]){
name.value=N;
mail.value=M;
}
}
onload=l;
function getCookie(key, tmp1, tmp2, xx1, xx2, xx3) {
tmp1 = " " + document.cookie + ";";
while(tmp1.match(/\+/)) {tmp1 = tmp1.replace("+", " ");};
xx1 = xx2 = 0;
len = tmp1.length;
while (xx1 < len) {
xx2 = tmp1.indexOf(";", xx1);
tmp2 = tmp1.substring(xx1 + 1, xx2);
xx3 = tmp2.indexOf("=");
if (tmp2.substring(0, xx3) == key) {return(unescape(tmp2.substring(xx3 + 1, xx2 - xx1 - 1)));}
xx1 = xx2 + 1;
}
return("");
}
if (!getCookie("WrtAgreementKey")) document.getElementById('Form').innerHTML = '<div><a href="/test/auth.php">投稿時に使用する同意鍵がありません。<br>投稿を行うには投稿前確認画面での同意が必要です。</a></div>'+document.getElementById('Form').innerHTML;
function upload() {
const preview = document.querySelector('img');
const file = document.querySelector('input[type=file]').files[0];
const reader = new FileReader();
reader.addEventListener("load", () => {
base64Url = reader.result;
base64 = base64Url.replace(new RegExp('data.*base64,'), '');
imgur();
}, false);
if (file) {
reader.readAsDataURL(file);
}
/// APIに渡すときは先頭の data:~~~base64 を除外
function imgur() {
document.getElementById('ntxt').innerHTML = '通信中';
$.ajax({
url: 'https://api.imgur.com/3/image',
method: 'POST',
headers: {
"Authorization": 'Client-ID '+imgurkey
},
data: {
image: base64,
type: 'base64'
},
success: function(r){
imgurlink = r.data.link
document.getElementById('bbs-textarea').value += '\n'+imgurlink;
document.getElementById('ntxt').innerHTML = '画像をアップロードしました';
},
error: function () {
document.getElementById('ntxt').innerHTML = 'アップロードできません';
}
});
}
}
function Post() {
let cookname = escape(document.getElementsByName("name")[0].value);
document.cookie = "NAME="+cookname+"; Max-Age=7776000; path=/";
let cookmail = escape(document.getElementsByName("mail")[0].value);
document.cookie = "MAIL="+cookmail+"; Max-Age=7776000; path=/";
}
function MSG() {
if (document.getElementById('bbs-textarea').value) {
sessionStorage.setItem('text', document.getElementById('bbs-textarea').value);
localStorage.setItem('text2', document.getElementById('bbs-textarea').value);
}
}
function BackMSG() {
document.getElementById('bbs-textarea').value = localStorage.getItem('text2');
}
</script>
</body>
</html>

15
test/css.html Normal file
View File

@ -0,0 +1,15 @@
<!DOCTYPE html><html lang="ja"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"><title>カスタムcssの設定</title><link href="/static/a.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="/static/jquery-1.11.3.min.js"></script></head><body><div id="container"><section><h1 class="section-title">カスタムcssの設定</h1><div class="contents"><input id="css" type="text" class="form-control" name="css" placeholder="カスタムcss"></div><div class="contents"><button onclick="setcss()" class="btn btn-primary btn-block">設定</button><br><br><button onclick="delcss()" class="btn btn-primary btn-block">削除</button><h3 id="ntxt"></h3></div></section></div>
<hr><a href="#" onclick="window.history.go(-1);">前ページに戻る</a><br><a href="#" onclick="window.history.go(-2);">2つ前のページに戻る</a><br><a href="https://rentalbbs.net/">トップページに戻る</a>
<script>
if (localStorage.getItem('css')) document.getElementById('css').value = localStorage.getItem('css');
function setcss() {
localStorage.setItem('css', document.getElementById('css').value);
document.getElementById('ntxt').innerHTML = '設定完了';
}
function delcss() {
localStorage.removeItem('css');
document.getElementById('ntxt').innerHTML = '削除完了';
}
</script>
</body></html>

121
test/delete.php Normal file
View File

@ -0,0 +1,121 @@
<?php
error_reporting(E_COMPILE_ERROR | E_RECOVERABLE_ERROR | E_ERROR | E_CORE_ERROR | E_PARSE);
header('Content-Type: text/html; charset=UTF-8');
$cap = false;
if (!isset($_REQUEST['bbs'])) $_REQUEST['bbs'] = '';
if (!isset($_REQUEST['mode'])) $_REQUEST['mode'] = '';
if (!isset($_REQUEST['key'])) $_REQUEST['key'] = '';
$PATH = "../".$_REQUEST['bbs']."/";
$passfile = $PATH."passfile.cgi";
$admin = @file_get_contents($passfile);
if (!isset($_POST['password'])) $_POST['password'] = '';
if (password_verify($_POST['password'], $admin)) $cap = true;
if (!$cap) {
if (is_file($PATH."cap.cgi")) {
$cap_str = file($PATH."cap.cgi");
foreach ($cap_str as $tmp){
$tmp = trim($tmp);
if (!$tmp || strpos(substr($tmp, 0, 1), '#') !== false || strpos($tmp, '<>') === false) continue;
list($name1,$pass1,$a1) = explode("<>", $tmp);
if (($_POST['password'] == $pass1) && ($a1 == "saku" or $a1 == "sakud")) {
$cap = true;
$password = $pass1;
if ($a1 == "sakud") $sakud = 1;
break;
}
}
}
}
if ($_POST['password'] && !$cap) $E = 'パスワードが無効です';
else $E = '';
if (!$_REQUEST['bbs'] || !$cap) {
?><!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content>
<meta name="author" content>
<title>削除ページ</title>
<link rel="stylesheet" href="/static/a.css">
</head>
<body>
<form class="form-signin" method="post" action="?bbs=<?=$_REQUEST['bbs']?>&mode=<?=$_REQUEST['mode']?>&key=<?=$_REQUEST['key']?>">
<h1 class="font-weight-normal mb-3">ログイン</h1>
<b><?=$E?></b>
<input name="bbs" class="form-control" placeholder="ディレクトリ名" value="<?=$_REQUEST['bbs']?>" required="">
<input type="password" name="password" class="form-control" placeholder="パスワード" value="<?=$_POST['password']?>" required="">
<p class="mb-3"></p>
<input name="login_be_normal_user" class="btn btn-primary btn-block" type="submit" value="ログイン">
</form>
</body>
</html>
<?php
exit;
}
// 設定ファイルを読む
$setfile = $PATH."setting.json";
$settxt = $PATH."SETTING.TXT";
$SET = '';
if (is_file($setfile)) {
$SETTING = json_decode(file_get_contents($setfile), true);
}else Finish('<b>設定ファイルがありません</b><div class="back"><a href="'.$_SERVER['HTTP_REFERER'].'">← 戻る</a></div>');
// 設定一覧
if (!$_GET['mode']) {
?><!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content>
<meta name="author" content>
<title>管理ページ</title>
<link rel="stylesheet" href="/static/a.css">
</head>
<body>
<div id="lists">
<div class="list"><form method="post" action="?bbs=<?=$_REQUEST['bbs']?>&mode=authorization"><button class="link-style-btn">承認済ユーザ</button><input type="hidden" name="password" value="<?=$_REQUEST['password']?>"></form></div>
<div class="list"><form method="post" action="?bbs=<?=$_REQUEST['bbs']?>&mode=log"><button class="link-style-btn">投稿ログ閲覧</button><input type="hidden" name="password" value="<?=$_REQUEST['password']?>"></form></div>
<div class="list"><form method="post" action="?bbs=<?=$_REQUEST['bbs']?>&mode=control"><button class="link-style-btn">スレッド・レス管理</button><input type="hidden" name="password" value="<?=$_REQUEST['password']?>"></form></div>
<div class="list"><form method="post" action="?bbs=<?=$_REQUEST['bbs']?>&mode=tl"><button class="link-style-btn">タイムライン管理</button><input type="hidden" name="password" value="<?=$_REQUEST['password']?>"></form></div>
<div class="list"><form method="post" action="?bbs=<?=$_REQUEST['bbs']?>&mode=kisei"><button class="link-style-btn">規制設定</button><input type="hidden" name="password" value="<?=$_REQUEST['password']?>"></form></div>
<div class="list"><form method="post" action="?bbs=<?=$_REQUEST['bbs']?>&mode=kisei2"><button class="link-style-btn">投稿規制</button><input type="hidden" name="password" value="<?=$_REQUEST['password']?>"></form></div>
<div class="list"><form method="post" action="?bbs=<?=$_REQUEST['bbs']?>&mode=kisei3"><button class="link-style-btn">スレッド作成規制</button><input type="hidden" name="password" value="<?=$_REQUEST['password']?>"></form></div>
<div class="list"><form method="post" action="?bbs=<?=$_REQUEST['bbs']?>&mode=error"><button class="link-style-btn">エラーログ</button><input type="hidden" name="password" value="<?=$_REQUEST['password']?>"></form></div>
</div>
</body>
</html>
<?php exit;
}elseif ($_GET['mode'] == "authorization") {
require './operate/authorization.php';
}elseif ($_GET['mode'] == "log") {
require './operate/log.php';
}elseif ($_GET['mode'] == "control") {
require './operate/control.php';
}elseif ($_GET['mode'] == "tl") {
require './operate/tl.php';
}elseif ($_GET['mode'] == "error") {
require './operate/error.php';
}elseif ($_GET['mode'] == "kisei") {
require './operate/kisei.php';
}elseif ($_GET['mode'] == "kisei2") {
require './operate/kisei2.php';
}elseif ($_GET['mode'] == "kisei3") {
require './operate/kisei3.php';
}
function Finish($value) {
?><!DOCTYPE HTML>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link href="/static/a.css" rel="stylesheet" type="text/css">
</head>
<body>
<?=$value?>
</body>
</html>
<?php }

1
test/extend/.htaccess Normal file
View File

@ -0,0 +1 @@
Deny from all

61
test/extend/commands.php Normal file
View File

@ -0,0 +1,61 @@
<?php
if ($SETTING['commands'] == "checked") {
if (strpos($message, '!sage') !== false) $sage = true;
if (strpos($message, '!nopic') !== false) $SETTING['NOPIC'] = "checked";
if (strpos($message, '!noid') !== false) {
$SETTING['id'] = "";
$SETTING['slip'] = "";
$SETTING['disp_slipname'] = "";
$SETTING['BBS_JP_CHECK'] = "";
}
if (strpos($message, '!jien') !== false) {
$SETTING['id'] = "checked";
$SETTING['slip'] = "checked";
$SETTING['disp_slipname'] = "checked";
$SETTING['BBS_JP_CHECK'] = "checked";
$SETTING['ID_RESET'] = "year";
}
if (strpos($message, '!live') !== false) {
$SETTING['threadcheck'] = "";
$SETTING['timecheck'] = "";
if ($SETTING['BBS_SAMBA24'] > 0) $SETTING['BBS_SAMBA24'] = $SETTING['BBS_SAMBA24'] / 2;
}
if (strpos($message, '!slip') !== false) $SETTING['slip'] = "checked";
if (strpos($message, '!slipname') !== false) $SETTING['disp_slipname'] = "checked";
if (strpos($message, '!ken') !== false) $SETTING['BBS_JP_CHECK'] = "checked";
if (strpos($message, '!id') !== false) $SETTING['id'] = "checked";
if (strpos($message, '!siberia') !== false) $SETTING['id'] = "siberia";
if (strpos($message, '!day') !== false) $SETTING['ID_RESET'] = "day";
if (strpos($message, '!month') !== false) $SETTING['ID_RESET'] = "month";
if (strpos($message, '!year') !== false) $SETTING['ID_RESET'] = "year";
if (strpos($message, '!host') !== false) $SETTING['fusianasan'] = "name";
if (strpos($message, '!clientid') !== false) $SETTING['fusianasan'] = "id";
if (strpos($message, '!nolink') !== false) $SETTING['DISABLE_LINK'] = "checked";
if (strpos($message, '!idchange') !== false) $SETTING['BBS_ID_CHANGE'] = "checked";
if (strpos($message, '!cap') !== false) $SETTING['cap_only'] = "checked";
if (strpos($message, '!auth') !== false) $SETTING['Authentication_required'] = "checked";
if (strpos($message, '!NO') !== false) $SETTING['disable_supervisor'] = "checked";
if (strpos($message, '!AA') !== false) $SETTING['BBS_AA'] = "checked";
if (strpos($message, '!ARR') !== false) $SETTING['NAME_ARR'] = "checked";
if (strpos($message, '!stop') !== false && $number != 1) Error("このスレッドは停止しました");
// !SETTING
if (preg_match_all("/!SETTING:(.*?):(.*?)(\s| |<br>)/", $_POST['comment'], $SETS, PREG_SET_ORDER)) {
foreach ($SETS as $SET) {
$SETTING[$SET[1]] = $SET[2];
}
}
if ($supervisor || $admin) {
if (strpos($_POST['comment'], "!") !== false) $reload = true;
if (strpos($_POST['comment'], '!stop') !== false) $stop = true;
// 追記
if (preg_match("/!add(.*)/", $_POST['comment'], $match) && $number != 1) {
$message .="<br><font class=\"add\" color=\"red\">※追記 {$DATE}</font>{$match[1]}";
}
// 部分削除
if (preg_match_all("/!saku:(.*?)(\s| |<br>)/", $_POST['comment'], $sakus, PREG_SET_ORDER)) {
foreach ($sakus as $sakujyo) {
$message = str_replace($sakujyo[1],'',$message);
}
}
}
}

View File

@ -0,0 +1,83 @@
<?php
$options =array(
'http' =>array(
'method' => "GET",
)
);
$url = "http://ip-api.com/json/".$_SERVER['REMOTE_ADDR']."?fields=countryCode,regionName,city,asname,mobile,proxy,hosting&lang=ja";
$cp = curl_init();
/*オプション:リダイレクトされたらリダイレクト先のページを取得する*/
curl_setopt($cp, CURLOPT_RETURNTRANSFER, 1);
/*オプション:URLを指定する*/
curl_setopt($cp, CURLOPT_URL, $url);
/*オプション:タイムアウト時間を指定する*/
curl_setopt($cp, CURLOPT_TIMEOUT, 2000);
/*オプション:ユーザーエージェントを指定する*/
curl_setopt($cp, CURLOPT_USERAGENT, "Mozilla/5.0 P2/2.5 (iPad; CPU OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/87.0.4280.77 Mobile/15E148 Safari/604.1");
curl_setopt($cp, CURLOPT_HEADER, true);
$source = curl_exec($cp);
$curlInfo = curl_getinfo($cp);
// ヘッダを一緒に出力したときは分割させる
$headerSize = false;
if ( isset($curlInfo["header_size"]) && $curlInfo["header_size"]!="" ) {
$headerSize = $curlInfo["header_size"];
}
$head = substr($source, 0, $headerSize); // ヘッダ部
$head = str_replace(["\r\n", "\r", "\n"], "\n", $head);
$header = explode("\n", $head);
foreach ($header as $tmp) {
list($key, $value) = explode(": ", $tmp);
$HTTP[$key] = $value;
}
$data = substr($source, $headerSize); // ボディ部
curl_close($cp);
$area = json_decode($data, true);
if (!$area["asname"]) $area["asname"] = preg_replace("/[0-9]/", "", $HOST);
// 国名取得(CFを通さないサーバの場合)
if (empty($_SERVER['HTTP_CF_IPCOUNTRY'])) {
if ($area["countryCode"]) $_SERVER['HTTP_CF_IPCOUNTRY'] = $area["countryCode"];
else $_SERVER['HTTP_CF_IPCOUNTRY'] = "JP";
}
// モバイルを検出
if ($area['mobile'] == true && $slip == "0" && strpos($HOST, 'bbtec.net') === false && strpos($HOST, 'ocn.ne.jp') === false && strpos($HOST, 'dion.ne.jp') === false) {
$slip = "S";
$SLIP_SP = true;
$SLIP_NAME = $area["asname"];
}
// 県名
if (!$area["regionName"]) $area["regionName"] = "catv?";
if ($SETTING['BBS_JP_CHECK'] == 1) $ken = $area["regionName"];
elseif ($SETTING['BBS_JP_CHECK'] == 2) $ken = $area["city"];
elseif ($SETTING['BBS_JP_CHECK'] == 3) $ken = $area["regionName"].$area["city"];
elseif ($SETTING['BBS_JP_CHECK'] == 4) $ken = $area["asname"];
elseif ($SETTING['BBS_JP_CHECK'] == 5) $ken = $area["regionName"]." ".$area["asname"];
elseif ($SETTING['BBS_JP_CHECK'] == 6) $ken = $area["regionName"].$area["city"]." ".$area["asname"];
if ($area["city"] == "Chiyoda") {
if ($slip == "d") $ken = "";
elseif ($slip != "0") $ken = "";
elseif ($area["asname"] == "KDDI" || strpos($HOST, 'dion.ne.jp') !== false) $ken = "dion軍";
}
if ($area["city"] == "東京" || $area["city"] == "大阪市") {
if ($slip == "d") $ken = "";
elseif ($slip == "M") $ken = "ジパング";
elseif ($slip != "0") $ken = "";
elseif ($area["asname"] == "KDDI" || strpos($HOST, 'dion.ne.jp') !== false) $ken = "dion軍";
}
if ($area["city"] == "港区") {
if ($slip == "p") $ken = "SB-iPhone";
elseif ($slip == "r") $ken = "SB-Android";
elseif ($area["asname"] == "GIGAINFRA" || strpos($HOST, 'bbtec.net') !== false) $ken = "やわらか銀行";
}
$ken = trim($ken);
// PROXYを検出
if ($area['proxy'] == true) {
if ($SETTING['BBS_BBX_PASS'] != "on" && !$authorized) Error("未承認ユーザーはVPN・PROXYから投稿することはできません");
$slip = "8";
}
// hostingを検出
if ($area['hosting'] == true && $slip != "8") {
if ($SETTING['BBS_BBX_PASS'] != "on" && !$authorized) Error("未承認ユーザーはhostingから投稿することはできません");
$slip = "h";
}
$provider = $area["regionName"].$area["asname"].$area['mobile'];

View File

@ -0,0 +1,190 @@
<?php
// smart phone marks
if (strpos($HOST, 'spmode') !== false) {
if (strpos($HOST, 'msb') !== false) $SLIP_NAME = "スプッッ";
elseif (strpos($HOST, 'msc') !== false) $SLIP_NAME = "スップ";
elseif (strpos($HOST, 'msd') !== false) $SLIP_NAME = "スッップ";
elseif (strpos($HOST, 'mse') !== false) $SLIP_NAME = "スププ";
elseif (strpos($HOST, 'msf') !== false) $SLIP_NAME = "スフッ";
else $SLIP_NAME = "スプー";
$SLIP_SP = true;
}elseif (strpos($HOST, 'au-net') !== false) {
if (strpos($HOST, 'KD027') !== false || strpos($HOST, 'kd027') !== false) $SLIP_NAME = "アウアウアー";
elseif (strpos($HOST, 'KD036') !== false || strpos($HOST, 'kd036') !== false) $SLIP_NAME = "アウアウイー"; elseif (strpos($HOST, 'KD106') !== false || strpos($HOST, 'kd106') !== false) $SLIP_NAME = "アウアウウー";
elseif (strpos($HOST, 'KD111') !== false || strpos($HOST, 'kd111') !== false) $SLIP_NAME = "アウアウエー";
elseif (strpos($HOST, 'KD119') !== false || strpos($HOST, 'kd119') !== false) $SLIP_NAME = "アウアウオー";
elseif (strpos($HOST, 'KD182249') !== false || strpos($HOST, 'kd182249') !== false || strpos($HOST, 'KD182250') !== false || strpos($HOST, 'kd182250') !== false || strpos($HOST, 'KD1822512') !== false || strpos($HOST, 'kd1822512') !== false) $SLIP_NAME = "アウアウカー";
elseif (strpos($HOST, 'KD182251') !== false || strpos($HOST, 'kd182251') !== false) $SLIP_NAME = "アウアウキー";
elseif (strpos($HOST, 'UQ') !== false || strpos($HOST, 'uq') !== false) {
$SLIP_NAME = "アウアウクー";
$MM = true;
}
else $SLIP_NAME = "アウアウ";
$SLIP_SP = true;
}elseif (strpos($HOST, 'openmobile') !== false) {
$SLIP_NAME = "オッペケ";
$SLIP_SP = true;
}elseif (strpos($HOST, 'panda-world') !== false) {
if (strpos($HOST, 'tss') !== false || strpos($HOST, 'pw126152') !== false || strpos($HOST, 'pw126161') !== false || strpos($HOST, 'pw126186') !== false || strpos($HOST, 'pw126199') !== false) $SLIP_NAME = "ササクッテロラ";
elseif (strpos($HOST, 'kyb') !== false || strpos($HOST, 'pw126205') !== false || strpos($HOST, 'pw126214') !== false || strpos($HOST, 'pw126225') !== false) $SLIP_NAME = "ササクッテロリ";
elseif (strpos($HOST, 'pw126236') !== false || strpos($HOST, 'pw126237') !== false) $SLIP_NAME = "ササクッテロル";
elseif (strpos($HOST, 'pw126245') !== false || strpos($HOST, 'pw126247') !== false) $SLIP_NAME = "ササクッテロレ";
elseif (strpos($HOST, 'pw126253') !== false || strpos($HOST, 'pw126254') !== false || strpos($HOST, 'pw126255') !== false) $SLIP_NAME = "ササクッテロロ";
else $SLIP_NAME = "ササクッテロ";
$SLIP_SP = true;
}elseif (strpos($HOST, 'access-internet') !== false) {
$SLIP_NAME = "ア-クセ-";
$SLIP_SP = true;
}elseif (strpos($HOST, 'e-mobile') !== false) {
$SLIP_NAME = "エ-イモ";
$SLIP_SP = true;
}elseif (strpos($HOST, 'emobile') !== false) {
$SLIP_NAME = "イモ";
$SLIP_SP = true;
}elseif (strpos($HOST, 'air.mopera.net') !== false) {
$SLIP_NAME = "エアペラ";
$SLIP_SP = true;
}elseif (strpos($HOST, 'mopera') !== false) {
$SLIP_NAME = "ペラペラ";
$SLIP_SP = true;
}elseif (strpos($HOST, 'google-proxy') !== false) {
$SLIP_NAME = "ググレカス";
$SLIP_SP = true;
}elseif (strpos($HOST, 'wi-fi.wi2') !== false) {
$SLIP_NAME = "ワイーワ2";
$WF = true;
}elseif (strpos($HOST, 'wi-fi.kddi') !== false) {
$SLIP_NAME = "アウウィフ";
$WF = true;
}elseif (strpos($HOST, 'm-zone') !== false) {
$SLIP_NAME = "エムゾネ";
$WF = true;
}elseif (strpos($HOST, 'wi-fi.fc2') !== false) {
$SLIP_NAME = "エフシーツー";
$WF = true;
}elseif (strpos($HOST, 'wi2.co.jp') !== false || strpos($HOST, 'wi2.ne.jp') !== false) {
$SLIP_NAME = "ワイワイ";
$WF = true;
}elseif (strpos($HOST, 'freespot.com') !== false) {
$SLIP_NAME = "フリスポ";
$WF = true;
}elseif (strpos($HOST, '7spot') !== false) {
$SLIP_NAME = "セブン";
$WF = true;
}elseif (strpos($HOST, 'family-wifi') !== false) {
$SLIP_NAME = "ファミマ";
$WF = true;
}elseif (strpos($HOST, 'freemobile.jp') !== false) {
$SLIP_NAME = "フリモバ";
$WF = true;
}elseif (strpos($HOST, 'ntt-bp.net') !== false) {
$SLIP_NAME = "ミカカウィフィ";
$WF = true;
}elseif (strpos($HOST, 'wi-fi') !== false) {
$SLIP_NAME = "ワイーワ";
$WF = true;
}elseif (strpos($HOST, 'vmobile') !== false) {
$SLIP_NAME = "ブーイモ";
$MM = true;
}elseif (strpos($HOST, 'mp') !== false && strpos($HOST, 'ap.nuro.jp') !== false) {
$SLIP_NAME = "ソネット"; // So-net モバイル LTE
$MM = true;
}elseif (strpos($HOST, 'wimax') !== false || strpos($HOST, 'wmaxuq') !== false) {
$SLIP_NAME = "ワイモマー";
$MM = true;
}elseif (strpos($HOST, 'wi-gate.net') !== false) {
$SLIP_NAME = "ワキゲー";
$MM = true;
}elseif (strpos($HOST, 'kualnet.jp') !== false) {
$SLIP_NAME = "ワイエディ";
$MM = true;
}elseif (strpos($HOST, 'omed01.tokyo') !== false) {
$SLIP_NAME = "ワントンキン";
$MM = true;
}elseif (strpos($HOST, 'omed01.osaka') !== false) {
$SLIP_NAME = "バッミングク";
$MM = true;
}elseif (strpos($HOST, 'mineo') !== false) {
$SLIP_NAME = "オイコラミネオ";
$MM = true;
}elseif (strpos($HOST, 'neoau1') !== false) {
$SLIP_NAME = "ドナドナー";
$MM = true;
}elseif (strpos($HOST, 'dcm2') !== false) {
$SLIP_NAME = "ドコグロ";
$MM = true;
}elseif (strpos($HOST, 'libmo') !== false) {
$SLIP_NAME = "ブモー";
$MM = true;
}elseif (strpos($HOST, 'ap.mvno.net') !== false) {
$SLIP_NAME = "アメ";
$MM = true;
}else {
$SLIP_NAME = "ワッチョイ";
}
if ($HOST == $_SERVER['REMOTE_ADDR'] && !$ipv6) {
$SLIP_NAME = "JP";
}
if (strpos($_SERVER['REMOTE_ADDR'], '133.106') !== false || strpos($_SERVER['REMOTE_ADDR'], '193.119') !== false || strpos($_SERVER['REMOTE_ADDR'], '133.100') !== false) {
$SLIP_NAME = "テテンテンテン";
$MM = true;
}
if (strpos($HOST, 'rakuten') !== false || strpos($_SERVER['REMOTE_ADDR'], '240b:c0') !== false) {
$SLIP_NAME = "ラクッペペ";
$MM = true;
}
if (strpos($_SERVER['REMOTE_ADDR'], '103.5.14') !== false) {
$SLIP_NAME = "ワイーワ2";
$WF = true;
}
if (strpos($HOST, '2001:240:24') !== false) {
$SLIP_NAME = "ブーイモ";
$MM = true;
}
// IPv6用(特殊)
if (strpos($HOST, '240a:61:') !== false) {
if (strpos($HOST, '240a:61:a') !== false || strpos($HOST, '240a:61:c') !== false || strpos($HOST, '240a:61:e') !== false || strpos($HOST, '240a:61:1') !== false || strpos($HOST, '240a:61:2') !== false || strpos($HOST, '240a:61:3') !== false || strpos($HOST, '240a:61:4') !== false) $SLIP_NAME = "スプッッ";
elseif (strpos($HOST, '240a:61:5') !== false || strpos($HOST, '240a:61:6') !== false || strpos($HOST, '240a:61:7') !== false || strpos($HOST, '240a:61:8') !== false || strpos($HOST, '240a:61:b') !== false || strpos($HOST, '240a:61:9') !== false || strpos($HOST, '240a:61:d') !== false || strpos($HOST, '240a:61:f') !== false) $SLIP_NAME = "スップ";
else $SLIP_NAME = "スプー";
$SLIP_SP = true;
}
if (strpos($HOST, '240a:6b:') !== false) {
if (strpos($HOST, '240a:6b:a') !== false || strpos($HOST, '240a:6b:c') !== false || strpos($HOST, '240a:6b:e') !== false || strpos($HOST, '240a:6b:1') !== false || strpos($HOST, '240a:6b:2') !== false || strpos($HOST, '240a:6b:3') !== false || strpos($HOST, '240a:6b:4') !== false) $SLIP_NAME = "スッップ";
elseif (strpos($HOST, '240a:6b:5') !== false || strpos($HOST, '240a:6b:6') !== false || strpos($HOST, '240a:6b:7') !== false || strpos($HOST, '240a:6b:8') !== false || strpos($HOST, '240a:6b:b') !== false || strpos($HOST, '240a:6b:9') !== false || strpos($HOST, '240a:6b:d') !== false || strpos($HOST, '240a:6b:f') !== false) $SLIP_NAME = "スププ";
else $SLIP_NAME = "スプッ";
$SLIP_SP = true;
}
if (strpos($HOST, '2001:268:9') !== false) {
if (strpos($HOST, '2001:268:9a') !== false || strpos($HOST, '2001:268:9e') !== false || strpos($HOST, '2001:268:9f') !== false) $SLIP_NAME = "アウアウアー";
elseif (strpos($HOST, '2001:268:9b') !== false || strpos($HOST, '2001:268:9c') !== false || strpos($HOST, '2001:268:9d') !== false) $SLIP_NAME = "アウアウイー";
elseif (strpos($HOST, '2001:268:98') !== false || strpos($HOST, '2001:268:91') !== false) $SLIP_NAME = "アウアウウー";
elseif (strpos($HOST, '2001:268:92') !== false || strpos($HOST, '2001:268:93') !== false) $SLIP_NAME = "アウアウエー";
elseif (strpos($HOST, '2001:268:94') !== false || strpos($HOST, '2001:268:95') !== false) $SLIP_NAME = "アウアウオー";
elseif (strpos($HOST, '2001:268:96') !== false || strpos($HOST, '2001:268:97') !== false) $SLIP_NAME = "アウアウカー";
elseif (strpos($HOST, '2001:268:99') !== false) $SLIP_NAME = "アウアウキー";
else $SLIP_NAME = "アウアウ";
$SLIP_SP = true;
}
if (strpos($HOST, '2400:2200:') !== false) {
if (strpos($HOST, '2400:2200:a') !== false || strpos($HOST, '2400:2200:c') !== false || strpos($HOST, '2400:2200:e') !== false) $SLIP_NAME = "ササクッテロラ";
elseif (strpos($HOST, '2400:2200:1') !== false || strpos($HOST, '2400:2200:2') !== false || strpos($HOST, '2400:2200:3') !== false) $SLIP_NAME = "ササクッテロリ";
elseif (strpos($HOST, '2400:2200:4') !== false || strpos($HOST, '2400:2200:5') !== false || strpos($HOST, '2400:2200:6') !== false) $SLIP_NAME = "ササクッテロル";
elseif (strpos($HOST, '2400:2200:7') !== false || strpos($HOST, '2400:2200:8') !== false || strpos($HOST, '2400:2200:b') !== false) $SLIP_NAME = "ササクッテロレ";
elseif (strpos($HOST, '2400:2200:9') !== false || strpos($HOST, '2400:2200:d') !== false || strpos($HOST, '2400:2200:f') !== false) $SLIP_NAME = "ササクッテロロ";
else $SLIP_NAME = "ササクッテロ";
$SLIP_SP = true;
}
if ($admin) $SLIP_NAME = "";
// ID末尾表示
if ($HOST == $_SERVER['REMOTE_ADDR'] && !$ipv6) $slip = "H";
if ($MM) $slip = "M";
elseif ($WF) $slip = "F";
elseif (strpos($HOST, 'spmode') !== false || strpos($HOST, '240a:61:') !== false || strpos($HOST, '240a:6b:') !== false) $slip = "d";
elseif (strpos($HOST, 'au-net') !== false || strpos($HOST, '2001:268:9') !== false) $slip = "a";
elseif (strpos($HOST, 'panda-world') !== false || strpos($HOST, '2400:2200:') !== false) $slip = "p";
elseif (strpos($HOST, 'openmobile') !== false) $slip = "r";
elseif (strpos($HOST, 'access-internet') !== false) $slip = "x";
elseif (strpos($HOST, 'e-mobile') !== false) $slip = "E";
elseif (strpos($HOST, 'mopera.net') !== false) $slip = "D";
elseif (strpos($HOST, 'google-proxy') !== false) $slip = "X";

7
test/htaccess Normal file
View File

@ -0,0 +1,7 @@
<Files ~ "^(bbs-main\.php|createcode\.cgi)$">
deny from all
</Files>
RewriteEngine on
RewriteRule ^read\.cgi/(.*?)/(.*?)/(.*)$ /#$1/$2 [L,R=301,NE]
RewriteRule bbs.cgi bbs.php
SetEnvIf Request_URI "bbs.php$" CONTENT_TYPE=application/x-www-form-urlencoded

80
test/icon.html Normal file
View File

@ -0,0 +1,80 @@
<!DOCTYPE html><html lang="ja"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"><title>アイコン設定</title><link href="/static/a.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="https://rentalbbs.net/js/jquery-1.11.3.min.js"></script></head><body><div id="container"><section><h1 class="section-title">アイコン設定</h1><div class="contents"><img id="iconimg" style="padding: 3px; margin-right: 3px; border-radius: 45px; display: block; padding-bottom: 5px; margin-left: -.1em;" width="45" height="45" align="left">:現在のアイコン<input id="imgurl" type="text" class="form-control" name="key" placeholder="画像URL"><p class="notice mt5">アイコンに設定するURLを入力してください</p></div><div class="contents">直接画像を選択:<input id="uploadImage" type="file" name="file" size="50" onchange="upload();"><p class="notice mt5">こちらでファイルを選択すると自動的にURLが入力されます。※imgur.comにアップロードされます</p></div><div class="contents"><input id="homepage" type="text" class="form-control" name="key" placeholder="ホームページURL"><p class="notice mt5">入力したURLがアイコンのリンク先となります</p></div><div class="contents"><button onclick="setimg()" class="btn btn-primary btn-block">設定</button><br><br><button onclick="delimg()" class="btn btn-primary btn-block">削除</button><h3 id="ntxt"></h3></div></section></div>
<hr><a href="#" onclick="window.history.go(-1);">前ページに戻る</a><br><a href="#" onclick="window.history.go(-2);">2つ前のページに戻る</a><br><a href="https://rentalbbs.net/">トップページに戻る</a>
<script>
if (getCookie("icon")) {
document.getElementById('imgurl').value = getCookie("icon");
document.getElementById('iconimg').src = getCookie("icon");
}
if (getCookie("homepage")) {
document.getElementById('homepage').value = getCookie("homepage");
}
function setimg() {
let cookname = escape(document.getElementById('imgurl').value);
document.cookie = "icon="+cookname+"; Max-Age=315360000; path=/";
let cookhome = escape(document.getElementById('homepage').value);
document.cookie = "homepage="+cookhome+"; Max-Age=315360000; path=/";
document.getElementById('ntxt').innerHTML = '設定完了';
}
function delimg() {
document.cookie = "icon=; Max-Age=0; path=/";
document.cookie = "homepage=; Max-Age=0; path=/";
document.getElementById('ntxt').innerHTML = '削除完了';
}
function upload() {
const preview = document.querySelector('img');
const file = document.querySelector('input[type=file]').files[0];
const reader = new FileReader();
reader.addEventListener("load", () => {
base64Url = reader.result;
base64 = base64Url.replace(new RegExp('data.*base64,'), '');
imgur();
}, false);
if (file) {
reader.readAsDataURL(file);
}
/// APIに渡すときは先頭の data:~~~base64 を除外
function imgur() {
let imgurkey = '34ee59e33373302';
$.ajax({
url: 'https://api.imgur.com/3/image',
method: 'POST',
headers: {
"Authorization": 'Client-ID '+imgurkey
},
data: {
image: base64,
type: 'base64'
},
success: function(r){
imgurlink = r.data.link
document.getElementById('imgurl').value = imgurlink;
},
error: function () {
document.getElementById('ntxt').innerHTML = '画像アップロードに失敗 ページをリロードしてください';
}
});
}
}
function getCookie(key, tmp1, tmp2, xx1, xx2, xx3) {
tmp1 = " " + document.cookie + ";";
while(tmp1.match(/\+/)) {tmp1 = tmp1.replace("+", " ");};
xx1 = xx2 = 0;
len = tmp1.length;
while (xx1 < len) {
xx2 = tmp1.indexOf(";", xx1);
tmp2 = tmp1.substring(xx1 + 1, xx2);
xx3 = tmp2.indexOf("=");
if (tmp2.substring(0, xx3) == key) {return(unescape(tmp2.substring(xx3 + 1, xx2 - xx1 - 1)));}
xx1 = xx2 + 1;
}
return("");
}
</script>
</body></html>

87
test/kanri2.php Normal file
View File

@ -0,0 +1,87 @@
<?php
error_reporting(E_COMPILE_ERROR | E_RECOVERABLE_ERROR | E_ERROR | E_CORE_ERROR | E_PARSE);
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
header("HTTP/1.1 403 Forbidden");
exit("403 Forbidden");
}
header('Content-Type: text/html; charset=UTF-8');
if (!isset($_POST['directory'])) $_POST['directory'] = '';
if (!isset($_POST['password'])) $_POST['password'] = '';
if (!isset($_POST['code'])) $_POST['code'] = '';
$file = "createcode.cgi";
$code = @file_get_contents($file);
if (strlen($_POST['directory']) == 0) Finish("ディレクトリ名が記入されていません");
if (strlen($_POST['directory']) > 16) Finish("ディレクトリ名は16文字以下で記入して下さい");
if (file_exists("../".$_POST['directory'])) Finish("ディレクトリ名は既に使用されています");
if (preg_match("/[^a-z0-9]/", $_POST['directory'])) Finish("ディレクトリ名には半角英数小文字のみ使用できます");
if (strlen($_POST['password']) == 0) Finish("パスワードが記入されていません");
if (strlen($code) > 0) {
if (strlen($_POST['code']) == 0) Finish("作成コードが記入されていません");
if ($_POST['code'] != $code) Finish("作成コードが無効です");
}
$password = password_hash($_POST['password'], PASSWORD_DEFAULT);
copy_dir("./board", "../".$_POST['directory']);
if (file_exists("../".$_POST['directory'])) {
@file_put_contents("../".$_POST['directory']."/passfile.cgi", $password);
$htaccess = '<Files ~ "\.cgi$">'."\n".'deny from all'."\n".'</Files>';
@file_put_contents("../".$_POST['directory']."/.htaccess", $htaccess);
$index = @file_get_contents("../".$_POST['directory']."/index.html");
$index = str_replace("<BBS>", $_POST['directory'], $index);
@file_put_contents("../".$_POST['directory']."/index.html", $index);
header('Location: ../'.$_POST['directory'].'/');
exit;
}else Finish("新規掲示板作成に失敗しました");
function Finish($value) {
header("HTTP/1.1 403 Forbidden");
?><!DOCTYPE HTML>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link href="/static/a.css" rel="stylesheet" type="text/css">
</head>
<body>
<?=$value?>
</body>
</html><?php
exit;
}
/**
* ディレクトリをコピーする
*
* @param string $dir コピー元ディレクトリ
* @param string $new_dir コピー先ディレクトリ
* @return void
*/
function copy_dir($dir, $new_dir) {
$dir = rtrim($dir, '/').'/';
$new_dir = rtrim($new_dir, '/').'/';
// コピー元ディレクトリが存在すればコピーを行う
if (is_dir($dir)) {
// コピー先ディレクトリが存在しなければ作成する
if (!is_dir($new_dir)) {
mkdir($new_dir);
}
// ディレクトリを開く
if ($handle = opendir($dir)) {
// ディレクトリ内のファイルを取得する
while (false !== ($file = readdir($handle))) {
if ($file === '.' || $file === '..') {
continue;
}
// 下の階層にディレクトリが存在する場合は再帰処理を行う
if (is_dir($dir.$file)) {
copy_dir($dir.$file, $new_dir.$file);
} else {
copy($dir.$file, $new_dir.$file);
}
}
closedir($handle);
}
}
}

1
test/operate/.htaccess Normal file
View File

@ -0,0 +1 @@
Deny from all

View File

@ -0,0 +1,38 @@
<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST' && $_POST['edit'] == "yes") {
file_put_contents($PATH."authorize.cgi", $_POST['authorize']);
}
$authorize = implode('', file($PATH."authorize.cgi"));
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content>
<meta name="author" content>
<title>承認済ユーザ</title>
<link rel="stylesheet" href="/static/a.css">
</head>
<body>
<div class="main">
<form method="post" action="?bbs=<?=$_REQUEST['bbs']?>&mode=authorization">
<input type="hidden" name="password" value="<?=$_REQUEST['password']?>">
<input type="hidden" name="edit" value="yes">
<div class="back"><a href="<?=$_SERVER['HTTP_REFERER']?>"> 管理ページへ戻る</a></div>
<div><b>承認済ユーザ</b></div><div><small class="notice mt5">掲示板TOP画面に表示されます</small></div>
<div class="notice mt5">
・自動承認に関する設定は基本設定にあります<br>
・承認済ユーザーとしたい<b>ClientID</b>または<b>リモートホスト</b>または<b>IPアドレス</b>を記入してください<br>
<b>ClientID</b>は完全一致のみ、<b>リモートホスト・IPアドレス</b>は部分一致も可(正規表現は使用不可)<br>
・一行につき一つとなります<br>
・行頭に半角の『#』を含んでいる行はコメント行として扱われます。<br>
<b>ClientID</b><b>リモートホスト</b><b>IPアドレス</b>はそれぞれ別々の適用となります<br>
</div>
<div><textarea style="font-size:9pt" rows="10" cols="70" name="authorize" wrap="OFF"><?=$authorize?></textarea></div>
<hr><div class="contents"><input type="submit" name="Submit" class="btn btn-primary btn-block" value="適用"></div>
</form>
</div>
</body>
</html>
<?php exit;

43
test/operate/cap.php Normal file
View File

@ -0,0 +1,43 @@
<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST' && $_POST['edit'] == "yes") {
file_put_contents($PATH."cap.cgi", $_POST['cap']);
}
$cap = implode('', file($PATH."cap.cgi"));
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content>
<meta name="author" content>
<title>キャップ</title>
<link rel="stylesheet" href="/static/a.css">
</head>
<body>
<div class="main">
<form method="post" action="/test/admin.php?bbs=<?=$_REQUEST['bbs']?>&mode=cap">
<input type="hidden" name="password" value="<?=$_REQUEST['password']?>">
<input type="hidden" name="edit" value="yes">
<div class="back"><a href="./admin.php"> 管理ページへ戻る</a></div>
<div><b>キャップ</b></div><div><small class="notice mt5">掲示板TOP画面に表示されます</small></div>
<div class="notice mt5">
&lt;&gt;が区切り文字、<b>名前</b>&lt;&gt;<b>パスワード</b>&lt;&gt;<b>権限</b>&lt;&gt;<b>ID</b><br>
・権限の欄が未記入の場合の権限(一般キャップ)<b>名前表示、ID秘匿、常時コマンド使用、一部規制回避、スレッド作成権限</b><br>
・権限の欄に<b>saku</b>を入れた場合:<b>一般キャップの権限に削除権限を加える</b><br>
・権限の欄に<b>sakud</b>を入れた場合:<b>削除権限、名前表示のみ</b><br>
・権限の欄に<b>plus</b>を入れた場合:<b>記者・立て子(名前表示+スレッド作成権限のみ)</b><br>
・権限の欄に<b>authorized</b>を入れた場合:キャップ使用時に<b>承認済ユーザー扱い</b>となる(ID欄に記入されている場合はそのIDを表示する。※名前は表示されませんが<b>アカウント・トリップ・Cookie</b>の欄に記入することで個別の規制を適用可能)<br>
・ID欄を設定するとキャップの種類に関わらず、<b>@&#60;設定したID&#62;</b>の形式で表示されます。ID秘匿権限が有るキャップでID欄が無記入の場合、<b>@CAP_USER</b>が表示されます。
・使用時は <b>Email欄</b><b>#パスワード</b>の形で記入して投稿してください。<br>
・authorized権限を除き名前欄に記入したものが投稿時の名前として表示されます。<br>
・一行につき一つのキャップです。<br>
・行頭に半角の『#』を含んでいる行はコメント行として扱われます。<br>
</div>
<div><textarea style="font-size:9pt" rows="10" cols="70" name="cap" wrap="OFF"><?=$cap?></textarea></div>
<hr><div class="contents"><input type="submit" name="Submit" class="btn btn-primary btn-block" value="適用"></div>
</form>
</div>
</body>
</html>
<?php exit;

143
test/operate/control.php Normal file
View File

@ -0,0 +1,143 @@
<?php
if (!$_REQUEST['key']) {
?><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>スレッド・レス管理</title>
<link href="/static/a.css" rel="stylesheet" type="text/css">
</head>
<body>
<div id="container"><section>
<h1 class="section-title">スレッド・レス管理</h1>
<h3>スレッド番号を直接入力</h3>
<form class="form-basic" method="POST" accept-charset="UTF-8" action="?bbs=<?=$_REQUEST['bbs']?>&mode=control">
<input type="hidden" name="password" value="<?=$_REQUEST['password']?>">
<div class="contents">
<input type="text" class="form-control" name="key" value="" placeholder="スレッド番号">
<p class="notice mt5">スレッド番号を入力してください。</p>
</div>
<div class="contents">
<button type="submit" class="btn btn-primary btn-block">管理</button>
</div>
</form>
<h3>スレッド一覧から探す</h3>
<div id="threadlist" class="contents"><?php
$Threads = json_decode(file_get_contents("../".$_REQUEST['bbs']."/subject.json"), true);
$PAGEFILE = array();
if ($Threads) {
foreach ($Threads as $thread) {
?><div><form class="form-basic" method="POST" accept-charset="UTF-8" action="?bbs=<?=$_REQUEST['bbs']?>&mode=control">
<div>スレッド番号:<a href="/#<?=$_REQUEST['bbs']?>/<?=$thread['thread']?>/"><?=$thread['thread']?></a></div>
<div>タイトル:<?=$thread['title']?></div>
<div>レス数:<?=$thread['number']?></div>
<div>作成時刻:<?php echo date("Y-m-d H:i:s", $thread['thread']); ?></div>
<div>最終更新時刻:<?php echo date("Y-m-d H:i:s", $thread['date']); ?></div>
<button type="submit" class="btn btn-primary btn-block">管理</button>
<input type="hidden" name="key" value="<?=$thread['thread']?>">
<input type="hidden" name="password" value="<?=$_REQUEST['password']?>">
</form></div><hr>
<?php
}
}
?></div>
</section></div>
</body>
</html><?php
exit;
}
// dat
$THREADFILE = "../".$_REQUEST['bbs']."/thread/".substr($_REQUEST['key'], 0, 4)."/".$_REQUEST['key'].".dat";
$DATFILE = "../".$_REQUEST['bbs']."/dat/".$_REQUEST['key'].".dat";
$KFILE = "../".$_REQUEST['bbs']."/dat/".$_REQUEST['key']."_kisei.cgi";
$subjectfile = "../".$_REQUEST['bbs']."/subject.json";
// スレッドが存在しない場合
if (!is_file($THREADFILE)) Finish('<b>該当するスレッドがありません</b>');
// スレッド取得
$LOG = file($THREADFILE);
if ($_POST['del']) {
if (!$_POST['kakunin']) {
// スレッド削除
if ($_POST['saku'] == "checked") {
unlink($THREADFILE);
if (is_file($DATFILE)) unlink($DATFILE);
if (is_file($KFILE)) unlink($KFILE);
//スレッド一覧から取り除く
$Threads = json_decode(file_get_contents($subjectfile), true);
$PAGEFILE = array();
if ($Threads) {
foreach ($Threads as $thread) {
if ($thread['thread'] != $_REQUEST['key']) array_push($PAGEFILE,$thread);
}
}
// 更新
file_put_contents($subjectfile, json_encode($PAGEFILE, JSON_UNESCAPED_UNICODE), LOCK_EX);
Finish('<b>スレッドを削除しました。</b>');
}else {
// レス削除・過去ログ化
if ($_POST['kako'] == "checked") {
if (is_file($DATFILE)) unlink($DATFILE);
//スレッド一覧から取り除く
$Threads = json_decode(file_get_contents($subjectfile), true);
$PAGEFILE = array();
if ($Threads) {
foreach ($Threads as $thread) {
if ($thread['thread'] != $_REQUEST['key']) array_push($PAGEFILE,$thread);
}
}
// 更新
file_put_contents($subjectfile, json_encode($PAGEFILE, JSON_UNESCAPED_UNICODE), LOCK_EX);
}
for ($i = 0; $i < count($LOG); $i++) {
if ($_POST[$i] == "checked" || ($i + 1 >= $_POST['from'] && $i + 1 <= $_POST['to']) || ($_POST['itti'] && strpos($LOG[$i],$_POST['itti']) !== false)) $LOG[$i] = "<><><>".$SETTING['DELETED_TEXT']."<>\n";
}
$fp = '';
foreach($LOG as $tmp) $fp .= $tmp;
file_put_contents($THREADFILE, $fp, LOCK_EX);
if (is_file($DATFILE)) file_put_contents($DATFILE, mb_convert_encoding($fp, "SJIS-win", "UTF-8"), LOCK_EX);
$result = "実行しました";
}
}else $result = "確認画面(削除されるレスにチェックが入っています。宜しければ「実行」をクリック)";
}
?><!DOCTYPE HTML>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>スレッド・レス管理</title>
<link href="/static/a.css" rel="stylesheet" type="text/css">
<style>
dd {
color: black;
margin-left: 40px;
clear: both;
font-size: 16px;
}
</style>
</head>
<body>
<b><?=$result?></b>
<div class="back"><a href='https://<?=$_SERVER['HTTP_HOST']?>/#<?=$_REQUEST['bbs']?>/<?=$_REQUEST['key']?>/'>スレッドを開く</a></div>
<form class="form-basic" method="POST" accept-charset="UTF-8" action=""><input type="hidden" name="password" value="<?=$_REQUEST['password']?>"><input type="hidden" name="bbs" value="<?=$_REQUEST['bbs']?>"><input type="hidden" name="key" value="<?=$_REQUEST['key']?>"><input type="hidden" name="del" value="true"><div class="contents"><button type="submit" class="btn btn-primary btn-block">実行</button></div>
<?php
$n = $i = 0;
echo "このスレッドを削除<input type=\"checkbox\" name=\"saku\" value=\"checked\"";
if ($_POST['kakunin'] && $_POST['saku'] == "checked") echo ' checked><br>';
else echo "><br>";
echo "このスレッドを強制過去ログ化<input type=\"checkbox\" name=\"kako\" value=\"checked\"";
if ($_POST['kakunin'] && $_POST['kako'] == "checked") echo ' checked>';
else echo ">";
echo '<div>レス一括削除(範囲指定)<input type="text" name="from">-<input type="text" name="to"></div><div>レス一括削除(条件一致)<input type="text" name="itti"></div>';
foreach($LOG as $tmp) {
$n++;
if ($_POST['kakunin'] && $_POST[$i] == "checked") $d = ' checked';
else $d = '';
list($name,$mail,$dateid,$comment,$subject) = explode("<>",$LOG[$i]);
$name = str_replace(array('<b>', '</b>'), "", $name);
if ($subject) echo "タイトル:".$subject;
echo "<dt>レス削除<input type=\"checkbox\" name=\"".$i."\" value=\"checked\"".$d."> ".$n."".$name."[".$mail."]".$dateid."</dt><dd>".$comment."</dd>";
$i++;
}
echo "<div>確認(削除が実行されるレスを確認できます。一括削除用)<input type=\"checkbox\" name=\"kakunin\" value=\"checked\"></div>";
exit('<div class="contents"><button type="submit" class="btn btn-primary btn-block">実行</button></div><div>一度操作を行うと復元できません</div></body></html>');

39
test/operate/error.php Normal file
View File

@ -0,0 +1,39 @@
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content>
<meta name="author" content>
<title>エラーログ</title>
<link rel="stylesheet" href="/static/a.css">
<style>
dd {
color: black;
margin-left: 40px;
clear: both;
font-size: 16px;
}
</style>
</head>
<body>
<div class="main">
<div class="back"><a href="<?=$_SERVER['HTTP_REFERER']?>"> 管理ページへ戻る</a></div>
<div><b>エラーログ</b></div>
<?php
// ログ
$LOGFILE = "../".$_REQUEST['bbs']."/errors.cgi";
$LOG = array();
$n = 0;
// ログ取得
if (is_file($LOGFILE)) $LOG = file($LOGFILE);
else Finish('<b>エラーログファイルがありません</b><div class="back"><a href="'.$_SERVER['HTTP_REFERER'].'">← 戻る</a></div>');
foreach($LOG as $tmp) {
$n++;
$tmp = rtrim($tmp);
list($error,$name,$mail,$dateid,$comment,$title,$key,$number,$HOST,$IP,$UA,$CH_UA,$ACCEPT,$accountid,$LV,$PORT,$CF_IPCOUNTRY,,$ken,$slip,) = explode("<>", $tmp);
echo "<dt>".$n."[$d] ".$name."[".$mail."]".$dateid." 発信元:".$IP."<".$PORT."> HOST:".$HOST."<dd>".$comment."<hr>ClientID:".$accountid."<Lv".$LV."><br>User-Agent:".$UA."<br>Sec-CH-UA:".$CH_UA."<br>ACCEPT:".$ACCEPT."<br>IPCOUNTRY:".$CF_IPCOUNTRY." 認証時データ:".$ken." ".$slip."<br>URL:<a href='https://".$_SERVER['HTTP_HOST']."/?st=".$number."#".$_REQUEST['bbs']."/".$key."/' target='_new'>https://".$_SERVER['HTTP_HOST']."/?st=".$number."#".$_REQUEST['bbs']."/".$key."/</a><hr><b>".$error."</b></dd>\n";
}
?></div>
</body>
</html>

34
test/operate/header.php Normal file
View File

@ -0,0 +1,34 @@
<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST' && $_POST['edit'] == "yes") {
file_put_contents($PATH."head.txt", $_POST['head']);
file_put_contents($PATH."kokuti.txt", $_POST['head2']);
}
$text = implode('', file($PATH."head.txt"));
$text2 = implode('', file($PATH."kokuti.txt"));
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content>
<meta name="author" content>
<title>ヘッダー・告知欄</title>
<link rel="stylesheet" href="/static/a.css">
</head>
<body>
<div class="main">
<form method="post" action="/test/admin.php?bbs=<?=$_REQUEST['bbs']?>&mode=header">
<input type="hidden" name="password" value="<?=$_REQUEST['password']?>">
<input type="hidden" name="edit" value="yes">
<div class="back"><a href="./admin.php"> 管理ページへ戻る</a></div>
<div><b>ヘッダー</b></div>
<div><textarea style="font-size:9pt" rows="10" cols="70" name="head" wrap="OFF"><?=$text?></textarea></div>
<div><b>告知欄</b></div>
<div><textarea style="font-size:9pt" rows="10" cols="70" name="head2" wrap="OFF"><?=$text2?></textarea></div>
<hr><div class="contents"><input type="submit" name="Submit" class="btn btn-primary btn-block" value="適用"></div>
</form>
</div>
</body>
</html>
<?php exit;

50
test/operate/id.php Normal file
View File

@ -0,0 +1,50 @@
<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST' && $_POST['edit'] == "yes") {
if (!isset($_POST['disp_accountid'])) $_POST['disp_accountid'] = '';
if (!isset($_POST['disp_slipname'])) $_POST['disp_slipname'] = '';
if (!isset($_POST['slip'])) $_POST['slip'] = '';
if (!isset($_POST['createid'])) $_POST['createid'] = '';
foreach ($SETTING as $name => $value) {
if (isset($_POST[$name])) $SETTING[$name] = $_POST[$name];
$SET .= $name."=".$SETTING[$name]."\n";
}
file_put_contents($setfile, json_encode($SETTING, JSON_UNESCAPED_UNICODE), LOCK_EX);
file_put_contents($settxt, mb_convert_encoding($SET, "SJIS-win", "UTF-8"), LOCK_EX);
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content>
<meta name="author" content>
<title>基本設定</title>
<link rel="stylesheet" href="/static/a.css">
</head>
<body>
<div class="main">
<form method="post" action="/test/admin.php?bbs=<?=$_REQUEST['bbs']?>&mode=id">
<input type="hidden" name="password" value="<?=$_REQUEST['password']?>">
<input type="hidden" name="edit" value="yes">
<div class="back"><a href="./admin.php"> 管理ページへ戻る</a></div>
<div><b>ID</b></div>
<div><input type="radio" name="id" value="checked" <?php if ($SETTING['id']=="checked") echo "checked"; ?>>IDを表示<br><input type="radio" name="id" value="" <?php if (!$SETTING['id']) echo "checked"; ?>>IDを表示しない<br><input type="radio" name="id" value="siberia" <?php if ($SETTING['id']=="siberia") echo "checked"; ?>>発信元IPアドレスを表示</div>
<div><b>IDをリセットする間隔</b></div>
<div><input type="radio" name="ID_RESET" value="day" <?php if ($SETTING['ID_RESET']=="day") echo "checked"; ?>>1日<input type="radio" name="ID_RESET" value="10days" <?php if ($SETTING['ID_RESET']=="10days") echo "checked"; ?>>10日<input type="radio" name="ID_RESET" value="10hours" <?php if ($SETTING['ID_RESET']=="10hours") echo "checked"; ?>>10時間<input type="radio" name="ID_RESET" value="month" <?php if ($SETTING['ID_RESET']=="month") echo "checked"; ?>>1ヶ月<input type="radio" name="ID_RESET" value="year" <?php if ($SETTING['ID_RESET']=="year") echo "checked"; ?>>1年<input type="radio" name="ID_RESET" value="hour" <?php if ($SETTING['ID_RESET']=="hour") echo "checked"; ?>>1時間<input type="radio" name="ID_RESET" value="10minutes" <?php if ($SETTING['ID_RESET']=="10minutes") echo "checked"; ?>>10分<input type="radio" name="ID_RESET" value="minute" <?php if ($SETTING['ID_RESET']=="minute") echo "checked"; ?>>60秒間隔<br></div>
<div><b>回線別ニックネーム(ワッチョイ)を表示</b><small class="notice mt5">承認済ユーザーは非表示</small></div>
<div><input type="checkbox" name="disp_slipname" value="checked"<?php if ($SETTING['disp_slipname']=="checked") echo " checked"; ?>>する</div>
<div><b>新規表示(Lv0以下のみ)と回線別末尾を追加</b></div>
<div><input type="checkbox" name="slip" value="checked"<?php if ($SETTING['slip']=="checked") echo " checked"; ?>>する</div>
<div><b>発信元表示</b></div>
<div><input type="radio" name="fusianasan" value="name" <?php if ($SETTING['fusianasan']=="name") echo "checked"; ?>>リモートホストを表示<br><input type="radio" name="fusianasan" value="id" <?php if ($SETTING['fusianasan']=="id") echo "checked"; ?>>ClientIDを表示<br><input type="radio" name="fusianasan" value="" <?php if ($SETTING['fusianasan']=="") echo "checked"; ?>>表示しない</div>
<div><b>スレッドタイトルにIDを追加</b></div>
<div><input type="checkbox" name="createid" value="checked"<?php if ($SETTING['createid']=="checked") echo " checked"; ?>>する</div>
<div><b>地域名表示</b></div>
<div><input type="radio" name="BBS_JP_CHECK" value="checked" <?php if ($SETTING['BBS_JP_CHECK']=="checked") echo "checked"; ?>>する<br><input type="radio" name="BBS_JP_CHECK" value="" <?php if (!$SETTING['BBS_JP_CHECK']) echo "checked"; ?>>しない</div>
<hr><div class="contents"><input type="submit" name="Submit" class="btn btn-primary btn-block" value="適用"></div>
</form>
</div>
</body>
</html>
<?php exit;

89
test/operate/kisei.php Normal file
View File

@ -0,0 +1,89 @@
<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST' && $_POST['edit'] == "yes") {
if (!isset($_POST['Samba24'])) $_POST['Samba24'] = '';
if (!isset($_POST['timecheck'])) $_POST['timecheck'] = '';
if (!isset($_POST['threadcheck'])) $_POST['threadcheck'] = '';
if (!isset($_POST['newthread_check'])) $_POST['newthread_check'] = '';
if (!isset($_POST['authorized_denypass'])) $_POST['authorized_denypass'] = '';
if (!isset($_POST['change_sakujyo'])) $_POST['change_sakujyo'] = '';
if (!isset($_POST['NANASHI_CHECK'])) $_POST['NANASHI_CHECK'] = '';
if (!isset($_POST['BBS_PROXY_CHECK'])) $_POST['BBS_PROXY_CHECK'] = '';
if (!isset($_POST['JAPANESE_CHECK'])) $_POST['JAPANESE_CHECK'] = '';
if (!isset($_POST['NOPIC'])) $_POST['NOPIC'] = '';
if (!isset($_POST['DISABLE_LINK'])) $_POST['DISABLE_LINK'] = '';
foreach ($SETTING as $name => $value) {
if (isset($_POST[$name])) $SETTING[$name] = $_POST[$name];
$SET .= $name."=".$SETTING[$name]."\n";
}
file_put_contents($setfile, json_encode($SETTING, JSON_UNESCAPED_UNICODE), LOCK_EX);
file_put_contents($settxt, mb_convert_encoding($SET, "SJIS-win", "UTF-8"), LOCK_EX);
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content>
<meta name="author" content>
<title>規制・制限設定</title>
<link rel="stylesheet" href="/static/a.css">
</head>
<body>
<div class="main">
<form method="post" action="?bbs=<?=$_REQUEST['bbs']?>&mode=kisei">
<input type="hidden" name="password" value="<?=$_REQUEST['password']?>">
<input type="hidden" name="edit" value="yes">
<div class="back"><a href="./admin.php"> 管理ページへ戻る</a></div>
<div><b>UNICODE</b>(絵文字等)</div>
<div><input type="radio" name="BBS_UNICODE" value="deny" <?php if ($SETTING['BBS_UNICODE']=="deny") echo "checked"; ?>>禁止<br><input type="radio" name="BBS_UNICODE" value="change" <?php if ($SETTING['BBS_UNICODE']=="change") echo "checked"; ?>>?に変換<br><input type="radio" name="BBS_UNICODE" value="pass" <?php if ($SETTING['BBS_UNICODE']=="pass") echo "checked"; ?>>タイトルのみ?に変換<br><input type="radio" name="BBS_UNICODE" value="checked" <?php if ($SETTING['BBS_UNICODE']=="checked") echo "checked"; ?>>許可</div>
<div><b>短時間連続投稿制限</b></div>
<div><input type="checkbox" value="checked" name="Samba24"<?php if ($SETTING['Samba24']=="checked") echo " checked"; ?>>適用する</div>
<div><input type="text" value="<?=$SETTING['BBS_SAMBA24']?>" name="BBS_SAMBA24"></div>
<div><b>各スレッド内でのレス間隔制限秒数</b><small class="notice mt5">(他者の投稿を含む)</small></div>
<div><input type="text" value="<?=$SETTING['timeinterval']?>" name="timeinterval"></div>
<div><b>連続投稿規制</b></div>
<div><input type="checkbox" value="checked" name="timecheck"<?php if ($SETTING['timecheck']=="checked") echo " checked"; ?>>適用する</div>
<div><input type="text" name="timelimit" value="<?=$SETTING['timelimit']?>">秒以内に<input type="text" name="timecount" value="<?=$SETTING['timecount']?>">回中<input type="text" name="timeclose" value="<?=$SETTING['timeclose']?>">回以上で規制</div>
<div><b>各スレッド内での連続投稿規制</b></div>
<div><input type="checkbox" value="checked" name="threadcheck"<?php if ($SETTING['threadcheck']=="checked") echo " checked"; ?>>適用する</div>
<div><input type="text" name="threadlimit" value="<?=$SETTING['threadlimit']?>">秒以内に<input type="text" name="threadcount" value="<?=$SETTING['threadcount']?>">回中<input type="text" name="timecover" value="<?=$SETTING['timecover']?>">回以上で規制</div>
<div><b>投稿上限行数</b><small class="notice mt5">(承認済ユーザーは値の3倍値・未承認ユーザーはこの値の2倍値を適用)</small></div>
<div><input type="text" name="BBS_LINE_NUMBER" value="<?=$SETTING['BBS_LINE_NUMBER']?>"></div>
<div><b>スレッドタイトル上限</b><small class="notice mt5">(承認済ユーザーは値の3倍値を適用)</small></div>
<div><input type="text" name="BBS_SUBJECT_COUNT" value="<?=$SETTING['BBS_SUBJECT_COUNT']?>"></div>
<div><b>名前上限</b><small class="notice mt5">(承認済ユーザーは値の3倍値を適用)</small></div>
<div><input type="text" name="BBS_NAME_COUNT" value="<?=$SETTING['BBS_NAME_COUNT']?>"></div>
<div><b>メール上限</b><small class="notice mt5">(承認済ユーザーは値の3倍値を適用)</small></div>
<div><input type="text" name="BBS_MAIL_COUNT" value="<?=$SETTING['BBS_MAIL_COUNT']?>"></div>
<div><b>本文上限</b><small class="notice mt5">(承認済ユーザーは値の3倍値を適用)</small></div>
<div><input type="text" name="BBS_MESSAGE_COUNT" value="<?=$SETTING['BBS_MESSAGE_COUNT']?>"></div>
<div><b>スレッド作成順番待ち</b></div>
<div><input type="checkbox" value="checked" name="newthread_check"<?php if ($SETTING['newthread_check']=="checked") echo " checked"; ?>>適用する</div>
<div><input type="text" name="JUNBAN_LIMIT" value="<?=$SETTING['JUNBAN_LIMIT']?>">秒以内に<input type="text" name="THREAD_JUNBAN" value="<?=$SETTING['THREAD_JUNBAN']?>"></div>
<div><b>スレッド作成間隔制限秒数</b><small class="notice mt5">(他者のスレ立てを含む)</small></div>
<div><input type="text" value="<?=$SETTING['THREAD_INTERVAL']?>" name="THREAD_INTERVAL"></div>
<div><b>承認済ユーザーを個別規制の対象から除外</b></div>
<div><input type="checkbox" value="checked" name="authorized_denypass"<?php if ($SETTING['authorized_denypass']=="checked") echo " checked"; ?>>する</div>
<div><b>日本国外の回線からの投稿を禁止</b><small class="notice mt5">(未承認ユーザーのみ)</small></div>
<div><input type="radio" name="BBS_FOREIGN_PASS" value="" <?php if ($SETTING['BBS_FOREIGN_PASS']!="on") echo "checked"; ?>>する<input type="radio" name="BBS_FOREIGN_PASS" value="on" <?php if ($SETTING['BBS_FOREIGN_PASS']=="on") echo "checked"; ?>>しない<br></div>
<div><b>Proxy規制</b><small class="notice mt5">(未承認ユーザーのみ)</small></div>
<div><input type="radio" name="BBS_BBX_PASS" value="" <?php if ($SETTING['BBS_BBX_PASS']!="on") echo "checked"; ?>>する<input type="radio" name="BBS_BBX_PASS" value="on" <?php if ($SETTING['BBS_BBX_PASS']=="on") echo "checked"; ?>>しない<br></div>
<div><b><small>名前欄の「管理」「削除」「sakujyo」を「"管理"」等へ置換(なりすまし防止)</small></b></div>
<div><input type="checkbox" name="change_sakujyo" value="checked"<?php if ($SETTING['change_sakujyo']=="checked") echo " checked"; ?>>する</div>
<div><b>投稿時の名前入力を必須</b></div>
<div><input type="checkbox" name="NANASHI_CHECK" value="checked"<?php if ($SETTING['NANASHI_CHECK']=="checked") echo " checked"; ?>>する</div>
<div><b>JPドメイン以外のホストからの投稿を禁止</b><small class="notice mt5">(未承認ユーザーのみ)</small></div>
<div><input type="checkbox" value="checked" name="BBS_PROXY_CHECK"<?php if ($SETTING['BBS_PROXY_CHECK']=="checked") echo " checked"; ?>>する</div>
<div><b>日本語を含まない投稿を禁止</b><small class="notice mt5">(未承認ユーザーのみ)</small></div>
<div><input type="checkbox" value="checked" name="JAPANESE_CHECK"<?php if ($SETTING['JAPANESE_CHECK']=="checked") echo " checked"; ?>>する</div>
<div><b>画像の投稿を禁止</b><small class="notice mt5">(未承認ユーザーのみ)</small></div>
<div><input type="checkbox" value="checked" name="NOPIC"<?php if ($SETTING['NOPIC']=="checked") echo " checked"; ?>>する</div>
<div bgcolor="#999999"><div><b>リンクの投稿を禁止</b><small class="notice mt5">(未承認ユーザーのみ)</small></div>
<div><input type="checkbox" value="checked" name="DISABLE_LINK"<?php if ($SETTING['DISABLE_LINK']=="checked") echo " checked"; ?>>する</div>
<hr><div class="contents"><input type="submit" name="Submit" class="btn btn-primary btn-block" value="適用"></div>
</form>
</div>
</body>
</html>
<?php exit;

88
test/operate/kisei2.php Normal file
View File

@ -0,0 +1,88 @@
<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST' && $_POST['edit'] == "yes") {
file_put_contents($PATH."deny_host.cgi", $_POST['host']);
file_put_contents($PATH."deny_ip.cgi", $_POST['ip']);
file_put_contents($PATH."deny_ua.cgi", $_POST['ua']);
file_put_contents($PATH."deny_account.cgi", $_POST['account']);
file_put_contents($PATH."deny_area.cgi", $_POST['area']);
}
$host = implode('', file($PATH."deny_host.cgi"));
$ip = implode('', file($PATH."deny_ip.cgi"));
$ua = implode('', file($PATH."deny_ua.cgi"));
$account = implode('', file($PATH."deny_account.cgi"));
$area = implode('', file($PATH."deny_area.cgi"));
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content>
<meta name="author" content>
<title>投稿規制</title>
<link rel="stylesheet" href="/static/a.css">
</head>
<body>
<div class="main">
<form method="post" action="?bbs=<?=$_REQUEST['bbs']?>&mode=kisei2">
<input type="hidden" name="password" value="<?=$_REQUEST['password']?>">
<input type="hidden" name="edit" value="yes">
<div class="back"><a href="./admin.php"> 管理ページへ戻る</a></div>
<h3>投稿規制</h3>
<div><b>リモートホスト</b></div>
<div class="notice mt5">
&lt;&gt;が区切り文字、<b>規制対象(リモートホスト)</b>&lt;&gt;<b>対象スレッド(省略可)</b>&lt;&gt;<b>発動ワード(省略可)</b>の形で記入してください。<br>
<b>対象スレッド</b>に記入されている場合はそのワードをタイトルに含むスレッド内でのみ規制。無記入の場合は掲示板内全スレッドが対象。<br>
<b>発動ワード</b>に記入されている場合はそのワードを含んだ場合のみ規制。特定範囲のみ適用されるNGワードとお考えください<br>
・1行につき1つの規制です。<br>
・行頭に半角の『#』を含んでいる行はコメント行として扱われます。<br>
・正規表現です。特殊な文字にご注意ください。<br>
</div>
<div><textarea style="font-size:9pt" rows="10" cols="70" name="host" wrap="OFF"><?=$host?></textarea></div>
<div><b>IPアドレス</b></div>
<div class="notice mt5">
&lt;&gt;が区切り文字、<b>規制対象(リモートホスト)</b>&lt;&gt;<b>対象スレッド(省略可)</b>&lt;&gt;<b>発動ワード(省略可)</b>の形で記入してください。<br>
<b>対象スレッド</b>に記入されている場合はそのワードをタイトルに含むスレッド内でのみ規制。無記入の場合は掲示板内全スレッドが対象。<br>
<b>発動ワード</b>に記入されている場合はそのワードを含んだ場合のみ規制。特定範囲のみ適用されるNGワードとお考えください<br>
・1行につき1つの規制です。<br>
・行頭に半角の『#』を含んでいる行はコメント行として扱われます。<br>
・正規表現です。特殊な文字にご注意ください。<br>
</div>
<div><textarea style="font-size:9pt" rows="10" cols="70" name="ip" wrap="OFF"><?=$ip?></textarea></div>
<div><b>User-Agent</b></div>
<div class="notice mt5">
&lt;&gt;が区切り文字、<b>規制対象(User-Agent)</b>&lt;&gt;<b>対象スレッド(省略可)</b>&lt;&gt;<b>発動ワード(省略可)</b>の形で記入してください。<br>
<b>対象スレッド</b>に記入されている場合はそのワードをタイトルに含むスレッド内でのみ規制。無記入の場合は掲示板内全スレッドが対象。<br>
<b>発動ワード</b>に記入されている場合はそのワードを含んだ場合のみ規制。特定範囲のみ適用されるNGワードとお考えください<br>
・1行につき1つの規制です。<br>
・行頭に半角の『#』を含んでいる行はコメント行として扱われます。<br>
・正規表現です。特殊な文字にご注意ください。<br>
</div>
<div><textarea style="font-size:9pt" rows="10" cols="70" name="ua" wrap="OFF"><?=$ua?></textarea></div>
<div><b>ClientID</b></div>
<div class="notice mt5">
&lt;&gt;が区切り文字、<b>規制対象</b>&lt;&gt;<b>対象スレッド(省略可)</b>&lt;&gt;<b>発動ワード(省略可)</b>の形で記入してください。<br>
<b>対象スレッド</b>に記入されている場合はそのワードをタイトルに含むスレッド内でのみ規制。無記入の場合は掲示板内全スレッドが対象。<br>
<b>発動ワード</b>に記入されている場合はそのワードを含んだ場合のみ規制。特定範囲のみ適用されるNGワードとお考えください<br>
・1行につき1つの規制です。<br>
・行頭に半角の『#』を含んでいる行はコメント行として扱われます。<br>
・正規表現です。特殊な文字にご注意ください。<br>
</div>
<div><textarea style="font-size:9pt" rows="10" cols="70" name="account" wrap="OFF"><?=$account?></textarea></div>
<div><b>国・地域</b></div>
<div class="notice mt5">
・国・地域による投稿規制は基本設定の<b>Geolocation API</b>を使用するにしている場合のみ使用できます<br>
&lt;&gt;が区切り文字、<b>規制対象(国コード・県名・市名)</b>&lt;&gt;<b>対象スレッド(省略可)</b>&lt;&gt;<b>発動ワード(省略可)</b>の形で記入してください。<br>
<b>対象スレッド</b>に記入されている場合はそのワードをタイトルに含むスレッド内でのみ規制。無記入の場合は掲示板内全スレッドが対象。<br>
<b>発動ワード</b>に記入されている場合はそのワードを含んだ場合のみ規制。特定範囲のみ適用されるNGワードとお考えください<br>
・1行につき1つの規制です。<br>
・行頭に半角の『#』を含んでいる行はコメント行として扱われます。<br>
・正規表現です。特殊な文字にご注意ください。<br>
</div>
<div><textarea style="font-size:9pt" rows="10" cols="70" name="area" wrap="OFF"><?=$area?></textarea></div>
<hr><div class="contents"><input type="submit" name="Submit" class="btn btn-primary btn-block" value="適用"></div>
</form>
</div>
</body>
</html>
<?php exit;

88
test/operate/kisei3.php Normal file
View File

@ -0,0 +1,88 @@
<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST' && $_POST['edit'] == "yes") {
file_put_contents($PATH."makedeny_host.cgi", $_POST['host']);
file_put_contents($PATH."makedeny_ip.cgi", $_POST['ip']);
file_put_contents($PATH."makedeny_ua.cgi", $_POST['ua']);
file_put_contents($PATH."makedeny_account.cgi", $_POST['account']);
file_put_contents($PATH."makedeny_area.cgi", $_POST['area']);
}
$host = implode('', file($PATH."makedeny_host.cgi"));
$ip = implode('', file($PATH."makedeny_ip.cgi"));
$ua = implode('', file($PATH."makedeny_ua.cgi"));
$account = implode('', file($PATH."makedeny_account.cgi"));
$area = implode('', file($PATH."makedeny_area.cgi"));
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content>
<meta name="author" content>
<title>スレッド作成規制</title>
<link rel="stylesheet" href="/static/a.css">
</head>
<body>
<div class="main">
<form method="post" action="?bbs=<?=$_REQUEST['bbs']?>&mode=kisei3">
<input type="hidden" name="password" value="<?=$_REQUEST['password']?>">
<input type="hidden" name="edit" value="yes">
<div class="back"><a href="./admin.php"> 管理ページへ戻る</a></div>
<h3>スレッド作成規制</h3>
<div><b>リモートホスト</b></div>
<div class="notice mt5">
&lt;&gt;が区切り文字、<b>規制対象(リモートホスト)</b>&lt;&gt;<b>発動タイトル(省略可)</b>&lt;&gt;<b>発動ワード(省略可)</b>の形で記入してください。<br>
<b>発動タイトル</b>に記入されている場合はそのワードをタイトルに含むスレッド作成のみ規制。<br>
<b>発動ワード</b>に記入されている場合はそのワードを含んだ場合のみ規制。特定範囲のみ適用されるNGワードとお考えください<br>
・1行につき1つの規制です。<br>
・行頭に半角の『#』を含んでいる行はコメント行として扱われます。<br>
・正規表現です。特殊な文字にご注意ください。<br>
</div>
<div><textarea style="font-size:9pt" rows="10" cols="70" name="host" wrap="OFF"><?=$host?></textarea></div>
<div><b>IPアドレス</b></div>
<div class="notice mt5">
&lt;&gt;が区切り文字、<b>規制対象(リモートホスト)</b>&lt;&gt;<b>発動タイトル(省略可)</b>&lt;&gt;<b>発動ワード(省略可)</b>の形で記入してください。<br>
<b>発動タイトル</b>に記入されている場合はそのワードをタイトルに含むスレッド作成のみ規制。<br>
<b>発動ワード</b>に記入されている場合はそのワードを含んだ場合のみ規制。特定範囲のみ適用されるNGワードとお考えください<br>
・1行につき1つの規制です。<br>
・行頭に半角の『#』を含んでいる行はコメント行として扱われます。<br>
・正規表現です。特殊な文字にご注意ください。<br>
</div>
<div><textarea style="font-size:9pt" rows="10" cols="70" name="ip" wrap="OFF"><?=$ip?></textarea></div>
<div><b>User-Agent</b></div>
<div class="notice mt5">
&lt;&gt;が区切り文字、<b>規制対象(User-Agent)</b>&lt;&gt;<b>発動タイトル(省略可)</b>&lt;&gt;<b>発動ワード(省略可)</b>の形で記入してください。<br>
<b>発動タイトル</b>に記入されている場合はそのワードをタイトルに含むスレッド作成のみ規制。<br>
<b>発動ワード</b>に記入されている場合はそのワードを含んだ場合のみ規制。特定範囲のみ適用されるNGワードとお考えください<br>
・1行につき1つの規制です。<br>
・行頭に半角の『#』を含んでいる行はコメント行として扱われます。<br>
・正規表現です。特殊な文字にご注意ください。<br>
</div>
<div><textarea style="font-size:9pt" rows="10" cols="70" name="ua" wrap="OFF"><?=$ua?></textarea></div>
<div><b>ClientID</b></div>
<div class="notice mt5">
&lt;&gt;が区切り文字、<b>規制対象</b>&lt;&gt;<b>発動タイトル(省略可)</b>&lt;&gt;<b>発動ワード(省略可)</b>の形で記入してください。<br>
<b>発動タイトル</b>に記入されている場合はそのワードをタイトルに含むスレッド作成のみ規制。<br>
<b>発動ワード</b>に記入されている場合はそのワードを含んだ場合のみ規制。特定範囲のみ適用されるNGワードとお考えください<br>
・1行につき1つの規制です。<br>
・行頭に半角の『#』を含んでいる行はコメント行として扱われます。<br>
・正規表現です。特殊な文字にご注意ください。<br>
</div>
<div><textarea style="font-size:9pt" rows="10" cols="70" name="account" wrap="OFF"><?=$account?></textarea></div>
<div><b>国・地域</b></div>
<div class="notice mt5">
・国・地域による投稿規制は基本設定の<b>Geolocation API</b><b>使用する</b>にしている場合のみ使用可能<br>
&lt;&gt;が区切り文字、<b>規制対象(国コード・県名・市名)</b>&lt;&gt;<b>発動タイトル(省略可)</b>&lt;&gt;<b>発動ワード(省略可)</b>の形で記入してください。<br>
<b>発動タイトル</b>に記入されている場合はそのワードをタイトルに含むスレッド作成のみ規制。<br>
<b>発動ワード</b>に記入されている場合はそのワードを含んだ場合のみ規制。特定範囲のみ適用されるNGワードとお考えください<br>
・1行につき1つの規制です。<br>
・行頭に半角の『#』を含んでいる行はコメント行として扱われます。<br>
・正規表現です。特殊な文字にご注意ください。<br>
</div>
<div><textarea style="font-size:9pt" rows="10" cols="70" name="area" wrap="OFF"><?=$area?></textarea></div>
<hr><div class="contents"><input type="submit" name="Submit" class="btn btn-primary btn-block" value="適用"></div>
</form>
</div>
</body>
</html>
<?php exit;

39
test/operate/log.php Normal file
View File

@ -0,0 +1,39 @@
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content>
<meta name="author" content>
<title>ログ閲覧</title>
<link rel="stylesheet" href="/static/a.css">
<style>
dd {
color: black;
margin-left: 40px;
clear: both;
font-size: 16px;
}
</style>
</head>
<body>
<div class="main">
<div class="back"><a href="<?=$_SERVER['HTTP_REFERER']?>"> 管理ページへ戻る</a></div>
<div><b>ログ閲覧</b></div>
<?php
// ログ
$LOGFILE = "../".$_REQUEST['bbs']."/LOG.cgi";
$LOG = array();
$n = 0;
// ログ取得
if (is_file($LOGFILE)) $LOG = file($LOGFILE);
else Finish('<b>ログファイルがありません</b><div class="back"><a href="'.$_SERVER['HTTP_REFERER'].'">← 戻る</a></div>');
foreach($LOG as $tmp) {
$n++;
$tmp = rtrim($tmp);
list($name,$mail,$dateid,$comment,$title,$key,$number,$HOST,$IP,$UA,$CH_UA,$ACCEPT,$accountid,$LV,$PORT,$CF_IPCOUNTRY,,$ken,$slip,) = explode("<>", $tmp);
echo "<dt>".$n."[$d] ".$name."[".$mail."]".$dateid." 発信元:".$IP."<".$PORT."> HOST:".$HOST."<dd>".$comment."<hr>ClientID:".$accountid."<Lv".$LV."><br>User-Agent:".$UA."<br>Sec-CH-UA:".$CH_UA."<br>ACCEPT:".$ACCEPT."<br>IPCOUNTRY:".$CF_IPCOUNTRY." 認証時データ:".$ken." ".$slip."<br>URL:<a href='https://".$_SERVER['HTTP_HOST']."/?st=".$number."#".$_REQUEST['bbs']."/".$key."/' target='_new'>https://".$_SERVER['HTTP_HOST']."/?st=".$number."#".$_REQUEST['bbs']."/".$key."/</a></dd>\n";
}
?></div>
</body>
</html>

95
test/operate/main.php Normal file
View File

@ -0,0 +1,95 @@
<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST' && $_POST['edit'] == "yes") {
if (!isset($_POST['ip_geolocation'])) $_POST['ip_geolocation'] = '';
if (!isset($_POST['use_capture'])) $_POST['use_capture'] = '';
if (!isset($_POST['capture_authorize'])) $_POST['capture_authorize'] = '';
if (!isset($_POST['use_account_lv'])) $_POST['use_account_lv'] = '';
if (!isset($_POST['authorized_denypass'])) $_POST['authorized_denypass'] = '';
if (!isset($_POST['cookie_enable'])) $_POST['cookie_enable'] = '';
if (!isset($_POST['trip_enable'])) $_POST['trip_enable'] = '';
if (!isset($_POST['trip_authorize'])) $_POST['trip_authorize'] = '';
if (!isset($_POST['account_enable'])) $_POST['account_enable'] = '';
if (!isset($_POST['auto_authorize'])) $_POST['auto_authorize'] = '';
if (!isset($_POST['g_auto_authorize'])) $_POST['g_auto_authorize'] = '';
if (!isset($_POST['DISABLE_ICON'])) $_POST['DISABLE_ICON'] = '';
if (!isset($_POST['DISABLE_NAME'])) $_POST['DISABLE_NAME'] = '';
if (!isset($_POST['DISABLE_TRIP'])) $_POST['DISABLE_TRIP'] = '';
if (!isset($_POST['FORCE_DISP_TRIP'])) $_POST['FORCE_DISP_TRIP'] = '';
if (!isset($_POST['NAME_ARR'])) $_POST['NAME_ARR'] = '';
if (!isset($_POST['Create_Authentication_required'])) $_POST['Create_Authentication_required'] = '';
if (!isset($_POST['Create_cap_only'])) $_POST['Create_cap_only'] = '';
if (!isset($_POST['Authentication_required'])) $_POST['Authentication_required'] = '';
if (!isset($_POST['cap_only'])) $_POST['cap_only'] = '';
if (!isset($_POST['disable_kakolog'])) $_POST['disable_kakolog'] = '';
if (!isset($_POST['thread_supervisor'])) $_POST['thread_supervisor'] = '';
if (!isset($_POST['aa_check'])) $_POST['aa_check'] = '';
foreach ($SETTING as $name => $value) {
if (isset($_POST[$name])) $SETTING[$name] = $_POST[$name];
$SET .= $name."=".$SETTING[$name]."\n";
}
file_put_contents($setfile, json_encode($SETTING, JSON_UNESCAPED_UNICODE), LOCK_EX);
file_put_contents($settxt, mb_convert_encoding($SET, "SJIS-win", "UTF-8"), LOCK_EX);
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content>
<meta name="author" content>
<title>基本設定</title>
<link rel="stylesheet" href="/static/a.css">
</head>
<body>
<div class="main">
<form method="post" action="/test/admin.php?bbs=<?=$_REQUEST['bbs']?>&mode=main">
<input type="hidden" name="password" value="<?=$_REQUEST['password']?>">
<input type="hidden" name="edit" value="yes">
<div class="back"><a href="./admin.php"> 管理ページへ戻る</a></div>
<div><b>指定Lv(鍵発行からの経過日数)以上の場合自動承認</b><small class="notice mt5">無記入で無効化</small></div>
<div><input type="text" value="<?=$SETTING['auto_authorize_lv']?>" name="auto_authorize_lv">Lv以上</div>
<div><b>アイコンを強制非表示</b></div>
<div><input type="checkbox" value="checked" name="DISABLE_ICON"<?php if ($SETTING['DISABLE_ICON']=="checked") echo " checked"; ?>>する</div>
<div><b>名前を強制非表示</b><small class="notice mt5">(※名前欄無効の場合でも投稿ログ閲覧ページからトリップを確認できます)</small></div>
<div><input type="checkbox" value="checked" name="DISABLE_NAME"<?php if ($SETTING['DISABLE_NAME']=="checked") echo " checked"; ?>>する</div>
<div><b>トリップを強制非表示</b><small class="notice mt5">(※トリップ無効の場合でも投稿ログ閲覧ページからトリップを確認できます)</small></div>
<div><input type="checkbox" value="checked" name="DISABLE_TRIP"<?php if ($SETTING['DISABLE_TRIP']=="checked") echo " checked"; ?>>する</div>
<div><b>!hideによるトリップ非表示を無効化</b><small class="notice mt5">(トリップ強制表示)</small></div>
<div><input type="checkbox" value="checked" name="FORCE_DISP_TRIP"<?php if ($SETTING['FORCE_DISP_TRIP']=="checked") echo " checked"; ?>>する</div>
<div><b>名前欄に@転載禁止を自動的に追加</b><small class="notice mt5">転載を完全に防止するものではありません。</small></div>
<div><input type="checkbox" value="checked" name="NAME_ARR"<?php if ($SETTING['NAME_ARR']=="checked") echo " checked"; ?>>する</div>
<div><b>認証済ユーザーのみスレッド作成を許可</b></div>
<div><input type="checkbox" value="checked" name="Create_Authentication_required"<?php if ($SETTING['Create_Authentication_required']=="checked") echo " checked"; ?>>する</div>
<div><b>キャップユーザーのみスレッド作成を許可</b></div>
<div><input type="checkbox" value="checked" name="Create_cap_only"<?php if ($SETTING['create_cap_only']=="checked") echo " checked"; ?>>する</div>
<div><b>認証済ユーザーのみ投稿を許可</b></div>
<div><input type="checkbox" value="checked" name="Authentication_required"<?php if ($SETTING['Authentication_required']=="checked") echo " checked"; ?>>する</div>
<div><b>キャップユーザーのみ投稿を許可</b></div>
<div><input type="checkbox" value="checked" name="cap_only"<?php if ($SETTING['cap_only']=="checked") echo " checked"; ?>>する</div>
<div><b>2ch専用ブラウザ</b></div>
<div><input type="radio" name="2ch_dedicate_browsers" value="disable" <?php if ($SETTING['2ch_dedicate_browsers']=="disable") echo "checked"; ?>>無効<input type="radio" name="2ch_dedicate_browsers" value="" <?php if ($SETTING['2ch_dedicate_browsers']=="") echo "checked"; ?>>閲覧のみ有効<input type="radio" name="2ch_dedicate_browsers" value="enable" <?php if ($SETTING['2ch_dedicate_browsers']=="enable") echo "checked"; ?>>閲覧・投稿共に有効</div>
<div><b>過去ログを保持</b></div>
<div><input type="checkbox" value="checked" name="disable_kakolog"<?php if ($SETTING['disable_kakolog']=="checked") echo " checked"; ?>>しない</div>
<div><b>スレッド最大保持数</b></div>
<div><input type="text" value="<?=$SETTING['BBS_THREADS_LIMIT']?>" name="BBS_THREADS_LIMIT"></div>
<div><b>タイムライン最大保持数</b></div>
<div><input type="text" value="<?=$SETTING['LTL_LIMIT']?>" name="LTL_LIMIT"></div>
<div><b>各スレッドのレス数上限</b></div>
<div><input type="text" value="<?=$SETTING['MAX_RES']?>" name="MAX_RES"></div>
<div><b>強制sageまでの秒数</b><small class="notice mt5">無記入で無効化</small></div>
<div><input type="text" value="" name="BBS_FORCE_SAGE"></div>
<div><b>スレッド作成主機能</b></div>
<div><input type="checkbox" value="checked" name="thread_supervisor"<?php if ($SETTING['thread_supervisor']=="checked") echo " checked"; ?>>有効</div>
<div><b>AAを自動検出し、フォントを最適化</b></div>
<div><input type="checkbox" name="aa_check" value="checked"<?php if ($SETTING['aa_check']=="checked") echo " checked"; ?>>する</div>
<div><b>各スレッドでの設定変更コマンド類</b></div>
<div><input type="radio" name="commands" value="checked"<?php if ($SETTING['commands'] == "checked") echo " checked"; ?>>有効<input type="radio" name="commands" value=""<?php if (!$SETTING['commands']) echo " checked"; ?>>無効</div>
<div><b>投稿最大ログ保存件数</b><small class="notice mt5">無記入の場合は上限なし</small></div>
<div><input type="text" value="<?=$SETTING['LOG_LIMIT']?>" name="LOG_LIMIT"></div>
<hr><div class="contents"><input type="submit" name="Submit" class="btn btn-primary btn-block" value="適用"></div>
</form>
</div>
</body>
</html>
<?php exit;

28
test/operate/security.php Normal file
View File

@ -0,0 +1,28 @@
<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if (strlen($_POST['PASS']) > 0) file_put_contents($passfile, password_hash($_POST['PASS'], PASSWORD_DEFAULT));
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content>
<meta name="author" content>
<title>セキュリティ設定</title>
<link rel="stylesheet" href="/static/a.css">
</head>
<body>
<div class="main">
<form method="post" action="/test/admin.php?bbs=<?=$_REQUEST['bbs']?>&mode=security">
<input type="hidden" name="password" value="<?=$_REQUEST['password']?>">
<div class="back"><a href="./admin.php"> 管理ページへ戻る</a></div>
<div><b>パスワード</b><small class="notice mt5">空欄の場合は変更されません</small></div>
<div><input type="text" name="PASS"></div>
<hr><div class="contents"><input type="submit" name="Submit" class="btn btn-primary btn-block" value="適用"></div>
</form>
</div>
</body>
</html>
<?php exit;

View File

@ -0,0 +1,93 @@
<?php
if (!$_GET['mode']) {
?><!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content>
<meta name="author" content>
<title>管理ページ</title>
<link rel="stylesheet" href="/static/a.css">
</head>
<body>
<div id="lists">
<div class="list"><form method="post" action="?bbs=<?=$_REQUEST['bbs']?>&mode=boardsetting"><button class="link-style-btn">掲示板設定</button><input type="hidden" name="password" value="<?=$_REQUEST['password']?>"></form></div>
<div class="list"><form method="post" action="?bbs=<?=$_REQUEST['bbs']?>&mode=header"><button class="link-style-btn">ヘッダー・告知欄</button><input type="hidden" name="password" value="<?=$_REQUEST['password']?>"></form></div>
<div class="list"><form method="post" action="?bbs=<?=$_REQUEST['bbs']?>&mode=authorization"><button class="link-style-btn">承認済ユーザ</button><input type="hidden" name="password" value="<?=$_REQUEST['password']?>"></form></div>
<div class="list"><form method="post" action="?bbs=<?=$_REQUEST['bbs']?>&mode=cap"><button class="link-style-btn">キャップ</button><input type="hidden" name="password" value="<?=$_REQUEST['password']?>"></form></div>
<div class="list"><form method="post" action="?bbs=<?=$_REQUEST['bbs']?>&mode=log"><button class="link-style-btn">投稿ログ閲覧</button><input type="hidden" name="password" value="<?=$_REQUEST['password']?>"></form></div>
<div class="list"><form method="post" action="?bbs=<?=$_REQUEST['bbs']?>&mode=control"><button class="link-style-btn">スレッド・レス管理</button><input type="hidden" name="password" value="<?=$_REQUEST['password']?>"></form></div>
<div class="list"><form method="post" action="?bbs=<?=$_REQUEST['bbs']?>&mode=tl"><button class="link-style-btn">タイムライン管理</button><input type="hidden" name="password" value="<?=$_REQUEST['password']?>"></form></div>
<div class="list"><form method="post" action="?bbs=<?=$_REQUEST['bbs']?>&mode=error"><button class="link-style-btn">エラーログ</button><input type="hidden" name="password" value="<?=$_REQUEST['password']?>"></form></div>
</div>
</body>
</html>
<?php exit;
}elseif ($_GET['mode'] == "boardsetting") {
?><!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content>
<meta name="author" content>
<title>管理ページ</title>
<link rel="stylesheet" href="/static/a.css">
<style>
button.link-style-btn{
cursor: pointer;
border: none;
background: none;
color: #0033cc;
}
button.link-style-btn:hover{
text-decoration: underline;
color: #002080;
}
</style>
</head>
<body>
<div id="lists">
<div class="list"><form method="post" action="?bbs=<?=$_REQUEST['bbs']?>&mode=security"><button class="link-style-btn">セキュリティ</button><input type="hidden" name="password" value="<?=$_REQUEST['password']?>"></form></div>
<div class="list"><form method="post" action="?bbs=<?=$_REQUEST['bbs']?>&mode=main"><button class="link-style-btn">基本設定</button><input type="hidden" name="password" value="<?=$_REQUEST['password']?>"></form></div>
<div class="list"><form method="post" action="?bbs=<?=$_REQUEST['bbs']?>&mode=view"><button class="link-style-btn">表示設定</button><input type="hidden" name="password" value="<?=$_REQUEST['password']?>"></form></div>
<div class="list"><form method="post" action="?bbs=<?=$_REQUEST['bbs']?>&mode=id"><button class="link-style-btn">ID・発信元等表示</button><input type="hidden" name="password" value="<?=$_REQUEST['password']?>"></form></div>
<div class="list"><form method="post" action="?bbs=<?=$_REQUEST['bbs']?>&mode=kisei"><button class="link-style-btn">規制設定</button><input type="hidden" name="password" value="<?=$_REQUEST['password']?>"></form></div>
<div class="list"><form method="post" action="?bbs=<?=$_REQUEST['bbs']?>&mode=kisei2"><button class="link-style-btn">投稿規制</button><input type="hidden" name="password" value="<?=$_REQUEST['password']?>"></form></div>
<div class="list"><form method="post" action="?bbs=<?=$_REQUEST['bbs']?>&mode=kisei3"><button class="link-style-btn">スレッド作成規制</button><input type="hidden" name="password" value="<?=$_REQUEST['password']?>"></form></div>
</div>
</body>
</html>
<?php exit;
}elseif ($_GET['mode'] == "header") {
require './operate/header.php';
}elseif ($_GET['mode'] == "authorization") {
require './operate/authorization.php';
}elseif ($_GET['mode'] == "cap") {
require './operate/cap.php';
}elseif ($_GET['mode'] == "log") {
require './operate/log.php';
}elseif ($_GET['mode'] == "control") {
require './operate/control.php';
}elseif ($_GET['mode'] == "tl") {
require './operate/tl.php';
}elseif ($_GET['mode'] == "security") {
require './operate/security.php';
}elseif ($_GET['mode'] == "view") {
require './operate/view.php';
}elseif ($_GET['mode'] == "main") {
require './operate/main.php';
}elseif ($_GET['mode'] == "kako") {
require './operate/kako.php';
}elseif ($_GET['mode'] == "kisei") {
require './operate/kisei.php';
}elseif ($_GET['mode'] == "id") {
require './operate/id.php';
}elseif ($_GET['mode'] == "kisei2") {
require './operate/kisei2.php';
}elseif ($_GET['mode'] == "kisei3") {
require './operate/kisei3.php';
}elseif ($_GET['mode'] == "error") {
require './operate/error.php';
}

56
test/operate/tl.php Normal file
View File

@ -0,0 +1,56 @@
<?php
$file = "../".$_REQUEST['bbs']."/index.json";
// TLが存在しない場合
if (!is_file($file)) Finish('<b>タイムラインがありません</b>');
// スレッド取得
$LOG = json_decode(file_get_contents($file), true);
if ($_POST['del']) {
if (!$_POST['kakunin']) {
for ($i = 0; $i < count($LOG); $i++) {
if ($_POST[$i] == "checked") {
$LOG[$i] = ["name"=>'',
"mail"=>'',
"date"=>'',
"id"=>'',
"comment"=>$SETTING['DELETED_TEXT'],
];
}
}
file_put_contents($file, json_encode($LOG, JSON_UNESCAPED_UNICODE), LOCK_EX);
$result = "実行しました";
}else $result = "確認画面(削除されるレスにチェックが入っています。宜しければ「実行」をクリック)";
}
?><!DOCTYPE HTML>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>タイムライン管理</title>
<link href="/static/a.css" rel="stylesheet" type="text/css">
<style>
dd {
color: black;
margin-left: 40px;
clear: both;
font-size: 16px;
}
</style>
</head>
<body>
<b><?=$result?></b>
<form class="form-basic" method="POST" accept-charset="UTF-8" action=""><input type="hidden" name="password" value="<?=$_REQUEST['password']?>"><input type="hidden" name="bbs" value="<?=$_REQUEST['bbs']?>"><input type="hidden" name="del" value="true"><div class="contents"><button type="submit" class="btn btn-primary btn-block">実行</button></div>
<?php
$n = $i = 0;
foreach($LOG as $tmp) {
$n++;
if ($_POST['kakunin'] && $_POST[$i] == "checked") $d = ' checked';
else $d = '';
$tmp['name'] = str_replace(array('<b>', '</b>'), "", $tmp['name']);
if ($tmp['title']) echo "スレッドタイトル:".$tmp['title'];
if ($tmp['key']) echo "スレッド番号:".$tmp['key'];
$name=$tmp['name'];$mail=$tmp['mail'];$dateid=$tmp['date']." ".$tmp['id'];$comment=$tmp['comment'];$key=$tmp['thread'];$title=$tmp['title'];
echo "<dt>削除<input type=\"checkbox\" name=\"".$i."\" value=\"checked\"".$d."> ".$n."".$name."[".$mail."]".$dateid."</dt><dd>".$comment."</dd><hr>";
$i++;
}
echo "<div>確認(削除が実行されるレスを確認できます。一括削除用)<input type=\"checkbox\" name=\"kakunin\" value=\"checked\"></div>";
exit('<div class="contents"><button type="submit" class="btn btn-primary btn-block">実行</button></div><div>一度操作を行うと復元できません</div></body></html>');

40
test/operate/view.php Normal file
View File

@ -0,0 +1,40 @@
<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST' && $_POST['edit'] == "yes") {
foreach ($SETTING as $name => $value) {
if (isset($_POST[$name])) $SETTING[$name] = $_POST[$name];
$SET .= $name."=".$SETTING[$name]."\n";
}
file_put_contents($setfile, json_encode($SETTING, JSON_UNESCAPED_UNICODE), LOCK_EX);
file_put_contents($settxt, mb_convert_encoding($SET, "SJIS-win", "UTF-8"), LOCK_EX);
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content>
<meta name="author" content>
<title>表示設定</title>
<link rel="stylesheet" href="/static/a.css">
</head>
<body>
<div class="main">
<form method="post" action="/test/admin.php?bbs=<?=$_REQUEST['bbs']?>&mode=view">
<input type="hidden" name="password" value="<?=$_REQUEST['password']?>">
<input type="hidden" name="edit" value="yes">
<div class="back"><a href="./admin.php"> 管理ページへ戻る</a></div>
<div><b>掲示板タイトル</b></div>
<div><input type="text" name="BBS_TITLE" value="<?=$SETTING['BBS_TITLE']?>"></div>
<div><b>背景</b></div>
<div><input type="text" name="background" value="<?=$SETTING['background']?>"></div>
<div><b>名前未入力時の名前</b><small class="notice mt5">(省略可)</small></div>
<div><input type="text" name="BBS_NONAME_NAME" value="<?=$SETTING['BBS_NONAME_NAME']?>"></div>
<div><b>削除された投稿に表示される内容</b><small class="notice mt5">(省略可)</small></div>
<div><input type="text" name="DELETED_TEXT" value="<?=$SETTING['DELETED_TEXT']?>"></div>
<hr><div class="contents"><input type="submit" name="Submit" class="btn btn-primary btn-block" value="適用"></div>
</form>
</div>
</body>
</html>
<?php exit;

61
test/post-v2.php Normal file
View File

@ -0,0 +1,61 @@
<?php
error_reporting(E_COMPILE_ERROR | E_RECOVERABLE_ERROR | E_ERROR | E_CORE_ERROR | E_PARSE);
ob_start();
header("Accept-CH: Sec-CH-UA-Arch, Sec-CH-UA-Bitness, Sec-CH-UA-Full-Version-List, Sec-CH-UA-Mobile, Sec-CH-UA-Model, Sec-CH-UA-Platform, Sec-CH-UA-Platform-Version");
header('Content-Type: text/html; charset=UTF-8');
if (!isset($_POST['board'])) $_POST['board'] = '';
if (!isset($_POST['thread'])) $_POST['thread'] = '';
if (!isset($_POST['comment'])) $_POST['comment'] = '';
if (!isset($_POST['name'])) $_POST['name'] = '';
if (!isset($_POST['mail'])) $_POST['mail'] = '';
if (!isset($_POST['title'])) $_POST['title'] = '';
$PATH = "../".$_POST['board']."/";
$NOWTIME = time();
// User-AgentにMozilla/5.0を含まない場合は拒否
if (strpos($_SERVER['HTTP_USER_AGENT'], 'Mozilla/5.0') === false) Error2("invalid");
// 投稿先の掲示板設定を取得
$setfile = $PATH."setting.json";
if (!is_file($setfile)) Error2("This board does not exist.");
$SETTING = json_decode(file_get_contents($setfile), true);
require "bbs-main.php";
// 投稿完了画面
function finish() {
global $NOWTIME,$tlonly;
if ($tlonly) header('Location: /'.$_POST['board'].'/');
else header('Location: /#'.$_POST['board'].'/'.$_POST['thread'].'/');
setcookie("response", "success", $NOWTIME+5, "/");
exit;
}
// エラーメッセージ表示用関数
function Error($error) {
global $NOWTIME,$PATH,$HOST,$DATE,$ID,$WrtAgreementKey,$number,$CH_UA,$ACCEPT,$accountid,$LV,$info;
// エラーログに保存
if (is_file($PATH."errors.cgi")) $EROG = file($PATH."errors.cgi");
else $EROG = [];
array_unshift($EROG, $error."<>".$_POST['name']."<>".$_POST['mail']."<>".$DATE." ".$ID."<>".$_POST['comment']."<>".$_POST['title']."<>".$_POST['thread']."<>".$number."<>".$HOST."<>".$_SERVER['REMOTE_ADDR']."<>".$_SERVER['HTTP_USER_AGENT']."<>".$CH_UA."<>".$ACCEPT."<>".$WrtAgreementKey."<>".$LV."<>".$info."\n");
// 500 個以内に調整して保存
while (count($EROG) > 500) array_pop($EROG);
$EROG = array_unique($EROG);
$fp = @fopen($PATH."errors.cgi", "w");
foreach($EROG as $tmp) fputs($fp, $tmp);
fclose($fp);
Header("HTTP/1.0 418 I'm a teapot");
setcookie("response", mb_convert_encoding($error, 'HTML-ENTITIES', 'UTF-8'), $NOWTIME+5, "/");
exit($error);
}
function Error2($error) {
global $NOWTIME;
Header("HTTP/1.0 403 Forbidden");
setcookie("response", mb_convert_encoding($error, 'HTML-ENTITIES', 'UTF-8'), $NOWTIME+5, "/");
exit($error);
}
function makeDir($path) {
return is_dir($path) || mkdir($path, 0777, true);
}

BIN
w6b.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

BIN
y2.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB