mirror of
https://github.com/tznb1/TwoNav.git
synced 2025-08-10 08:51:49 +00:00
v2.0.07-20230405
This commit is contained in:
444
system/UseFew/Import_data.php
Normal file
444
system/UseFew/Import_data.php
Normal file
@@ -0,0 +1,444 @@
|
||||
<?php
|
||||
if(!defined('DIR')){
|
||||
header('HTTP/1.1 404 Not Found');
|
||||
header("status: 404 Not Found");
|
||||
exit;
|
||||
}
|
||||
session_start();
|
||||
$sid = $_POST['page_sid'];
|
||||
if($_GET['type'] == 'upload'){
|
||||
if(empty($sid) || $sid == 'undefined'){
|
||||
msg(1,'page_sid error');
|
||||
}
|
||||
|
||||
$temp_path = $_SESSION['upload_bookmark'][UID][$sid];
|
||||
if(!empty($sid) && !empty($temp_path) && is_file($temp_path)){
|
||||
@unlink($temp_path);
|
||||
}
|
||||
|
||||
//取后缀并判断是否支持
|
||||
$suffix = strtolower(end(explode('.',$_FILES["file"]["name"])));
|
||||
if(!preg_match('/^(db3|html)$/i',$suffix)){
|
||||
@unlink($_FILES["file"]["tmp_name"]);
|
||||
msg(-1,'文件格式不被支持!');
|
||||
}
|
||||
//限制文件大小
|
||||
if(filesize($_FILES["file"]["tmp_name"]) > 10 * 1024 * 1024){
|
||||
msg(-1,'文件大小超限');
|
||||
}
|
||||
//文件临时路径
|
||||
$temp_path = DIR . "/data/temp";
|
||||
//检测目录,不存在则创建!
|
||||
if(!Check_Path($temp_path)){
|
||||
msg(-1,'创建临时目录失败,请检查权限');
|
||||
}
|
||||
//移动文件到临时目录
|
||||
$tmp_name = UID . "_upload_bookmark_" . uniqid() . ".{$suffix}"; //临时文件名
|
||||
if(!move_uploaded_file($_FILES["file"]["tmp_name"],"{$temp_path}/{$tmp_name}")) {
|
||||
msg(-1,'上传失败,请检查目录权限');
|
||||
}else{
|
||||
$_SESSION['upload_bookmark'][UID][$sid] = "{$temp_path}/{$tmp_name}";
|
||||
msg(1,'上传成功'."{$temp_path}/{$tmp_name}");
|
||||
}
|
||||
}elseif($_GET['type'] == 'html'){
|
||||
$temp_path = $_SESSION['upload_bookmark'][UID][$sid];
|
||||
if(empty($temp_path) || !is_file($temp_path)){
|
||||
msg(-1,'文件不存在,请重新上传');
|
||||
}
|
||||
try{
|
||||
$content = file_get_contents($temp_path);
|
||||
}catch(Exception $e) {
|
||||
msg(-1,'读入文件失败');
|
||||
}
|
||||
|
||||
$property = empty($_POST['property']) ? 0 : 1; //私有属性
|
||||
$all = $_POST['all'] == '1' ? true:false; //保留属性(db3)
|
||||
$AutoClass = $_POST['AutoClass']; //自动分类(HTML)
|
||||
if($AutoClass != 1 && empty($_POST['fid'])){
|
||||
msg(-1,'请先选择默认分类在开始导入!');
|
||||
}
|
||||
//如果默认分类为空,则读取默认分类(不存在则创建)
|
||||
if(empty($_POST['fid'])){
|
||||
$fid = get_db('user_categorys','cid',['uid'=>UID,'name'=>'默认分类']);
|
||||
if(empty($fid)){
|
||||
insert_db('user_categorys',[
|
||||
'uid'=>UID,
|
||||
'cid'=>get_maxid('category_id'),
|
||||
'fid'=>0,
|
||||
'pid'=>0,
|
||||
'status'=>1,
|
||||
'property'=>$property,
|
||||
'name'=>'默认分类',
|
||||
'add_time'=>time(),
|
||||
'up_time'=>time(),
|
||||
'weight'=>0,
|
||||
'description'=>'',
|
||||
'font_icon'=>'fa fa-folder',
|
||||
'icon'=>''
|
||||
]);
|
||||
$fid = get_db('user_categorys','cid',['uid'=>UID,'name'=>'默认分类']);
|
||||
if(empty($fid)){
|
||||
msg(-1,'创建默认分类失败');
|
||||
}
|
||||
}
|
||||
}else{
|
||||
$fid = intval($_POST['fid']);
|
||||
}
|
||||
//默认分类
|
||||
$default_category = get_db('user_categorys','name',['uid'=>UID,'cid'=>$fid]);
|
||||
if(empty($default_category)){
|
||||
msg(-1,'获取分类名失败!'.$fid);
|
||||
}
|
||||
|
||||
$data = []; //链接组
|
||||
$categorys = []; //分类信息组(遍历时)
|
||||
$categoryt = []; //分类信息表
|
||||
$fcategorys = []; //上级分类
|
||||
$Hierarchy = 0; //层级
|
||||
$currenttime = time(); //当前时间
|
||||
|
||||
$HTMLs = explode("\n",$content); //按行分割
|
||||
//遍历html
|
||||
foreach( $HTMLs as $HTMLh ){
|
||||
if( $_POST['AutoClass'] == 1 && preg_match("/<DT><H3.*>(.*)<\/H3>/i",$HTMLh,$category) ){
|
||||
//匹配到文件夹名时加入数组
|
||||
$Hierarchy ++;
|
||||
$category[1] = empty($category[1]) ? $default_category : $category[1]; //如果为空则用默认分类(浏览器允许空)
|
||||
array_push($categoryt,$category[1]);
|
||||
array_push($categorys,$category[1]);
|
||||
//层级3等于是二级分类,记录父子关系;
|
||||
if($Hierarchy == 3){
|
||||
$fcategorys[$category[1]] = $categorys[$Hierarchy - 2];
|
||||
}
|
||||
}elseif( preg_match('/<DT><A HREF="(http.+)" ADD_DATE="(\d*)".*>(.+)<\/A>/i',$HTMLh,$urls) ){
|
||||
//匹配标准格式 1.链接 2.添加时间 3.标题
|
||||
$datat['category'] = $categorys[count($categorys) -1];
|
||||
$datat['category'] = empty($datat['category']) ? $default_category : $datat['category'] ;
|
||||
$datat['ADD_DATE'] = $urls[2];
|
||||
$datat['title'] = $urls[3];
|
||||
$datat['url'] = $urls[1];
|
||||
$datat['html'] = $HTMLh;
|
||||
array_push($data,$datat);
|
||||
}elseif( preg_match('/<DT><A HREF="(http.+)">(.+)<\/A>/i',$HTMLh,$urls) ){
|
||||
//匹配精简格式 1.链接 2.标题
|
||||
$datat['category'] = $categorys[count($categorys) -1];
|
||||
$datat['category'] = empty($datat['category']) ? $default_category : $datat['category'] ;
|
||||
$datat['title'] = $urls[2];
|
||||
$datat['url'] = $urls[1];
|
||||
$datat['html'] = $HTMLh;
|
||||
array_push($data,$datat);
|
||||
}elseif( $_POST['AutoClass'] == 1 && preg_match('/<\/DL><p>/i',$HTMLh) ){
|
||||
//匹配到文件夹结束标记时删除一个
|
||||
$Hierarchy --;
|
||||
array_pop($categorys);
|
||||
}
|
||||
}
|
||||
//遍历结束,分类名去重!
|
||||
$categoryt = array_unique($categoryt);
|
||||
//var_dump($categoryt);var_dump($fcategorys);var_dump($data);exit;
|
||||
|
||||
//创建分类
|
||||
$fids = [];
|
||||
foreach( $categoryt as $name ){
|
||||
//读取分类ID
|
||||
$id = get_db('user_categorys','cid',['uid'=>UID,'name'=>$name]);
|
||||
//如果为空则创建
|
||||
if(empty($id)){
|
||||
insert_db('user_categorys',[
|
||||
'uid'=>UID,
|
||||
'cid'=>get_maxid('category_id'),
|
||||
'fid'=>0,
|
||||
'pid'=>0,
|
||||
'status'=>1,
|
||||
'property'=>$property,
|
||||
'name'=>$name,
|
||||
'add_time'=>$currenttime,
|
||||
'up_time'=>$currenttime,
|
||||
'weight'=>0,
|
||||
'description'=>'',
|
||||
'font_icon'=>'fa fa-folder',
|
||||
'icon'=>''
|
||||
]
|
||||
);
|
||||
$id = get_db('user_categorys','cid',['uid'=>UID,'name'=>$name]);
|
||||
if(empty($id)){
|
||||
msg(-1,'意外结束:创建或读取分类信息失败!');
|
||||
}
|
||||
}
|
||||
$fids[$name] = $id;//名称为key,值为id
|
||||
}
|
||||
$fids[$default_category] = $fid; //加入默认分类
|
||||
//var_dump($fcategorys);exit;
|
||||
|
||||
//二级分类处理
|
||||
if($_POST['AutoClass'] == 1 && $_POST['2Class'] == 1){
|
||||
foreach( $fcategorys as $name3 => $name2 ){
|
||||
//读取父分类信息,确定它是父分类,而不是子分类
|
||||
if(get_db('user_categorys','fid',['uid'=>UID,'name'=>$name2]) == 0){
|
||||
update_db('user_categorys',['fid'=>$fids[$name2]],['uid'=>UID,'cid' => $fids[$name3]]); //更新二级分类的父id
|
||||
}
|
||||
}
|
||||
}
|
||||
// 遍历导入链接
|
||||
$fail = 0; $success = 0; $iconcount = 0;$time = $currenttime;
|
||||
//$data = array_reverse($data); //数组倒序(这样导入后链接的顺序和浏览器一样)
|
||||
//表头
|
||||
$res='<table class="layui-table" lay-even><colgroup><col width="200"><col width="250"><col></colgroup><thead><tr><th>标题</th><th>URL</th><th>失败原因</th></tr></thead><tbody>';
|
||||
foreach( $data as $link ){
|
||||
//检查链接xss
|
||||
if(check_xss($link['url'])){
|
||||
$fail++;
|
||||
$res=$res.'<tr><td>'.mb_substr(htmlspecialchars($link['title'],ENT_QUOTES), 0, 30).'</td><td>'.mb_substr(htmlspecialchars($link['url'],ENT_QUOTES), 0, 30).'</td><td>URL存在非法字符</td></tr>';
|
||||
continue;
|
||||
}
|
||||
//检查标题xss
|
||||
if(check_xss($link['title'])){
|
||||
$fail++;
|
||||
$res=$res.'<tr><td>'.mb_substr(htmlspecialchars($link['title'],ENT_QUOTES), 0, 30).'</td><td>'.mb_substr(htmlspecialchars($link['url'],ENT_QUOTES), 0, 30).'</td><td>标题存在非法字符</td></tr>';
|
||||
continue;
|
||||
}
|
||||
// 检测链接是否合法
|
||||
if( !filter_var($link['url'], FILTER_VALIDATE_URL) ) {
|
||||
$fail++;
|
||||
$res=$res.'<tr><td>'.mb_substr(htmlspecialchars($link['title'],ENT_QUOTES), 0, 30).'</td><td>'.mb_substr(htmlspecialchars($link['url'],ENT_QUOTES), 0, 30).'</td><td>链接无效,只支持识别http/https协议的链接!</td></tr>';
|
||||
continue;
|
||||
}
|
||||
// 如果书签时间不合理则使用当前时间!
|
||||
if( $_POST['ADD_DATE'] == 1 ){
|
||||
$time = intval($link['ADD_DATE']);
|
||||
if( $time > $currenttime || $currenttime < 788889600){
|
||||
$time = $currenttime;
|
||||
}
|
||||
}
|
||||
//匹配图片 data:image/png;base64,iVBORw0KGgoAAAANSUhEU
|
||||
$base64_img = '';
|
||||
if ($_POST['icon'] == 1 && preg_match('/ICON="(data:image\/png;base64,(\S+))"/', $link['html'], $result)){
|
||||
$len = GetFileSize($result[2],'b');//取图标大小
|
||||
if($len > 128 && $len < 2048){
|
||||
$iconcount++;
|
||||
$base64_img = $result[1];
|
||||
}
|
||||
}
|
||||
//判断是否存在
|
||||
$id = get_db('user_links','id',['uid'=>UID,'url'=>$link['url'] ]);
|
||||
if(empty($id)){
|
||||
insert_db('user_links',[
|
||||
'uid' => UID,
|
||||
'lid' => get_maxid('link_id'),
|
||||
'fid' => $fids[$link['category']],
|
||||
'add_time' => $time,
|
||||
'up_time' => $time,
|
||||
'weight' => 0,
|
||||
'title' => $link['title'] ,
|
||||
'url' => $link['url'],
|
||||
'property' => $property,
|
||||
'icon' => $base64_img,
|
||||
'status' => 1
|
||||
]);
|
||||
$success++;
|
||||
}else{
|
||||
$res=$res.'<tr><td>'.mb_substr($link['title'], 0, 30).'</td><td>'.mb_substr($link['url'], 0, 40).'</td><td>URL重复'.'</td></tr>';
|
||||
$fail++;
|
||||
}
|
||||
}
|
||||
$data = [
|
||||
'code' => 1,
|
||||
'msg' => '总数:'.count($data).' 成功:'.$success.' 失败:'.$fail.( $_POST['icon'] == 1 ? ' 图标:'.$iconcount:''),
|
||||
'res' => $res.'</tbody></table>',
|
||||
'fail' => $fail
|
||||
];
|
||||
//删除文件和变量
|
||||
unlink($temp_path);
|
||||
unset($_SESSION['upload_bookmark'][UID][$sid]);
|
||||
msgA($data);
|
||||
}elseif($_GET['type'] == 'db3'){
|
||||
if(empty($_POST['source'])){
|
||||
msg(-1,'请选择数据来源');
|
||||
}
|
||||
$tempnam = $_SESSION['upload_bookmark'][UID][$sid];
|
||||
//载入数据库
|
||||
try {
|
||||
$temp_db = new Medoo\Medoo(['type'=>'sqlite','database'=>$tempnam ]);
|
||||
}catch (Exception $e) {
|
||||
unset($_SESSION['upload_bookmark'][UID][$sid]);
|
||||
unlink ($tempnam);
|
||||
msg(-1,'载入数据库失败');
|
||||
}
|
||||
$attr = !empty($_POST['attr']); //保留属性
|
||||
$currenttime = time();
|
||||
//遍历数据库
|
||||
$res='<table class="layui-table" lay-even><colgroup><col width="200"><col width="250"><col></colgroup><thead><tr><th>标题</th><th>URL</th><th>失败原因</th></tr></thead><tbody>';
|
||||
try{
|
||||
//处理分类
|
||||
$fids = [];
|
||||
$categorys = select_data($temp_db,'on_categorys','*','');
|
||||
!empty($categorys) or msg(-1,'未找到分类数据');
|
||||
foreach ($categorys as $category) {
|
||||
//查找本地同名分类
|
||||
$local_id = get_db('user_categorys','cid',['uid'=>UID,'name'=>$category['name']]);
|
||||
//没找到则创建
|
||||
if(empty($local_id)){
|
||||
//处理图标
|
||||
if($_POST['source'] == 1 || $_POST['source'] ==3){
|
||||
$font_icon = strstr($category['font_icon'],'fa fa') ? $category['font_icon'] : 'fa fa-folder' ;
|
||||
}elseif($_POST['source'] == 2){
|
||||
if(strstr($category['Icon'],'fa')){
|
||||
$font_icon = 'fa '.$category['Icon'];
|
||||
}else{
|
||||
$font_icon = 'fa fa-folder';
|
||||
}
|
||||
}
|
||||
$local_id = get_maxid('category_id');
|
||||
insert_db('user_categorys',[
|
||||
'uid'=>UID,
|
||||
'cid'=>$local_id,
|
||||
'fid'=>0,
|
||||
'pid'=>0,
|
||||
'status'=>1,
|
||||
'property'=>$category['property'] ?? 0,
|
||||
'name'=>$category['name'],
|
||||
'add_time'=>$attr ? $category['add_time'] : $currenttime,
|
||||
'up_time'=>$attr ? $category['up_time'] ?? $currenttime : $currenttime,
|
||||
'weight'=>0,
|
||||
'description'=>$link['description']??'',
|
||||
'font_icon'=>$font_icon,
|
||||
'icon'=>''
|
||||
]
|
||||
);
|
||||
}
|
||||
//缓存旧分类ID所对应的新分类ID
|
||||
$fids['id-'.$category['id']] = $local_id;
|
||||
}
|
||||
|
||||
//在遍历一次,处理二级分类
|
||||
foreach ($categorys as $category) {
|
||||
//如果fid为空或为零则跳过
|
||||
if(empty($category['fid'])) continue;
|
||||
//更新分类的父id
|
||||
update_db('user_categorys',['fid'=>$fids['id-'.$category['fid']]],['uid'=>UID,'cid'=>$fids['id-'.$category['id']]]);
|
||||
}
|
||||
|
||||
//处理链接
|
||||
$links = select_data($temp_db,'on_links','*','');
|
||||
!empty($links) or msg(-1,'未找到链接数据');
|
||||
$total = count($links); $fail = 0; $success = 0;
|
||||
//遍历链接
|
||||
foreach($links as $link){
|
||||
//判断父分类是否存在
|
||||
if(empty($fids['id-'.$link['fid']])){
|
||||
$res=$res.'<tr><td>'.mb_substr($link['title'], 0, 30).'</td><td>'.mb_substr($link['url'], 0, 40).'</td><td>父分类不存在'.'</td></tr>';
|
||||
$fail++;
|
||||
continue;
|
||||
}
|
||||
//判断是URL否存在
|
||||
$id = get_db('user_links','id',['uid'=>UID,'url'=>$link['url'] ]);
|
||||
if(empty($id)){
|
||||
//备用链接处理
|
||||
$url_standby = '';
|
||||
if($_POST['source'] == 1 || $_POST['source'] ==2){ //OneNav / Extend
|
||||
if(!empty($link['url_standby'])){
|
||||
$url_standby = [$link['url_standby']]; //转为数组
|
||||
}
|
||||
}elseif($_POST['source'] == 3){ //TwoNav
|
||||
$url_standby = $link['url_standby'];
|
||||
}
|
||||
|
||||
insert_db('user_links',[
|
||||
'uid' => UID,
|
||||
'lid' => get_maxid('link_id'),
|
||||
'fid' => $fids['id-'.$link['fid']],
|
||||
'add_time' => $attr ? $link['add_time'] : $currenttime,
|
||||
'up_time' => $attr ? $link['up_time'] ?? $currenttime: $currenttime,
|
||||
'weight' => 0,
|
||||
'click' => $attr ? $link['click']??0 : 0,
|
||||
'title' => $link['title']??'',
|
||||
'description' => $link['description']??'',
|
||||
'url' => $link['url'],
|
||||
'url_standby' => $url_standby,
|
||||
'property' => $link['property']??0,
|
||||
'icon' => ''
|
||||
]);
|
||||
$success++;
|
||||
}else{
|
||||
$res=$res.'<tr><td>'.mb_substr($link['title'], 0, 30).'</td><td>'.mb_substr($link['url'], 0, 40).'</td><td>URL重复'.'</td></tr>';
|
||||
$fail++;
|
||||
}
|
||||
}
|
||||
$data = [
|
||||
'code' => 1,
|
||||
'msg' => '总数:'.$total.' 成功:'.$success.' 失败:'.$fail,
|
||||
'res' => $res.'</tbody></table>',
|
||||
'fail' => $fail
|
||||
];
|
||||
//删除文件和变量
|
||||
unset($_SESSION['upload_bookmark'][UID][$sid]);
|
||||
unlink($tempnam);
|
||||
msgA($data);
|
||||
}catch (Exception $e) {
|
||||
unset($_SESSION['upload_bookmark'][UID][$sid]);
|
||||
unlink ($tempnam);
|
||||
if(Debug){
|
||||
msgA(['code'=>-1,'msg'=>'数据库操作失败','Message'=>$e->getMessage(),'debug'=>debug_backtrace()]);
|
||||
}else{
|
||||
Amsg(-1,'数据库操作失败');
|
||||
}
|
||||
}
|
||||
msg(-1,'导入失败.');
|
||||
}elseif($_GET['type'] == 'data_empty'){
|
||||
//验证密码
|
||||
global $USER_DB;
|
||||
if(Get_MD5_Password($_POST['pwd'],$USER_DB["RegTime"]) != $USER_DB["Password"]){
|
||||
msg(-1,'密码错误');
|
||||
}
|
||||
//数据库清除
|
||||
if(!empty($_POST['TABLE'])){
|
||||
$TABLE = ["user_categorys","user_links","user_pwd_group","user_share","user_apply"];
|
||||
foreach($_POST['TABLE'] as $key =>$value){
|
||||
if(in_array($key,$TABLE)){
|
||||
delete_db($key,['uid'=>UID]);
|
||||
}
|
||||
}
|
||||
//重置链接ID
|
||||
if($_POST['TABLE']['user_links'] == 'on'){
|
||||
update_db('user_config',['v'=>1],['uid'=>UID,"k" =>'link_id']);
|
||||
}
|
||||
//重置分类ID
|
||||
if($_POST['TABLE']['user_categorys'] == 'on'){
|
||||
update_db('user_config',['v'=>1],['uid'=>UID,"k" =>'category_id']);
|
||||
}
|
||||
//重置加密组ID
|
||||
if($_POST['TABLE']['user_pwd_group'] == 'on'){
|
||||
update_db('user_config',['v'=>1],['uid'=>UID,"k" =>'pwd_group_id']);
|
||||
}
|
||||
//重置收录ID
|
||||
if($_POST['TABLE']['user_apply'] == 'on'){
|
||||
update_db('user_config',['v'=>1],['uid'=>UID,"k" =>'apply_id']);
|
||||
}
|
||||
}
|
||||
|
||||
//文件删除
|
||||
if(!empty($_POST['FILE'])){
|
||||
$FILE = ["MessageBoard","favicon"];
|
||||
foreach($_POST['FILE'] as $key =>$value){
|
||||
$path = DIR.'/data/user/'.U.'/'.$key;
|
||||
if(in_array($key,$FILE) && is_dir($path)){
|
||||
deldir($path);
|
||||
}
|
||||
}
|
||||
}
|
||||
msg(1,'操作成功,请刷新页面!');
|
||||
}
|
||||
|
||||
|
||||
function select_data($db,$table,$columns,$where){
|
||||
try {
|
||||
$re = $db->select($table,$columns,$where);
|
||||
return $re;
|
||||
}catch (Exception $e) {
|
||||
if(Debug){
|
||||
msgA(['code'=>-1,'msg'=>'查询数据库失败','Message'=>$e->getMessage(),'debug'=>debug_backtrace()]);
|
||||
}else{
|
||||
Amsg(-1,'查询数据库失败');
|
||||
}
|
||||
}
|
||||
}
|
||||
18
system/UseFew/demo_up_sys_db_mysql.php
Normal file
18
system/UseFew/demo_up_sys_db_mysql.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php if(!defined('DIR')){header('HTTP/1.1 404 Not Found');header("status: 404 Not Found");exit;}
|
||||
$sql =<<<EOF
|
||||
DROP TABLE IF EXISTS `user_config2`;
|
||||
CREATE TABLE IF NOT EXISTS `user_config2` (
|
||||
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`uid` int(10) UNSIGNED NOT NULL COMMENT '用户ID',
|
||||
`k` varchar(32) NOT NULL COMMENT '键',
|
||||
`v` text NOT NULL COMMENT '值',
|
||||
`t` varchar(32) NOT NULL COMMENT '类型',
|
||||
`d` varchar(32) DEFAULT '' COMMENT '描述',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
|
||||
EOF;
|
||||
if(exe_sql($sql)){
|
||||
insert_db('updatadb_logs',['file_name'=>$file_name,'update_time'=>time(),'status'=>'TRUE','extra'=>'']);
|
||||
}else{
|
||||
msg(-1,'数据库更新失败');
|
||||
}
|
||||
17
system/UseFew/demo_up_sys_db_sqlite.php
Normal file
17
system/UseFew/demo_up_sys_db_sqlite.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php if(!defined('DIR')){header('HTTP/1.1 404 Not Found');header("status: 404 Not Found");exit;}
|
||||
$sql =<<<EOF
|
||||
CREATE TABLE IF NOT EXISTS "user_config2" (
|
||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"uid" integer(10) NOT NULL,
|
||||
"k" text(32) NOT NULL DEFAULT "",
|
||||
"v" text NOT NULL DEFAULT "",
|
||||
"t" text(32) NOT NULL DEFAULT "",
|
||||
"d" TEXT(32) NOT NULL DEFAULT "",
|
||||
CONSTRAINT "id" UNIQUE ("id" ASC)
|
||||
);
|
||||
EOF;
|
||||
if(exe_sql($sql)){
|
||||
insert_db('updatadb_logs',['file_name'=>$file_name,'update_time'=>time(),'status'=>'TRUE','extra'=>'']);
|
||||
}else{
|
||||
msg(-1,'数据库更新失败');
|
||||
}
|
||||
33
system/UseFew/downFile.php
Normal file
33
system/UseFew/downFile.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/**
|
||||
* CURL下载文件 成功返回true,失败返回false
|
||||
*/
|
||||
function downFile($url, $file = '', $savePath = './data/temp/'){
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 60); //超时/秒
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //不直接输出
|
||||
curl_setopt($ch, CURLOPT_HEADER, FALSE); //不需要response header
|
||||
curl_setopt($ch, CURLOPT_NOBODY, FALSE); //需要response body
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); //允许重定向(适应网盘下载)
|
||||
|
||||
try{
|
||||
$res = curl_exec($ch);
|
||||
}finally{
|
||||
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
}
|
||||
|
||||
if ($code == '200') { //状态码正常
|
||||
|
||||
if(empty($file)){ //如果文件名为空
|
||||
$file = date('Ymd_His').'.tmp';
|
||||
}
|
||||
$fullName = rtrim($savePath, '/') . '/' . $file;
|
||||
return file_put_contents($fullName, $res);
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
245
system/UseFew/export_data.php
Normal file
245
system/UseFew/export_data.php
Normal file
@@ -0,0 +1,245 @@
|
||||
<?php
|
||||
if(!defined('DIR')){
|
||||
header('HTTP/1.1 404 Not Found');
|
||||
header("status: 404 Not Found");
|
||||
exit;
|
||||
}
|
||||
|
||||
global $USER_DB;
|
||||
session_start();
|
||||
//请求生成数据,验证密码,成功返回Key
|
||||
if($_GET['type'] == 'create' ){
|
||||
$pwd = Get_MD5_Password($_POST['pwd'],$USER_DB["RegTime"]) === $USER_DB["Password"];
|
||||
if($pwd){
|
||||
$key = md5(uniqid().Get_Rand_Str(8));
|
||||
try {
|
||||
$tempnam = create_data();
|
||||
}catch(Exception $e){
|
||||
if(Debug){
|
||||
msgA(['code'=>-1,'msg'=>'导出失败','Message'=>$e->getMessage(),'debug'=>debug_backtrace()]);
|
||||
}else{
|
||||
msg(-1,'导出失败');
|
||||
}
|
||||
}
|
||||
$_SESSION['download'][$key] = $tempnam;
|
||||
msgA(['code'=>1,'msg'=>'success','key'=>$key,'name'=>$tempnam]);
|
||||
}else{
|
||||
msg(-1,'密码错误');
|
||||
}
|
||||
}
|
||||
|
||||
//验证Key
|
||||
if(!is_file($_SESSION['download'][$_GET['key']])){
|
||||
exit("Key错误,请在后台重新导出!");
|
||||
}else{
|
||||
if($_GET['type'] == 'html' ){
|
||||
header("Cache-Control: public");
|
||||
header("Content-Description: File Transfer");
|
||||
header('Content-disposition: attachment; filename=TwoNav_bookmarks_'.date("Ymd_His").'.html');
|
||||
header("Content-Type: application/octet-stream");
|
||||
header("Content-Transfer-Encoding: binary");
|
||||
header('Content-Length: '. filesize($_SESSION['download'][$_GET['key']]));
|
||||
readfile($_SESSION['download'][$_GET['key']]);
|
||||
unlink ($_SESSION['download'][$_GET['key']]);//删除临时文件
|
||||
unset($_SESSION['download'][$_GET['key']]); //删除Key
|
||||
}
|
||||
|
||||
if($_GET['type'] == 'db3' ){
|
||||
header("Cache-Control: public");
|
||||
header("Content-Description: File Transfer");
|
||||
header('Content-disposition: attachment; filename=TwoNav_bookmarks_'.date("Ymd_His").'.db3'); //文件名
|
||||
header("Content-Type: application/octet-stream");
|
||||
header("Content-Transfer-Encoding: binary"); //告诉浏览器,这是二进制文件
|
||||
header('Content-Length: '. filesize($_SESSION['download'][$_GET['key']])); //告诉浏览器,文件大小
|
||||
readfile($_SESSION['download'][$_GET['key']]);
|
||||
unlink ($_SESSION['download'][$_GET['key']]);//删除临时文件
|
||||
unset($_SESSION['download'][$_GET['key']]); //删除Key
|
||||
}
|
||||
}
|
||||
//生成数据
|
||||
function create_data(){
|
||||
if($_POST['type'] == 'html' ){
|
||||
$tempnam = tempnam(null,'export_html_');
|
||||
$file = fopen($tempnam, "w") or msg(-1,'载入临时文件失败');
|
||||
fwrite($file,base64_decode("PCFET0NUWVBFIE5FVFNDQVBFLUJvb2ttYXJrLWZpbGUtMT4NCjwhLS0gVGhpcyBpcyBhbiBhdXRvbWF0aWNhbGx5IGdlbmVyYXRlZCBmaWxlLg0KICAgICBJdCB3aWxsIGJlIHJlYWQgYW5kIG92ZXJ3cml0dGVuLg0KICAgICBETyBOT1QgRURJVCEgLS0+DQo8TUVUQSBIVFRQLUVRVUlWPSJDb250ZW50LVR5cGUiIENPTlRFTlQ9InRleHQvaHRtbDsgY2hhcnNldD1VVEYtOCI+DQo8VElUTEU+T25lTmF2IEV4dGVuZCBCb29rbWFya3M8L1RJVExFPg0KPEgxPk9uZU5hdiBFeHRlbmQgQm9va21hcmtzPC9IMT4NCjxETD48cD4NCg=="));
|
||||
fwrite($file,' <DT><H3 ADD_DATE="1677783783" LAST_MODIFIED="1677783783" PERSONAL_TOOLBAR_FOLDER="true">书签栏</H3>'."\n");
|
||||
fwrite($file," <DL><p>\n");
|
||||
//获取父分类
|
||||
$category_parent = get_category_parent();
|
||||
foreach ($category_parent as $category) {
|
||||
fwrite($file,' <DT><H3 ADD_DATE="'.$category['add_time'].'" LAST_MODIFIED="'.$category['add_time'].'">'.$category['name']."</H3>\n");
|
||||
fwrite($file," <DL><p>\n");
|
||||
//二级分类
|
||||
$category_subs = get_category_subs($category['id']);
|
||||
foreach ($category_subs as $category_sub) {
|
||||
fwrite($file,' <DT><H3 ADD_DATE="'.$category['add_time'].'" LAST_MODIFIED="'.$category['add_time'].'">'.$category_sub['name']."</H3>\n");
|
||||
fwrite($file," <DL><p>\n");
|
||||
$links = get_links($category_sub['id']);
|
||||
foreach ($links as $link) {
|
||||
fwrite($file,' <DT><A HREF="'.$link["url"].'" ADD_DATE="'.$link["add_time"].'">'.$link["title"].'</A>'."\n");
|
||||
}
|
||||
fwrite($file," </DL><p>\n");
|
||||
}
|
||||
//二级分类End
|
||||
$links = get_links($category['id']);
|
||||
foreach ($links as $link) {
|
||||
fwrite($file,' <DT><A HREF="'.$link["url"].'" ADD_DATE="'.$link["add_time"].'">'.$link["title"].'</A>'."\n");
|
||||
}
|
||||
fwrite($file," </DL><p>\n");
|
||||
}
|
||||
fwrite($file," </DL><p>");
|
||||
fwrite($file,base64_decode("DQo8L0RMPjxwPg0K"));
|
||||
fclose($file);
|
||||
return $tempnam;
|
||||
}
|
||||
|
||||
if($_POST['type'] == 'db3'){
|
||||
$tempnam = tempnam(null,'export_db3_');
|
||||
try { //初始化数据库
|
||||
class MyDB extends SQLite3 {function __construct() {} }
|
||||
$MyDB = new MyDB();
|
||||
$MyDB -> open($tempnam);
|
||||
if(!$MyDB) {
|
||||
msg(-1,'打开SQLite3数据库失败:'.$MyDB->lastErrorMsg());
|
||||
}
|
||||
if(!$MyDB->exec(sql_found_table())){
|
||||
msg(-1,'执行SQL语句失败:'.$MyDB->lastErrorMsg());
|
||||
}
|
||||
$MyDB->close();
|
||||
}catch(Exception $e){
|
||||
msg(-1,'初始化SQLite3失败:'.$e->getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
$temp_db = new Medoo\Medoo(['type'=>'sqlite','database'=>$tempnam ]);
|
||||
}catch (Exception $e) {
|
||||
msg(-1,'载入数据库失败');
|
||||
}
|
||||
//处理分类
|
||||
$categorys = get_category_db3();
|
||||
foreach ($categorys as $key => $data) {
|
||||
//去掉fa 头,适应OneNav Extend
|
||||
$categorys[$key]['Icon'] = str_replace("fa ","",$data['font_icon']);;
|
||||
}
|
||||
//处理分类和链接
|
||||
foreach ($categorys as $category) {
|
||||
//添加分类
|
||||
$temp_db->insert('on_categorys',[
|
||||
'id' => $category['id'],
|
||||
'name' => $category['name'],
|
||||
'fid' => $category['fid'],
|
||||
'add_time' => $category['add_time'],
|
||||
'up_time' => $category['up_time'],
|
||||
'weight' => $category['weight'],
|
||||
'property' => $category['property'],
|
||||
'description'=> $category['description'],
|
||||
'Icon' => $category['Icon'],
|
||||
'font_icon' => $category['font_icon'],
|
||||
]);
|
||||
|
||||
$links = get_links_db3($category['id']);
|
||||
foreach ($links as $link) {
|
||||
$temp_db->insert('on_links',[
|
||||
'id' => $link['lid'],
|
||||
'fid' => $link['fid'],
|
||||
'title' => $link['title'],
|
||||
'url' => $link['url'],
|
||||
'description'=> $link['description'],
|
||||
'add_time' => $link['add_time'],
|
||||
'up_time' => $link['up_time'],
|
||||
'weight' => $link['weight'],
|
||||
'property' => $link['property'],
|
||||
'click' => $link['click'],
|
||||
'topping' => 0,
|
||||
'url_standby' => $link['url_standby'],
|
||||
'iconurl' => $link['icon']
|
||||
]);
|
||||
}
|
||||
}
|
||||
return $tempnam;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function sql_found_table(){
|
||||
return
|
||||
"DROP TABLE IF EXISTS \"on_categorys\";\n".
|
||||
"CREATE TABLE \"on_categorys\" (\n".
|
||||
" \"id\" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,\n".
|
||||
" \"name\" TEXT(32) NOT NULL,\n".
|
||||
" \"add_time\" TEXT(10) NOT NULL,\n".
|
||||
" \"up_time\" TEXT(10) DEFAULT '',\n".
|
||||
" \"weight\" integer(3) NOT NULL DEFAULT 0,\n".
|
||||
" \"property\" integer(1) NOT NULL DEFAULT 0,\n".
|
||||
" \"description\" TEXT(128) DEFAULT '',\n".
|
||||
" \"Icon\" TEXT(128),\n".
|
||||
" \"font_icon\" TEXT(32),\n".
|
||||
" \"fid\" INTEGER NOT NULL DEFAULT 0,\n".
|
||||
" CONSTRAINT \"name\" UNIQUE (\"name\" ASC)\n".
|
||||
");\n".
|
||||
"DROP TABLE IF EXISTS \"on_links\";\n".
|
||||
"CREATE TABLE \"on_links\" (\n".
|
||||
" \"id\" INTEGER NOT NULL,\n".
|
||||
" \"fid\" INTEGER(5) NOT NULL,\n".
|
||||
" \"title\" TEXT(64) NOT NULL,\n".
|
||||
" \"url\" TEXT(256) NOT NULL,\n".
|
||||
" \"description\" TEXT(256),\n".
|
||||
" \"add_time\" TEXT(10) NOT NULL,\n".
|
||||
" \"up_time\" TEXT(10),\n".
|
||||
" \"weight\" integer(3) NOT NULL DEFAULT 0,\n".
|
||||
" \"property\" integer(1) NOT NULL DEFAULT 0,\n".
|
||||
" \"click\" integer NOT NULL DEFAULT 0,\n".
|
||||
" \"topping\" INTEGER NOT NULL DEFAULT 0,\n".
|
||||
" \"url_standby\" TEXT(256),\n".
|
||||
" \"iconurl\" TEXT(256),\n".
|
||||
" \"tagid\" INTEGER DEFAULT 0,\n".
|
||||
" PRIMARY KEY (\"id\"),\n".
|
||||
" CONSTRAINT \"url\" UNIQUE (\"url\" ASC)\n".
|
||||
");";
|
||||
}
|
||||
|
||||
//导出db3
|
||||
function get_category_db3(){
|
||||
$content = ['cid(id)','name','add_time','up_time','weight','property','description','font_icon','fid'];
|
||||
$where['uid'] = UID;
|
||||
$where['status'] = 1;
|
||||
$where['ORDER'] = ['weight'=>'ASC'];
|
||||
return select_db('user_categorys',$content,$where);
|
||||
}
|
||||
function get_links_db3($fid) {
|
||||
$where["uid"] = UID;
|
||||
$where['fid'] = intval($fid);
|
||||
$where['status'] = 1;
|
||||
$where['ORDER'] = ['weight'=>'DESC'];
|
||||
$where['ORDER']['lid'] = 'ASC';
|
||||
$links = select_db('user_links','*',$where);
|
||||
return $links;
|
||||
}
|
||||
|
||||
|
||||
//导出html
|
||||
function get_category_parent(){
|
||||
$content = ['cid(id)','name','add_time'];
|
||||
$where['uid'] = UID;
|
||||
$where['fid'] = 0;
|
||||
$where['status'] = 1;
|
||||
$where['ORDER'] = ['weight'=>'ASC'];
|
||||
return select_db('user_categorys',$content,$where);
|
||||
}
|
||||
function get_category_subs($fid){
|
||||
$content = ['cid(id)','name','add_time'];
|
||||
$where['uid'] = UID;
|
||||
$where['fid'] = $fid;
|
||||
$where['status'] = 1;
|
||||
$where['ORDER'] = ['weight'=>'ASC'];
|
||||
return select_db('user_categorys',$content,$where);
|
||||
}
|
||||
function get_links($fid) {
|
||||
$where["uid"] = UID;
|
||||
$where['fid'] = intval($fid);
|
||||
$where['status'] = 1;
|
||||
$where['ORDER'] = ['weight'=>'DESC'];
|
||||
$where['ORDER']['lid'] = 'ASC';
|
||||
$links = select_db('user_links',['title','url','add_time'],$where);
|
||||
return $links;
|
||||
}
|
||||
347
system/UseFew/local_backup.php
Normal file
347
system/UseFew/local_backup.php
Normal file
@@ -0,0 +1,347 @@
|
||||
<?php
|
||||
if(!defined('DIR')){
|
||||
header('HTTP/1.1 404 Not Found');
|
||||
header("status: 404 Not Found");
|
||||
exit;
|
||||
}else{
|
||||
if(!is_subscribe('bool')){
|
||||
msg(-1,"未检测到有效授权,无法使用该功能!");
|
||||
}
|
||||
|
||||
if($_GET['type'] == 'list'){
|
||||
$backup_dir = DIR."/data/backup/".U."/"; //备份目录
|
||||
$file_list = glob("{$backup_dir}*.info"); //扫描文件
|
||||
$num = count($file_list); //取列表数
|
||||
rsort($file_list,2); //按时间从大到小重排序
|
||||
//备份文件数大于20个时删除旧数据
|
||||
if( $num > 20 ) {
|
||||
for ($i=$num; $i > 20; $i--) {
|
||||
$path = pathinfo($file_list[$i-1]);
|
||||
$path = $path['dirname'] .'/'. $path['filename'];
|
||||
unlink($path.'.info');
|
||||
unlink($path.'.db3');
|
||||
unlink($path.'.tar');
|
||||
array_pop($file_list);
|
||||
}
|
||||
$count = 20;
|
||||
}else{
|
||||
$count = $num;
|
||||
}
|
||||
|
||||
$data = [];
|
||||
//遍历读入备份信息
|
||||
foreach ($file_list as $key => $filePath) {
|
||||
$file = pathinfo($filePath);
|
||||
$info_file = @file_get_contents("{$file['dirname']}/{$file['filename']}.info");
|
||||
$info = json_decode($info_file,true);
|
||||
if($info != false){
|
||||
array_push($data,$info);
|
||||
}
|
||||
}
|
||||
msgA( ['code' => 1,'msg' => '','count' => $count,'data' => $data] );
|
||||
}elseif($_GET['type'] == 'backup'){
|
||||
//初始信息
|
||||
$info['user_dir'] = DIR."/data/user/".U;
|
||||
$info['backup_dir'] = DIR."/data/backup/".U; //备份目录
|
||||
$info['file'] = SysVer . "_".date("ymdHis",time())."_".Get_Rand_Str(5);
|
||||
$info['file_db'] = $info['backup_dir'] .'/'. $info['file'].'.db3';
|
||||
$info['file_info'] = $info['backup_dir'] .'/'. $info['file'].'.info';
|
||||
$info['file_gz'] = $info['backup_dir'] .'/'. $info['file'].'.tar';
|
||||
$info['table_arr'] = ['user_config','user_categorys','user_links','user_pwd_group','user_apply','user_share'];
|
||||
$info['lock'] = DIR.'/data/user/'.U.'/lock.'.UID;
|
||||
if (!extension_loaded('phar')) {
|
||||
msg(-1,'不支持phar扩展');
|
||||
}elseif(!is_dir($info['backup_dir']) && !mkdir($info['backup_dir'],0755,true) ){
|
||||
msg(-1,'创建backup目录失败');
|
||||
}elseif(!is_file($info['lock']) && !file_put_contents($info['lock'],'TwoNav')){
|
||||
msg(-1,'创建lock文件失败');
|
||||
}
|
||||
|
||||
//打包用户文件
|
||||
try {
|
||||
$phar = new PharData($info['file_gz']);
|
||||
$phar->buildFromDirectory($info['user_dir']);
|
||||
} catch (Exception $e) {
|
||||
msg(-1,'打包用户数据发生异常>'.$e->getMessage());
|
||||
}
|
||||
//创建数据
|
||||
try {
|
||||
$MyDB = new Medoo\Medoo(['type'=>'sqlite','database'=>$info['file_db']]);
|
||||
$MyDB->query('CREATE TABLE IF NOT EXISTS "backup" ("id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"name" TEXT,"data" TEXT,CONSTRAINT "id" UNIQUE ("id" ASC));')->fetchAll();
|
||||
$MyDB->insert('backup',['name'=>'ver','data'=>SysVer]); //记系统版本
|
||||
$MyDB->insert('backup',['name'=>'backup_time','data'=>time()]); //记备份时间
|
||||
$MyDB->insert('backup',['name'=>'database_type','data'=>$GLOBALS['db_config']['type']]); //数据库类型
|
||||
}catch (Exception $e) {
|
||||
Amsg(-1,'创建备份数据库失败');
|
||||
}
|
||||
|
||||
//开始备份数据
|
||||
$table_info = [];
|
||||
foreach($info['table_arr'] as $table_name){
|
||||
$count = count_db($table_name,['uid'=>UID]); //总条数
|
||||
$limit = 100; //每页数量
|
||||
$pages= ceil($count/$limit); //总页数
|
||||
//分页逐条处理
|
||||
for ($page=1; $page<=$pages; $page++) {
|
||||
$where['uid'] = UID;
|
||||
$where['LIMIT'] = [($page - 1) * $limit,$limit];
|
||||
$datas = select_db($table_name,'*',$where);
|
||||
foreach($datas as $data){
|
||||
try {
|
||||
if(isset($data['id'])){
|
||||
unset($data['id']);
|
||||
}
|
||||
$MyDB->insert('backup',['name'=>$table_name,'data'=>$data]);
|
||||
}catch (Exception $e) {
|
||||
Amsg(-1,'插入数据时发生异常');
|
||||
}
|
||||
}
|
||||
}
|
||||
$table_info[$table_name] = ['count'=>$count,'pages'=>$pages];
|
||||
}
|
||||
|
||||
//备份信息
|
||||
$info['info'] = [
|
||||
"name" => $info['file'],
|
||||
"db_size" => filesize($info['file_db']),
|
||||
"db_md5" => md5_file($info['file_db']),
|
||||
"tar_size" => filesize($info['file_gz']),
|
||||
"tar_md5" => md5_file($info['file_gz']),
|
||||
"backup_time" => time(),
|
||||
"version" => SysVer,
|
||||
"desc" => "{$_POST['desc']}"
|
||||
];
|
||||
$info['info'] = array_merge($table_info,$info['info']);
|
||||
$info['info'] = json_encode($info['info']);
|
||||
//写到文件
|
||||
if(file_put_contents($info['file_info'], $info['info']) === false){
|
||||
msg(-1,'写备份信息失败');
|
||||
}
|
||||
msg(1,'备份成功');
|
||||
//删除备份
|
||||
}elseif($_GET['type'] == 'del'){
|
||||
$path = DIR."/data/backup/".U."/".$_POST['name'];
|
||||
if( !preg_match_all('/^v\d+\.\d+\.\d+-\d{8}_\d{12}_[A-Za-z0-9]{5}$/',$_POST['name']) ) {
|
||||
msg(-1,'数据库名称不合法');
|
||||
}elseif(!is_file($path.'.info')){
|
||||
msg(-1,'备份不存在');
|
||||
}elseif(!extension_loaded('phar')) {
|
||||
msg(-1,'不支持phar扩展');
|
||||
}
|
||||
try {
|
||||
unlink($path.'.info');
|
||||
unlink($path.'.db3');
|
||||
unlink($path.'.tar');
|
||||
msg(1,'备份数据库已被删除');
|
||||
} catch (\Throwable $th) {
|
||||
msg(-1,"删除失败,请检查目录权限");
|
||||
}
|
||||
//回滚备份
|
||||
}elseif($_GET['type'] == 'restore'){
|
||||
try {
|
||||
global $db;
|
||||
header('Content-Type:application/json; charset=utf-8');
|
||||
//使用事务来处理
|
||||
$db->action(function($db) {
|
||||
//检测是否符合回滚要求
|
||||
$path = DIR."/data/backup/".U."/".$_POST['name'];
|
||||
if( !preg_match_all('/^v\d+\.\d+\.\d+-\d{8}_\d{12}_[A-Za-z0-9]{5}$/',$_POST['name']) ) {
|
||||
msg(-1,'数据库名称不合法');
|
||||
}
|
||||
$info_file = @file_get_contents($path.'.info');
|
||||
$info = json_decode($info_file,true);
|
||||
if($info == false){
|
||||
msg(-1,'读取备份信息失败');
|
||||
}elseif($info['db_md5'] != md5_file($path.'.db3')){
|
||||
msg(-1,'db3文件效验失败');
|
||||
}elseif($info['tar_md5'] != md5_file($path.'.tar')){
|
||||
msg(-1,'tar文件效验失败');
|
||||
}
|
||||
|
||||
//载入数据库
|
||||
try {
|
||||
$MyDB = new Medoo\Medoo(['type'=>'sqlite','database'=>$path.'.db3']);
|
||||
}catch (Exception $e) {
|
||||
msg(-1,'载入备份数据库失败');
|
||||
return false;
|
||||
}
|
||||
|
||||
//遍历删除用户数据
|
||||
$info['table_arr'] = ['user_config','user_categorys','user_links','user_pwd_group','user_apply','user_share'];
|
||||
foreach($info['table_arr'] as $table_name){
|
||||
|
||||
//删除数据
|
||||
delete_db($table_name,['uid'=>UID]);
|
||||
|
||||
//确保数据已删除
|
||||
if($db->has($table_name,['uid'=>UID])){
|
||||
msg(-1,'del ' . $table_name . ' fail');
|
||||
}
|
||||
|
||||
//读取条数,分页逐条导入
|
||||
$count = $MyDB->count('backup',['name'=>$table_name]); //总条数
|
||||
$limit = 100; //每页数量
|
||||
$pages= ceil($count/$limit); //总页数
|
||||
for ($page=1; $page<=$pages; $page++) {
|
||||
$where['name'] = $table_name;
|
||||
$where['LIMIT'] = [($page - 1) * $limit,$limit];
|
||||
$datas = $MyDB->select('backup','data',$where);
|
||||
foreach($datas as $data){
|
||||
$data = unserialize($data);
|
||||
if(isset($data['id'])){
|
||||
unset($data['id']);
|
||||
}
|
||||
$data['uid'] = UID;
|
||||
insert_db($table_name,$data);
|
||||
}
|
||||
}
|
||||
|
||||
//确保数据已导入
|
||||
if($count != count_db($table_name,['uid'=>UID])){
|
||||
msg(-1,'restore ' . $table_name . ' fail');
|
||||
}
|
||||
}
|
||||
|
||||
//删除用户目录
|
||||
$user_dir = DIR."/data/user/".U;
|
||||
if(is_dir($user_dir) && !deldir($user_dir)){
|
||||
msg(-1,'删除用户目录失败');
|
||||
}
|
||||
//创建用户目录
|
||||
if(!is_dir($user_dir) && !mkdir($user_dir,0755,true)){
|
||||
msg(-1,'创建用户目录失败');
|
||||
}
|
||||
//回滚用户目录
|
||||
try {
|
||||
$phar = new PharData($path.'.tar');
|
||||
$phar->extractTo($user_dir, null, true);
|
||||
} catch (Exception $e) {
|
||||
msg(-1,'回滚用户数据失败');
|
||||
}
|
||||
//返回信息,直接msg会导致回滚
|
||||
header('Content-Type:application/json; charset=utf-8');
|
||||
echo(json_encode(['code'=>1,'msg'=>'回滚成功']));
|
||||
});
|
||||
} catch (\Throwable $th) {
|
||||
msg(-1,"回滚失败");
|
||||
}
|
||||
//导出密码验证
|
||||
}elseif($_GET['type'] == 'create'){
|
||||
global $USER_DB;
|
||||
$pwd = Get_MD5_Password($_POST['pwd'],$USER_DB["RegTime"]) === $USER_DB["Password"];
|
||||
if(!$pwd){
|
||||
msg(-1,'密码错误');
|
||||
}elseif(empty($_POST['name'])){
|
||||
msg(-1,'文件名不能为空');
|
||||
}elseif(!extension_loaded('phar')) {
|
||||
msg(-1,'不支持phar扩展');
|
||||
}
|
||||
|
||||
$path = DIR."/data/backup/".U."/".$_POST['name'];
|
||||
if(!is_file($path.'.info')){
|
||||
msg(-1,'info文件不存在');
|
||||
}elseif(!is_file($path.'.db3')){
|
||||
msg(-1,'db3文件不存在');
|
||||
}elseif(!is_file($path.'.tar')){
|
||||
msg(-1,'tar文件不存在');
|
||||
}
|
||||
|
||||
session_start();
|
||||
$key = md5(uniqid().Get_Rand_Str(8));
|
||||
try {
|
||||
$temp_dir = DIR."/data/temp/{$key}";
|
||||
if(!is_dir($temp_dir) && !mkdir($temp_dir,0755,true)){
|
||||
msg(-1,'创建临时目录失败');
|
||||
}
|
||||
copy($path.'.info',"{$temp_dir}/{$_POST['name']}.info");
|
||||
copy($path.'.db3',"{$temp_dir}/{$_POST['name']}.db3");
|
||||
copy($path.'.tar',"{$temp_dir}/{$_POST['name']}.tar");
|
||||
$backup_path = "{$temp_dir}/TwoNav_{$_POST['name']}.tar";
|
||||
$phar = new PharData($backup_path);
|
||||
$phar->buildFromDirectory($temp_dir);
|
||||
$phar->compress(Phar::GZ);
|
||||
$backup_path .= ".gz";
|
||||
if(!is_file($backup_path)){
|
||||
msg(-1,'打包数据失败');
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
msg(-1,'压缩数据异常');
|
||||
}
|
||||
$_SESSION['download'][$key] = $backup_path;
|
||||
msgA(['code'=>1,'msg'=>'success','key'=>$key]);
|
||||
//下载备份数据
|
||||
}elseif($_GET['type'] == 'download'){
|
||||
session_start();
|
||||
if(empty($_GET['key']) || !isset($_SESSION['download'][$_GET['key']])){
|
||||
msg(-1,'Key不存在,请重新导出');
|
||||
}
|
||||
$path = $_SESSION['download'][$_GET['key']];
|
||||
if(!is_file($path)){
|
||||
msg(-1,'文件不存在,请重新导出');
|
||||
}
|
||||
|
||||
$filename = pathinfo($path,PATHINFO_BASENAME);
|
||||
header("Cache-Control: public");
|
||||
header("Content-Description: File Transfer");
|
||||
header('Content-disposition: attachment; filename='.$filename); //文件名
|
||||
header("Content-Type: application/octet-stream");
|
||||
header("Content-Transfer-Encoding: binary"); //告诉浏览器,这是二进制文件
|
||||
header('Content-Length: '. filesize($path)); //告诉浏览器,文件大小
|
||||
readfile($path); //返回文件
|
||||
unlink ($path);//删除临时文件
|
||||
unset($_SESSION['download'][$_GET['key']]); //删除Key
|
||||
deldir(DIR."/data/temp/{$_GET['key']}"); //删除临时目录
|
||||
//导入
|
||||
}elseif($_GET['type'] == 'local_import'){
|
||||
if (!extension_loaded('phar')) {
|
||||
msg(-1,'不支持phar扩展');
|
||||
}
|
||||
$key = md5(uniqid().Get_Rand_Str(8));
|
||||
$temp_dir = DIR."/data/temp/{$key}";
|
||||
if(!is_dir($temp_dir) && !mkdir($temp_dir,0755,true)){
|
||||
msg(-1,'创建临时目录失败');
|
||||
}
|
||||
//解压数据
|
||||
try {
|
||||
copy($_FILES['file']['tmp_name'],"{$temp_dir}/{$_FILES['file']['name']}");
|
||||
$phar = new PharData("{$temp_dir}/{$_FILES['file']['name']}");
|
||||
$phar->extractTo($temp_dir, null, true);
|
||||
unlink("{$temp_dir}/{$_FILES['file']['name']}");
|
||||
} catch (Exception $e) {
|
||||
deldir($temp_dir);
|
||||
msg(-1,'解压数据失败');
|
||||
}
|
||||
//获取备份信息
|
||||
$file = glob("{$temp_dir}/*.info");
|
||||
if(count($file) != 1){
|
||||
deldir($temp_dir);
|
||||
msg(-1,'读取备份信息失败');
|
||||
}
|
||||
$file = pathinfo($file[0]);
|
||||
$info = @file_get_contents("{$temp_dir}/{$file['basename']}");
|
||||
$info = json_decode($info,true);
|
||||
if($info == false){
|
||||
deldir($temp_dir);
|
||||
msg(-1,'解析备份信息失败');
|
||||
}elseif($info['db_md5'] != md5_file("{$temp_dir}/{$info['name']}.db3")){
|
||||
deldir($temp_dir);
|
||||
msg(-1,'db3文件效验失败'.$info['db_md5']);
|
||||
}elseif($info['tar_md5'] != md5_file("{$temp_dir}/{$info['name']}.tar")){
|
||||
deldir($temp_dir);
|
||||
msg(-1,'tar文件效验失败');
|
||||
}
|
||||
//复制到用户数据
|
||||
try {
|
||||
$backup_dir = DIR."/data/backup/".U."/";
|
||||
copy("{$temp_dir}/{$info['name']}.info","{$backup_dir}{$info['name']}.info");
|
||||
copy("{$temp_dir}/{$info['name']}.db3", "{$backup_dir}{$info['name']}.db3");
|
||||
copy("{$temp_dir}/{$info['name']}.tar", "{$backup_dir}{$info['name']}.tar");
|
||||
deldir($temp_dir);
|
||||
msg(1,'导入成功');
|
||||
} catch (Exception $e) {
|
||||
deldir($temp_dir);
|
||||
msg(-1,'复制数据失败,请检查目录权限');
|
||||
}
|
||||
//结束
|
||||
}
|
||||
}
|
||||
182
system/UseFew/root_import_data.php
Normal file
182
system/UseFew/root_import_data.php
Normal file
@@ -0,0 +1,182 @@
|
||||
<?php
|
||||
if(!defined('DIR')){
|
||||
header('HTTP/1.1 404 Not Found');
|
||||
header("status: 404 Not Found");
|
||||
exit;
|
||||
}
|
||||
|
||||
if($_POST['step'] == 1){
|
||||
if(empty($_POST['file'])){
|
||||
msg(-1,'文件名不能为空');
|
||||
}
|
||||
if(!preg_match("/twonav_updata_[0-9a-z]{8}\.tar/",$_POST['file'])){
|
||||
msg(-1,'文件名格式错误,请勿修改导出数据的文件名!');
|
||||
}
|
||||
if(!is_file( "./data/{$_POST['file']}")){
|
||||
msg(-1,'文件不存在');
|
||||
}
|
||||
if($_POST['file'] != "twonav_updata_".hash_file('crc32b',"./data/{$_POST['file']}").".tar"){
|
||||
msg(-1,'文件哈希值效验失败(请勿修改文件名)');
|
||||
}
|
||||
try {
|
||||
$phar = new PharData("./data/{$_POST['file']}");
|
||||
$phar->extractTo("./data/user/", null, true);
|
||||
} catch (Exception $e) {
|
||||
msg(-1,'解压数据异常');
|
||||
}
|
||||
if(!is_file("./data/user/lm.TwoNav.db3")){
|
||||
msg(-1,'解压数据失败,未找到lm.TwoNav.db3');
|
||||
}
|
||||
$MyDB = new Medoo\Medoo(['type'=>'sqlite','database'=>"./data/user/lm.TwoNav.db3"]);
|
||||
$ver = $MyDB->get('backup','data',['name'=>'ver']);
|
||||
|
||||
if(empty($ver)){
|
||||
msg(-1,'获取版本号失败');
|
||||
}
|
||||
|
||||
|
||||
$user_list = $MyDB->select('backup','*',['name'=>'user']);
|
||||
$users = [];
|
||||
foreach ($user_list as $user) {
|
||||
$data = unserialize($user['data']);
|
||||
array_push($users,['id'=>$user['id'],'name'=>$data['User']]);
|
||||
}
|
||||
msgA(['code'=>1,'msg'=>'版本 ' .$ver ,'count'=>count($users),'data'=>$users]);
|
||||
}
|
||||
if($_POST['step'] == 3){
|
||||
$MyDB = new Medoo\Medoo(['type'=>'sqlite','database'=>"./data/user/lm.TwoNav.db3"]);
|
||||
$config = $MyDB->get('backup','data',['name'=>'config']);
|
||||
global $global_config;
|
||||
if(!empty($config)){
|
||||
$config = unserialize($config);
|
||||
|
||||
//保留默认用户
|
||||
if(!empty($config['DUser'])) !has_db('global_user',["User"=>$config['DUser']]) or $global_config['Default_User'] = $config['DUser'];
|
||||
//备案号
|
||||
if(!empty($config['ICP']) && empty($global_config['ICP'])) $global_config['ICP'] = $config['ICP'];
|
||||
//底部代码
|
||||
if(!empty($config['footer']) && empty($global_config['global_footer'])) $global_config['global_footer'] = htmlspecialchars_decode(base64_decode($config['footer']));
|
||||
update_db("global_config", ["v" => $global_config],['k'=>'o_config']);
|
||||
//订阅信息
|
||||
if(!empty($config['s_subscribe']) && !is_subscribe('bool')){
|
||||
write_global_config('s_subscribe',$config['s_subscribe'],'订阅信息');
|
||||
}
|
||||
|
||||
}
|
||||
msg(1, "更新配置");
|
||||
}
|
||||
if($_POST['step'] == 2){
|
||||
$local_user = get_db("global_user", "ID", ["User"=>$_POST['user']]);
|
||||
if(has_db('global_user',["User"=>$_POST['user']])){
|
||||
msg(1, "用户:{$_POST['user']},本地已存在,跳过!");
|
||||
}
|
||||
try {
|
||||
global $db;
|
||||
$db->action(function($db) {
|
||||
$MyDB = new Medoo\Medoo(['type'=>'sqlite','database'=>"./data/user/lm.TwoNav.db3"]);
|
||||
$User = unserialize($MyDB->get('backup','data',['id'=>$_POST['id']]));
|
||||
$LoginConfig = get_db('global_config','v',['k'=>'LoginConfig']);
|
||||
if(has_db('global_user',['Email'=>$User['Email']])){
|
||||
msg(1,"用户:{$_POST['user']},邮箱冲突,跳过!");
|
||||
}
|
||||
insert_db("global_user", [
|
||||
"FID"=>0,
|
||||
"User"=>$User['User'],
|
||||
"Password"=>$User['Pass'],
|
||||
"UserGroup"=>$User['Level'] == 999 ? 'root':'default',
|
||||
"Email"=>$User['Email'],
|
||||
"Token"=>'',
|
||||
"SecretKey"=>'',
|
||||
"RegIP"=>$User['RegIP'],
|
||||
"RegTime"=>$User['RegTime'],
|
||||
"Login"=>$User['Login'],
|
||||
"LoginConfig"=>$LoginConfig
|
||||
]);
|
||||
$USER_DB['ID'] = get_db('global_user','ID',['User'=>$User['User']]);
|
||||
if(empty($USER_DB['ID'])){
|
||||
msg(1, "用户:{$_POST['user']},导入失败-1");
|
||||
}
|
||||
$time = time();
|
||||
|
||||
//遍历需要的配置
|
||||
$configs = [];
|
||||
foreach( $MyDB->select('backup','data',['name'=>"{$User['User']}_on_config"]) as $config){
|
||||
$config = unserialize($config);
|
||||
if(in_array($config ['name'],['title','subtitle','logo','keywords','description'])){
|
||||
$configs[$config ['name']] = $config ['value'];
|
||||
}
|
||||
}
|
||||
//保留部分站点配置
|
||||
$s_site = unserialize(get_db('global_config','v',['k'=>'s_site']));
|
||||
foreach($s_site as $key => $data){
|
||||
$s_site[$key] = empty($configs[$key]) ? $s_site[$key] : $configs[$key];
|
||||
}
|
||||
|
||||
insert_db("user_config", ["uid"=>$USER_DB['ID'],"k" =>"s_site","v"=>$s_site,"d"=>'站点配置','t'=>'config']);
|
||||
insert_db("user_config", ["uid"=>$USER_DB['ID'],"k"=>"s_templates","v"=>get_db('global_config','v',['k'=>'s_templates']),"t"=>"config","d"=>'默认模板']);
|
||||
|
||||
|
||||
//导入用户分类
|
||||
$categorys = $MyDB->select('backup','data',['name'=>"{$User['User']}_on_categorys"]);
|
||||
foreach ($categorys as $data){
|
||||
$data = unserialize($data);
|
||||
insert_db('user_categorys',[
|
||||
'uid'=>$USER_DB['ID'],
|
||||
'cid'=>$data['id'],
|
||||
'fid'=>$data['fid'] ?? 0,
|
||||
'pid'=>0,
|
||||
'status'=>1,
|
||||
'property'=>$data['property']??'0',
|
||||
'name'=>htmlspecialchars($data['name'],ENT_QUOTES),
|
||||
'add_time'=>$data['add_time'] ?? time(),
|
||||
'up_time'=>$data['up_time'] ?? time(),
|
||||
'weight'=>0,
|
||||
'description'=>htmlspecialchars($data['description'],ENT_QUOTES),
|
||||
'font_icon'=> strstr($data['Icon'],'fa') ? 'fa '.$data['Icon'] : 'fa fa-folder',
|
||||
'icon'=>''
|
||||
]
|
||||
);
|
||||
}
|
||||
//导入用户链接
|
||||
$inks = $MyDB->select('backup','data',['name'=>"{$User['User']}_on_links"]);
|
||||
foreach ($inks as $data){
|
||||
$data = unserialize($data);
|
||||
insert_db('user_links',[
|
||||
'uid' => $USER_DB['ID'],
|
||||
'lid' => $data['id'],
|
||||
'fid' => $data['fid'],
|
||||
'pid' => 0,
|
||||
'title' => $data['title'],
|
||||
'url' => $data['url'],
|
||||
'url_standby' => empty($data['url_standby']) ? '': [$data['url_standby']] ,
|
||||
'description' => $data['description'],
|
||||
'add_time' => $data['add_time'] ?? time(),
|
||||
'up_time' => $data['up_time'] ?? time(),
|
||||
'click' => $data['click'] ?? 0,
|
||||
'weight' => 0,
|
||||
'status' => 1,
|
||||
'property' => $data['property'] ?? 0,
|
||||
'icon' => $data['iconurl'] ?? ''
|
||||
]);
|
||||
}
|
||||
|
||||
//写初始ID
|
||||
$link_id = intval(max_db('user_links','lid',['uid'=>$USER_DB['ID']])) +1;
|
||||
insert_db("user_config", ["uid"=>$USER_DB['ID'],"k"=>"link_id","v"=>$link_id,"t"=>"max_id","d"=>'链接ID']);
|
||||
$category_id = intval(max_db('user_categorys','cid',['uid'=>$USER_DB['ID']])) +1;
|
||||
insert_db("user_config", ["uid"=>$USER_DB['ID'],"k"=>"category_id","v"=>$category_id,"t"=>"max_id","d"=>'分类ID']);
|
||||
insert_db("user_config", ["uid"=>$USER_DB['ID'],"k"=>"pwd_group_id","v"=>1,"t"=>"max_id","d"=>'加密组ID']);
|
||||
});
|
||||
}catch(\Throwable $e) {
|
||||
if(Debug){
|
||||
msgA(['code'=>-1,'msg'=>"导入用户数据失败,用户名:{$_POST['user']}",'Message'=>$e->getMessage(),'debug'=>debug_backtrace()]);
|
||||
}else{
|
||||
msg(-1,"导入用户数据失败,用户名:{$_POST['user']}");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
sleep(0.5);
|
||||
msg(1, "用户:{$_POST['user']},数据导入成功!");
|
||||
}
|
||||
Reference in New Issue
Block a user