This commit is contained in:
2024-11-05 12:10:06 +08:00
commit 6b687feee2
3995 changed files with 418583 additions and 0 deletions
+80
View File
@@ -0,0 +1,80 @@
<?php
namespace app\controller;
use support\Request;
use yzh52521\EasyHttp\Response;
use yzh52521\EasyHttp\RequestException;
use yzh52521\EasyHttp\Http;
use support\Db;
use Webman\Captcha\CaptchaBuilder;
class Account
{
public function login(Request $request)
{
$session = $request->session();
$user=$session->get('user',null);
if($user!=null){
return redirect('/my');
}
return view('login');
}
public function logout(Request $request)
{
$session = $request->session();
$session->delete('user');
$session->delete('realname');
return redirect('/');
}
public function my(Request $request)
{
$session = $request->session();
$user=$session->get('user',null);
$realname=$session->get('realname',null);
if($user==null||$realname==null){
return redirect('/');
}
$record=Db::table('links')->where('user', "$user")->get();
print_r($record);
return view('my', ['user' => $user,'realname' => $realname,'record' => $record]);
}
public function captcha(Request $request)
{
// 初始化验证码类
$builder = new CaptchaBuilder;
// 生成验证码
$builder->build();
// 将验证码的值存储到session中
$request->session()->set('captcha', strtolower($builder->getPhrase()));
// 获得验证码图片二进制数据
$img_content = $builder->get();
// 输出验证码二进制数据
return response($img_content, 200, ['Content-Type' => 'image/jpeg']);
}
public function loginapi(Request $request)
{
$session = $request->session();
$username = $request->input('username');
$password = $request->input('password');
$captcha = $request->input('captcha');
$captcha_session = $request->session()->get('captcha');
if(strtolower($captcha) != $captcha_session){
return json(['code' => 400, 'msg' => '验证码错误']);
}
if($username == null || $password == null){
return json(['code' => 400, 'msg' => '用户名或密码不能为空']);
}
if(strlen($username)>=36){
return json(['code' => 400, 'msg' => '用户名格式错误']);
}
$username=Db::table('users')->where('username', "$username")->where('password',"$password")->value('username');
if($username==null){
return json(['code' => 400, 'msg' => '用户名或密码错误']);
}else{
$session->set('user', $username);
$session->set('realname', Db::table('users')->where('username', "$username")->value('realname'));
return json(['code' => 200, 'msg' => '登陆成功']);
}
}
}
+32
View File
@@ -0,0 +1,32 @@
<?php
namespace app\controller;
use support\Request;
class IndexController
{
public function index(Request $request)
{
$session = $request->session();
$user=$session->get('user',null);
$realname=$session->get('realname',null);
if($user==null||$realname==null){
$display='none';
}else{
$display='block';
}
return view('index', ['user' => $user,'realname' => $realname,'display' => $display]);
}
public function view(Request $request)
{
return view('index/view', ['name' => 'webman']);
}
public function json(Request $request)
{
return json(['code' => 0, 'msg' => 'ok']);
}
}
+107
View File
@@ -0,0 +1,107 @@
<?php
namespace app\controller;
use support\Request;
use yzh52521\EasyHttp\Response;
use yzh52521\EasyHttp\RequestException;
use yzh52521\EasyHttp\Http;
use support\Db;
class Server
{
public function short(Request $request)
{
$session = $request->session();
$url = $request->input('url',null);
$link = $request->input('link',null);
$type = $request->input('type','false');
if($link==null && Db::table('links')->where('source', "$url")->where('type',0)->exists() ){
$link=Db::table('links')->where('source', "$url")->where('type',0)->value('link');
return json(['code' => 200, 'msg' => 'success','link'=>'https://SPQR.top/'.$link]);
}
$user=$session->get('user',null);
if($user==null&&($type!='false'||$link!=null)){
return json(['code' => 505, 'msg' => '302直链和自定义链接后缀需要登陆后才可使用']);
}
$realname=$session->get('realname',null);
#$domain=parse_url($url)['host'];
$domain=$url;
$response = Http::post('https://api.uutool.cn/beian/icp/', ['site' => "$domain"])->json();
if(isset($response->data->is_icp)){
if($response->data->is_icp==1){
$icp=$response->data;
$owner=$icp->icp_org;
$webid=$icp->icp_no;
}else{
$icp=null;
if($user==null){
$owner='anonymous';
}else{
$owner=$realname;
}
$webid=null;
}
}else{
return json(['code' => 405, 'msg' => '备案查询接口响应异常,请稍后重试']);
}
if($icp==null&&($user==null||$type!='false')){
return json(['code' => 502, 'msg' => '该域名未备案,需要登陆后才可缩短,且不支持302直链']);
}
if($link==null){
for($i=4;$i>0;$i++){
$link=substr(md5($url).rand(0,pow(10,$i)),0,$i);
if(Db::table('links')->where('link', "$link")->exists()){
continue;
}else{
break;
}
}
}else{
if(Db::table('links')->where('link', "$link")->exists()){
return json(['code' => 408, 'msg' => '自定义链接已存在']);
}
}
if($user==null){
$user='anonymous';
}
if($type=='false'){
$type=0;
}elseif($type=='true'){
$type=1;
}
$data=[
'link'=>$link,
'source'=>$url,
'owner'=>$owner,
'webid'=>$webid,
'user'=>$user,
'type'=>$type,
'time'=>time()
];
Db::table('links')->insert($data);
return json(['code' => 200, 'msg' => 'success','link'=>'https://SPQR.top/'.$link]);
}
public function view(Request $request,$link)
{
$source=Db::table('links')->where('link', "$link")->first();
if($source==null){
return redirect('/');
}
if($source->type==0){
if($source->webid==null){
$ba='block';
}else{
$ba='none';
}
return view('jump', ['source' => $source,'ba'=>$ba]);
}elseif($source->type==1){
return redirect($source->source);
}
}
}
+4
View File
@@ -0,0 +1,4 @@
<?php
/**
* Here is your custom functions.
*/
+42
View File
@@ -0,0 +1,42 @@
<?php
/**
* This file is part of webman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace app\middleware;
use Webman\MiddlewareInterface;
use Webman\Http\Response;
use Webman\Http\Request;
/**
* Class StaticFile
* @package app\middleware
*/
class StaticFile implements MiddlewareInterface
{
public function process(Request $request, callable $next): Response
{
// Access to files beginning with. Is prohibited
if (strpos($request->path(), '/.') !== false) {
return response('<h1>403 forbidden</h1>', 403);
}
/** @var Response $response */
$response = $next($request);
// Add cross domain HTTP header
/*$response->withHeaders([
'Access-Control-Allow-Origin' => '*',
'Access-Control-Allow-Credentials' => 'true',
]);*/
return $response;
}
}
+29
View File
@@ -0,0 +1,29 @@
<?php
namespace app\model;
use support\Model;
class Test extends Model
{
/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'test';
/**
* The primary key associated with the table.
*
* @var string
*/
protected $primaryKey = 'id';
/**
* Indicates if the model should be timestamped.
*
* @var bool
*/
public $timestamps = false;
}
+232
View File
@@ -0,0 +1,232 @@
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href='normalize.css' rel='stylesheet' type='text/css'>
<link href="https://fonts.laysense.com/css/5000/zh-cn/harmonyossans/harmonyossans.css" rel="preload" as="style" onload="this.rel='stylesheet'">
<link id="theme_css" rel="stylesheet" href="sakura.css">
<style>
.pmnet { font-family: DOUYUFont;}
html {font-family: HarmonyOSSans;}
.animbox {
margin: 50px auto;
width: 200px;
text-align: center;
}
/*设置各竖条的共有样式*/
.animbox > div {
background-color: #279fcf;
width: 4px;
height: 35px;
border-radius: 2px;
margin: 2px;
animation-fill-mode: both;
display: inline-block;
animation: anim 0.9s 0s infinite cubic-bezier(.11, .49, .38, .78);
}
/*设置动画延迟*/
.animbox > :nth-child(2), .animbox > :nth-child(4) {
animation-delay: 0.25s !important;
}
.animbox > :nth-child(1), .animbox > :nth-child(5) {
animation-delay: 0.5s !important;
}
/*定义动画*/
@keyframes anim {
0% { transform: scaley(1); }
80% { transform: scaley(0.3); }
90% { transform: scaley(1); }
}
/* 开关 - 滑块周围的框 */
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
}
/* 隐藏默认 HTML 复选框 */
.switch input {
opacity: 0;
width: 0;
height: 0;
}
/* 滑块 */
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #2fbc47;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked + .slider {
background-color: #2196F3;
}
input:focus + .slider {
box-shadow: 0 0 1px #2196F3;
}
input:checked + .slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
/* 圆形滑块 */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
</style>
<title>SPQR短链接服务-罗马元老院与罗马人民SPQR.TOP</title>
<meta name="keywords" content="短链接,短网址,链接缩短,网址缩短,SPQR,罗马元老院,元老院">
<meta name="description" content="SPQR.top提供免费的短链接、网址缩短服务,SPQR是罗马元老院与罗马人民的缩写">
</head>
<body>
<script>
//切换深色模式
if(window.matchMedia('(prefers-color-scheme: dark)').matches){
document.getElementById('theme_css').href = 'sakura-dark.css';
}
</script>
<main>
<h1>SPQR.top 免费短链接服务 </h1><hr />
<p>可以将很长的网址链接缩短成以SPQR.top开头弘扬罗马元老院与人民精神的短链接。</p>
<a href="//laysense.cn" target="_blank_laysense">由[<span class="pmnet">来笙</span>]维护</a>
<blockquote>
SPQR.top 代表 SPQR(罗马元老院与人民) 宇宙第一
<br />
SPQR是拉丁语Senatus Populusque Romanus(罗马元老院与罗马人民)的缩写
<br />
<img src="https://wallpapercave.com/wp/wp2471066.jpg" alt="SPQR" style=" max-height: 200px;">
<br />
<span style="color: coral;">严禁将本服务用于违法目的。</span>
</blockquote>
<blockquote>
登陆后,您可以使用自定义短链接后缀,以及302直链功能。<br />
未备案的域名必须登陆后才能缩短,且不支持302直链<br />
<?php if($user==null){
echo '<span><a href="/!/login" target="_blank_login">[登陆]</a></span>';
}else{
echo '<span>你好,'.$realname.'。<a href="/!/my" target="_blank_login">[查看我缩短的域名]</a><a href="/!/logout">[登出]</a></span>';
}
?>
</blockquote>
<section>
<h4>缩短一个网址</h4>
<hr />
<form action="new_apply.php" method="POST">
<p style="display: <?=htmlspecialchars($display)?>;">JS跳转 <label class="switch">
<input id="type" type="checkbox" name="type">
<span class="slider round"></span>
</label> 302直链[需登录]
</p>
<p>
<label for="name">需要缩短的网址链接</label>
<input required="required" name="url" id="url" placeholder="https://baidu.cn/" type="url" style="width:80%">
</p>
<p style="display: <?=htmlspecialchars($display)?>;">
<label for="password">自定义短链接后缀[需登录,留空则由系统生成]</label>
https://SPQR.top/<input name="link" id="link" type="text" style="width:30%">
</p>
<div id="load" class="animbox" style="display: none;">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<p style="color: blueviolet;" id="notice"></p>
<p style="color: skyblue;" id="notice2"></p>
</form>
<p>
<button onclick="short()" value="缩短网址" style="width:50%">缩短网址</button>
<br />
点击缩短代表您同意并接受<a href="https://www.pmnet.gq/PMNETTOS" target="_blank_tos">TOS</a>
</p>
</section>
</main>
<footer>
<hr/>
©<a href="https://laysense.cn">laysense.cn</a> 2024 Made with <a href="https://oxal.org/projects/sakura">sakura.css</a>
</footer>
<script src="jquery-3.6.3.min.js"></script>
<script>
function short(){
var url = $("#url").val();
var link = $("#link").val();
var type = $("#type").prop('checked');
$.ajax({
type: "POST",
url: '/!/short',
data: {'url':url,'link':link,'type':type},
async: true,
dataType: 'json',
cache: false,
beforeSend: function () {
$('#notice2').html('');
$('#notice').html('正在进行缩短');
$('#load').show();
},
success: function (data) {
if (data.code == 200) {
$('#notice').html(`短链接为<a href="javascript:copyToClipboard('`+data.link+`')">`+data.link+'</a>,点击复制');
} else {
$('#notice').html(data.msg);
}
$('#load').hide();
},
clearForm: true,
resetForm: false
});
}
async function copyToClipboard(text) {
try {
await navigator.clipboard.writeText(text);
$('#notice2').html('复制成功');
} catch (err) {
$('#notice2').html('复制失败', err);
}
}
</script>
</body>
</html>
+93
View File
@@ -0,0 +1,93 @@
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>正在跳转|SPQR.top 短网址跳转服务</title>
<!-- 引入Bootstrap CDN -->
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
<style>
/* 内联CSS样式 */
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
/**background: linear-gradient(270deg, #ff9a9e, #fad0c4);**/
background-image: url('https://cdn-dynmedia-1.microsoft.com/is/image/microsoftcorp/305616-skucards-backgroundfullbleed-1600x1132?resMode=sharp2&op_usm=1.5,0.65,15,0&wid=2000&hei=1415&qlt=100&fmt=png-alpha&fit=constrain');
background-size: 400% 400%;
animation: gradient 15s ease infinite;
}
@keyframes gradient {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
.card {
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
border-radius: 10px;
}
.btn-primary {
background-color: #007bff;
border: none;
}
.btn-primary:hover {
background-color: #0056b3;
}
.btn-error {
background-color: #ff3700;
border: none;
}
.btn-error:hover {
background-color: #b70404;
}
.loader {
border: 4px solid #f3f3f3;
border-radius: 50%;
border-top: 4px solid #3498db;
width: 48px;
height: 48px;
animation: spin 2s linear infinite;
margin: 0 auto 15px auto;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>
</head>
<body>
<div class="card text-center">
<div class="card-body">
<img src="https://wallpapercave.com/wp/wp2471066.jpg" style="max-width: 168px;"/>
<h2 class="card-title" id="title">正在前往目标站点</h2>
<p class="card-text"><a href="//spqr.top" target="_blank">SPQR.top</a> 提供网址链接缩短服务。</p>
<p class="card-text">目标网站由 <span><?php echo($source->owner); ?></span> 提供 <br />
我们不对其内容的真实性和合法性负责。
</p>
<p class="card-text" style="display: <?php echo($ba);?>;">⚠️该网站未备案,可能存在违规内容,请谨慎访问!⚠️</p>
<div id="loader" class="loader"></div>
<a id="msg" class="btn "></a>
</div>
</div>
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.7.1.js" ></script>
<script type="text/javascript">
let min = 2000;
let max = 6000;
let randomIntInRange = Math.floor(Math.random() * (max - min + 1)) + min;
setTimeout(function(){
var goto='<?php echo $source->source; ?>';
$("#msg").attr("href", goto);
$("#msg").html('若您的浏览器没有反应,请点击此处');
$("#msg").addClass("btn-primary");
$("#msg").show();
window.location.href=goto;
}, randomIntInRange);
</script>
</body>
</html>
+71
View File
@@ -0,0 +1,71 @@
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>登录 SPQR.top</title>
<link href='normalize.css' rel='stylesheet' type='text/css'>
<link href="https://fonts.laysense.com/css/5000/zh-cn/harmonyossans/harmonyossans.css" rel="preload" as="style" onload="this.rel='stylesheet'">
<link id="theme_css" rel="stylesheet" href="/sakura.css"></head>
<body>
<script>
//切换深色模式
if(window.matchMedia('(prefers-color-scheme: dark)').matches){
document.getElementById('theme_css').href = '/sakura-dark.css';
}
</script>
<div class="login-container">
<h2>登录 SPQR.top</h2>
<form action="/login" method="post">
<label for="username">用户名:</label>
<input type="text" id="username" name="username" required>
<label for="password">密码:</label>
<input type="password" id="password" name="password" required>
<label for="captcha">验证码:</label>
<img src="/!/captcha" alt="Captcha Image" id="captcha-image" onclick="change()"><br />
<input type="text" id="captcha" name="captcha" required>
<br />
<button type="submit">登入</button>
</form>
<hr />
<a href="/">[返回首页]</a>
</div>
</body>
</html>
<script src="/jquery-3.6.3.min.js"></script>
<script>
function change() {
document.getElementById('captcha-image').src = '/!/captcha?' + Math.random();
}
$(document).ready(function() {
$('form').on('submit', function(event) {
event.preventDefault();
var formData = {
username: $('#username').val(),
password: $('#password').val(),
captcha: $('#captcha').val()
};
$.ajax({
type: 'POST',
url: '/!/loginapi',
data: JSON.stringify(formData),
contentType: 'application/json',
success: function(response) {
if(response.code == 200) {
window.location.href = '/my';
} else {
alert('登陆失败:'+response.msg);
change();
}
},
error: function(error) {
alert('登陆失败:接口错误');
change();
}
});
});
});
</script>
+66
View File
@@ -0,0 +1,66 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Short Links</title>
<link id="theme_css" rel="stylesheet" href="/sakura.css"></head>
<link href="https://cdn.bootcdn.net/ajax/libs/datatables/1.10.21/css/jquery.dataTables.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/datatables/1.10.21/js/jquery.dataTables.min.js"></script>
</head>
<body>
<script>
//切换深色模式
if(window.matchMedia('(prefers-color-scheme: dark)').matches){
document.getElementById('theme_css').href = '/sakura-dark.css';
}
</script>
<h1>当前的短链接</h1>
<p>用户名:<?=htmlspecialchars($user)?> <?=htmlspecialchars($realname)?><a href="/logout">[登出]</a> <a href="/">[回到首页]</a></p>
<hr />
<table id="shortLinksTable" class="display" style="width: 100%; table-layout: fixed; word-break: break-all;color:black">
<thead>
<tr>
<th>短链接</th>
<th>原始域名</th>
<th>备案号/负责人</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<style>
.sourcelink {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width: 200px;
}
</style>
<?php
foreach($record as $rec){
echo '<tr>';
echo '<td>SPQR.top/'.$rec->link.'</td>';
echo '<td class="sourcelink">'.$rec->source .'</td>';
if($rec->webid == null) {
echo '<td>未备案</td>';
} else {
echo '<td>' . $rec->webid . '<br />'.$rec->owner.'</td>';
}
echo '<td><a style="color: red;" href="/!/delete/'. $rec->link . '">[删除]</a></td>';
echo '</tr>';
}
?>
</tbody>
</table>
<script>
$(document).ready(function() {
$('#shortLinksTable').DataTable();
});
</script>
</body>
</html>