复查修复(二): 同步模块与安全遗留

- 修复 remove_sync_source 引入的 stop_sync KeyError 回归(容错 get)
- stop_sync 不再删除存活线程条目(防双 worker);FTP 子目录递归传真名(不再 KeyError)
- 远程文件名统一 _safe_remote_name 校验(FTP/SFTP/HTTP 防路径穿越)
- temp 任务名加随机后缀防碰撞;temp 状态/线程完成后清理(防 sync_state.json 膨胀)
- save_sync_state 快照+原子写(临时文件+os.replace),持锁调用不死锁
- URL 打印脱敏(user:pass@ -> ***@)
- _need_sync_http size=0 不再全量重下(仅按存在性)
- cron 同一分钟去重;PyPI 进度只更新当前源
- v2 start_sync 不再把 bool 当 task_id
- UserRecord.to_dict 脱敏(不返回 password_hash/token),新增 to_dict_private/get_user_with_password
- config_hotreload 单配置源(set+persist 与热重载一致);server.py 用 get_all()
- 会话创建时顺带清理过期项;JSON stats/历史读改写加锁
- 解压目标目录先校验;FTP RETR 命令注入防护;rsync --delete 目标保护
- git/urlopen 补超时;cleanup_completed_tasks 删旧留新
This commit is contained in:
HYC Fixer
2026-09-02 00:39:12 +08:00
parent fc72759a92
commit 82875b710a
10 changed files with 957 additions and 810 deletions
+13 -8
View File
@@ -12,6 +12,7 @@ import mimetypes
import base64
import hashlib
import shutil
import threading
from datetime import datetime
from http.server import BaseHTTPRequestHandler
from urllib.parse import unquote, urlparse, parse_qs
@@ -40,6 +41,7 @@ class MirrorServerHandler(BaseHTTPRequestHandler):
debug_log_file = None # 调试日志文件路径
_debug_categories = set() # 启用的调试类别
_mirror_handlers = {} # 镜像处理器实例缓存
_stats_lock = threading.Lock() # 保护 JSON 统计/历史文件读改写
@classmethod
def _setup_debug(cls, config):
@@ -1421,10 +1423,11 @@ class MirrorServerHandler(BaseHTTPRequestHandler):
except Exception as e:
print(f"Error updating download count in database: {e}")
# 回退到 JSON 文件
stats = self.load_stats()
stats[filepath] = stats.get(filepath, 0) + 1
self.save_stats(stats)
# 回退到 JSON 文件(加锁防并发读改写丢计数)
with self._stats_lock:
stats = self.load_stats()
stats[filepath] = stats.get(filepath, 0) + 1
self.save_stats(stats)
# ==================== 下载历史记录 ====================
@@ -1501,8 +1504,9 @@ class MirrorServerHandler(BaseHTTPRequestHandler):
except Exception as e:
print(f"Error logging download to database: {e}")
# 回退到 JSON 文件
history = self.load_download_history(1000)
# 回退到 JSON 文件(加锁防并发写坏/丢记录)
with self._stats_lock:
history = self.load_download_history(1000)
entry = {
'timestamp': datetime.now().isoformat(),
@@ -1513,5 +1517,6 @@ class MirrorServerHandler(BaseHTTPRequestHandler):
'method': self.command if hasattr(self, 'command') else 'GET'
}
history.append(entry)
self.save_download_history(history)
with self._stats_lock:
history.append(entry)
self.save_download_history(history)