OneBot: Leantime 改造版源码(BOM/Univer 表格/AI 接管/品牌替换等)
This commit is contained in:
67
dev/library.php
Normal file
67
dev/library.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/**
|
||||
* 2D/3D 数模库 - 元数据接口(首页库表用)
|
||||
* GET 无参 → 返回 library.json 的全部记录(静态 JSON 也行,这里统一走接口)
|
||||
* POST {"records":[...]} → 清洗后整体保存(客户端把编辑后的数组传回)
|
||||
*
|
||||
* 只允许本站页面调用(Sec-Fetch-Site 优先、Referer 兜底,与 api/token.php 同一策略)。
|
||||
* 注意这只是防顺手篡改的弱校验:库表只存名称/备注等元数据,不含文件内容。
|
||||
*/
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
header('Cache-Control: no-store');
|
||||
|
||||
$fetchSite = $_SERVER['HTTP_SEC_FETCH_SITE'] ?? '';
|
||||
$referer = $_SERVER['HTTP_REFERER'] ?? '';
|
||||
$host = $_SERVER['HTTP_HOST'] ?? '';
|
||||
if ($fetchSite !== '') {
|
||||
if ($fetchSite !== 'same-origin' && $fetchSite !== 'same-site') json_out(403, ['error' => 'forbidden']);
|
||||
} elseif (!$host || strpos($referer, $host) === false) {
|
||||
json_out(403, ['error' => 'forbidden']);
|
||||
}
|
||||
|
||||
function json_out($code, $obj) {
|
||||
http_response_code($code);
|
||||
echo json_encode($obj, JSON_UNESCAPED_UNICODE);
|
||||
exit;
|
||||
}
|
||||
|
||||
$file = __DIR__ . '/library.json';
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
||||
if (is_file($file)) { readfile($file); exit; }
|
||||
json_out(200, ['records' => []]);
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') json_out(405, ['error' => 'method not allowed']);
|
||||
|
||||
$in = json_decode((string)file_get_contents('php://input'), true);
|
||||
if (!is_array($in) || !isset($in['records']) || !is_array($in['records'])) {
|
||||
json_out(400, ['error' => 'bad body']);
|
||||
}
|
||||
|
||||
// 清洗:path 是链接核心(拒绝 ..、限制字符与长度),name/note 纯文本截断
|
||||
$records = [];
|
||||
$seen = [];
|
||||
foreach ($in['records'] as $r) {
|
||||
if (!is_array($r)) continue;
|
||||
$path = is_string($r['path'] ?? null) ? trim($r['path']) : '';
|
||||
$name = is_string($r['name'] ?? null) ? trim($r['name']) : '';
|
||||
$note = is_string($r['note'] ?? null) ? trim($r['note']) : '';
|
||||
$type = ($r['type'] ?? '') === '2d' ? '2d' : '3d';
|
||||
if ($path === '' || strpos($path, '..') !== false || strlen($path) > 300) continue;
|
||||
if (!preg_match('/^[\x20-\x7e\x{4e00}-\x{9fff}\/\\\\]+$/u', $path)) continue;
|
||||
if (isset($seen[$path])) continue;
|
||||
$seen[$path] = true;
|
||||
$records[] = [
|
||||
'path' => $path,
|
||||
'name' => mb_substr($name, 0, 100),
|
||||
'type' => $type,
|
||||
'note' => mb_substr($note, 0, 200),
|
||||
'time' => is_numeric($r['time'] ?? null) ? (int)$r['time'] : time(),
|
||||
];
|
||||
}
|
||||
|
||||
// 带锁写文件,防止两个查看器上传时并发写坏
|
||||
$json = json_encode(['records' => $records], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
if (file_put_contents($file, $json, LOCK_EX) === false) json_out(500, ['error' => 'write failed']);
|
||||
json_out(200, ['ok' => true, 'count' => count($records)]);
|
||||
Reference in New Issue
Block a user