<?php

declare(strict_types=1);

$nosession = true;
$nosecu = true;
include("./includes/common.php");

function showresult(array $arr): never
{
	$format = isset($_POST['format']) && is_string($_POST['format']) ? $_POST['format'] : 'json';
	if ($format === 'json') {
		header('Content-Type: application/json; charset=UTF-8');
		exit(json_encode($arr, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
	}

	if ($format === 'jsonp') {
		$callback = isset($_POST['callback']) && is_string($_POST['callback']) ? $_POST['callback'] : 'callback';
		if (!preg_match('/^[a-zA-Z_][a-zA-Z0-9_]*$/', $callback)) {
			$callback = 'callback';
		}

		header('Content-Type: application/javascript; charset=UTF-8');
		exit($callback . '(' . json_encode($arr, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . ')');
	}

	header('Content-Type: text/html; charset=UTF-8');
	if ($arr['code'] == 0) {
		$backurl = isset($_POST['backurl']) && is_string($_POST['backurl']) ? $_POST['backurl'] : ($_SERVER['HTTP_REFERER'] ?? $siteurl);
		if (!is_string($backurl) || $backurl === '') {
			$backurl = $siteurl;
		}

echo '<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8"/>
<meta name="viewport" content="width=device-width">
<title>文件上传页面</title>
</head>
<body>
<form action="'.$backurl.'" method="post">
<input name="file" type="hidden" value="'.$arr['downurl'].'" />
<input name="type" type="hidden" value="'.$arr['type'].'" />
<input name="name" type="hidden" value="'.$arr['name'].'" />
<input name="submit" type="submit" value="下一步" />
</form>
</body></html>';
		exit;
	}

	sysmsg($arr['msg']);
}

if(!$conf['api_open'])showresult(['code'=>-4, 'msg'=>'当前站点未开启上传API']);

if($conf['forcelogin'] == 1 && !$islogin2)showresult(['code'=>-1, 'msg'=>'请先登录后上传']);

// 支持API密钥认证
$api_key = $_POST['api_key'] ?? $_GET['api_key'] ?? '';
if(!empty($api_key)) {
    $api_user = $DB->getRow("SELECT * FROM pre_user WHERE api_key=:api_key AND enable=1 LIMIT 1", [':api_key'=>$api_key]);
    if($api_user) {
        $islogin2 = true;
        $uid = $api_user['uid'];
        $userrow = $api_user;
    }
}

if(!empty($conf['api_referer'])){
	$referers = array_values(array_filter(array_map('trim', explode('|', (string) $conf['api_referer']))));
	$refererRaw = $_SERVER['HTTP_REFERER'] ?? '';
	$url_arr = $refererRaw !== '' ? parse_url($refererRaw) : false;
	$host = is_array($url_arr) && isset($url_arr['host']) ? strtolower((string) $url_arr['host']) : null;
	$allowed = array_map(static fn (string $h): string => strtolower($h), $referers);
	if ($host === null || !in_array($host, $allowed, true)) {
		showresult(['code'=>-4, 'msg'=>'来源地址不正确']);
	}
}


if(!isset($_FILES['file']))showresult(['code'=>-1, 'msg'=>'请选择文件']);
$name=trim(htmlspecialchars($_FILES['file']['name']));
$size=intval($_FILES['file']['size']);
$hide = $_POST['show']==1?0:1;
$ispwd = intval($_POST['ispwd']);
$pwd = $ispwd==1?trim(htmlspecialchars((string) ($_POST['pwd'] ?? ''))):null;
$folder_id = isset($_POST['folder_id']) ? intval($_POST['folder_id']) : 0;
if($folder_id < 0) $folder_id = 0;
if($folder_id > 0){
	if(!$islogin2) showresult(['code'=>-1, 'msg'=>'请登录后选择文件夹']);
	$folderRow = $DB->getRow("SELECT folder_id FROM pre_folder WHERE folder_id=:fid AND uid=:uid LIMIT 1", [':fid'=>$folder_id, ':uid'=>$uid]);
	if(!$folderRow) showresult(['code'=>-1, 'msg'=>'目标文件夹不存在或无权限']);
}
$name = str_replace(['/','\\',':','*','"','<','>','|','?'],'',$name);
if(empty($name))showresult(['code'=>-1, 'msg'=>'文件名不能为空']);
if($ispwd==1 && !empty($pwd)){
	if (!preg_match('/^[a-zA-Z0-9]+$/', $pwd)) {
		showresult(['code'=>-1, 'msg'=>'文件密码只能为字母和数字']);
	}
}
$pwdHash = $ispwd === 1 && $pwd !== null && $pwd !== '' ? password_hash($pwd, PASSWORD_DEFAULT) : null;
$ext=get_file_ext($name);
if($conf['type_block']){
	$type_block = explode('|',$conf['type_block']);
	if(in_array($ext,$type_block)){
		showresult(['code'=>-1, 'msg'=>'文件上传失败', 'error'=>'block']);
	}
}
if($conf['name_block']){
	$name_block = explode('|',$conf['name_block']);
	foreach($name_block as $row){
		if(strpos($name,$row)!==false){
			showresult(['code'=>-1, 'msg'=>'文件上传失败', 'error'=>'block']);
		}
	}
}
// 存储配额检查
if($islogin2) {
	$quota = check_user_quota($userrow);
	if($quota['code'] !== 0) {
		showresult(['code'=>-1, 'msg'=>$quota['msg']]);
	}
	if ($userrow['storage_limit'] > 0 && ($userrow['storage_used'] + $size) > ($userrow['storage_limit'] * 1024 * 1024)) {
		showresult(['code'=>-1, 'msg'=>'存储空间不足，无法上传该文件']);
	}
}

$hash = md5_file($_FILES['file']['tmp_name']);
$row = $DB->getRow("SELECT * FROM pre_file WHERE hash=:hash", [':hash'=>$hash]);
if($row){
	unset($_SESSION['csrf_token']);
	$downurl = $siteurl.'down.php?hash='.$row['hash'];
	$result = ['code'=>0, 'msg'=>'本站已存在该文件', 'exists'=>1, 'hash'=>$hash, 'name'=>$name, 'size'=>$size, 'type'=>$ext, 'id'=>$row['id'], 'downurl'=>$downurl];
	if(is_view($row['type']))$result['viewurl'] = $siteurl.'view.php?hash='.$hash.'.'.$row['type'];
	showresult($result);
}
$result = $stor->upload($hash, $_FILES['file']['tmp_name'], minetype($ext));
if(!$result)showresult(['code'=>-1, 'msg'=>'文件上传失败', 'error'=>'stor']);
$guest_token = (!$islogin2) ? get_guest_token() : null;
$sds = $DB->exec("INSERT INTO `pre_file` (`name`,`type`,`size`,`hash`,`addtime`,`ip`,`hide`,`pwd`,`uid`,`folder_id`,`guest_token`) values (:name,:type,:size,:hash,NOW(),:ip,:hide,:pwd,:uid,:folder_id,:guest_token)", [':name'=>$name, ':type'=>$ext, ':size'=>$size, ':hash'=>$hash, ':ip'=>$clientip, ':hide'=>$hide, ':pwd'=>$pwdHash, ':uid'=>($uid?$uid:0), ':folder_id'=>$folder_id, ':guest_token'=>$guest_token]);
if(!$sds)showresult(['code'=>-1, 'msg'=>'上传失败'.$DB->error(), 'error'=>'database']);
$id = $DB->lastInsertId();

if($uid > 0){
	$DB->exec("UPDATE pre_user SET storage_used=storage_used+:size WHERE uid=:uid", [':size'=>$size, ':uid'=>$uid]);
}

$type_image = explode('|',$conf['type_image']);
$type_video = explode('|',$conf['type_video']);
if($conf['green_check']>0 && in_array($ext,$type_image)){
	if(checkImage($hash, $ext)){
		$DB->exec("UPDATE `pre_file` SET `block`=1 WHERE `id`=:id LIMIT 1", [':id' => $id]);
	}
}
if($conf['videoreview']==1 && in_array($ext,$type_video)){
	$DB->exec("UPDATE `pre_file` SET `block`=2 WHERE `id`=:id LIMIT 1", [':id' => $id]);
}

$downurl = $siteurl.'down.php?hash='.$hash;
$result = ['code'=>0, 'msg'=>'文件上传成功！', 'exists'=>0, 'hash'=>$hash, 'name'=>$name, 'size'=>$size, 'type'=>$ext, 'id'=>$id, 'downurl'=>$downurl];
if(is_view($ext))$result['viewurl'] = $siteurl.'view.php?hash='.$hash.'.'.$ext;
showresult($result);
