Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ A modern, feature-rich desktop application for managing and organizing your book
- 📥 **Import/Export**: Support for Chrome, Firefox, HTML, and JSON formats
- 🎲 **Blind Box**: Random bookmark discovery feature
- 📚 **History Tracking**: Keep track of accessed bookmarks
- 🔒 **Password Protection**: Secure your bookmarks with password authentication
- 🔒 **Edit Lock Mode**: Prevent accidental modifications
- 🌍 **Multi-language**: Support for Chinese, English, Japanese, German, French, Korean, and Spanish
- 💾 **Auto-backup**: Automatic data backup and restore
Expand Down Expand Up @@ -60,11 +61,16 @@ A modern, feature-rich desktop application for managing and organizing your book

### Basic Operations

1. Adding Bookmarks : Click the "Add" button or drag URLs from your browser
2. Creating Folders : Right-click in the sidebar to create new folders
3. Searching : Use Ctrl+F or click the search icon
4. Import/Export : Access through the File menu
For detailed instructions, see the User Guide .
1. **Adding Bookmarks**: Click the "Add" button or drag URLs from your browser
2. **Creating Folders**: Right-click in the sidebar to create new folders
3. **Searching**: Use Ctrl+F or click the search icon
4. **Import/Export**: Access through the File menu
5. **Password Protection**: Set up password protection in Settings → Password Settings
- Enable password protection and set your password
- Configure security questions for password recovery
- Password will be required on next startup
Comment on lines 63 to +71

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Consider adding a space after the colon in each list item for better readability.

Suggested change
1. Adding Bookmarks : Click the "Add" button or drag URLs from your browser
2. Creating Folders : Right-click in the sidebar to create new folders
3. Searching : Use Ctrl+F or click the search icon
4. Import/Export : Access through the File menu
For detailed instructions, see the User Guide .
1. **Adding Bookmarks**: Click the "Add" button or drag URLs from your browser
2. **Creating Folders**: Right-click in the sidebar to create new folders
3. **Searching**: Use Ctrl+F or click the search icon
4. **Import/Export**: Access through the File menu
5. **Password Protection**: Set up password protection in Settings → Password Settings
- Enable password protection and set your password
- Configure security questions for password recovery
- Password will be required on next startup
1. **Adding Bookmarks**: Click the "Add" button or drag URLs from your browser
2. **Creating Folders**: Right-click in the sidebar to create new folders
3. **Searching**: Use Ctrl+F or click the search icon
4. **Import/Export**: Access through the File menu
5. **Password Protection**: Set up password protection in Settings → Password Settings
- Enable password protection and set your password
- Configure security questions for password recovery
- Password will be required on next startup


For detailed instructions, see the User Guide.

## 🛠️ Development

Expand Down
20 changes: 13 additions & 7 deletions README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
- 📥 **导入/导出**:支持 Chrome、Firefox、HTML 和 JSON 格式
- 🎲 **盲盒功能**:随机书签发现功能
- 📚 **历史记录**:跟踪访问过的书签
- 🔒 **密码保护**:使用密码验证保护您的书签安全
- 🔒 **编辑锁定模式**:防止意外修改
- 🌍 **多语言支持**:支持中文、英文、日文、德文、法文、韩文和西班牙文
- 💾 **自动备份**:自动数据备份和恢复
Expand Down Expand Up @@ -60,12 +61,17 @@

### 基本操作

1. 添加书签 :点击"添加"按钮或从浏览器拖拽 URL
2. 创建文件夹 :在侧边栏右键点击创建新文件夹
3. 搜索 :使用 Ctrl+F 或点击搜索图标
4. 导入/导出 :通过文件菜单访问
5. 开魔盒:也叫开盲盒,通过点击右上角的圆形魔盒按钮打开。可直接选择数字(1-5)或输入数字(>5)随机浏览。
详细说明请参阅 用户指南 。
1. **添加书签**:点击"添加"按钮或从浏览器拖拽 URL
2. **创建文件夹**:在侧边栏右键点击创建新文件夹
3. **搜索**:使用 Ctrl+F 或点击搜索图标
4. **导入/导出**:通过文件菜单访问
5. **密码保护**:在设置 → 密码设置中配置密码保护
- 启用密码保护并设置密码
- 配置密保问题用于密码恢复
- 下次启动时将需要输入密码
6. **开魔盒**:也叫开盲盒,通过点击右上角的圆形魔盒按钮打开。可直接选择数字(1-5)或输入数字(>5)随机浏览。
Comment on lines 63 to +72

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Consider adding a space after the colon in each list item for better readability.

Suggested change
1. 添加书签 :点击"添加"按钮或从浏览器拖拽 URL
2. 创建文件夹 :在侧边栏右键点击创建新文件夹
3. 搜索 :使用 Ctrl+F 或点击搜索图标
4. 导入/导出 :通过文件菜单访问
5. 开魔盒:也叫开盲盒,通过点击右上角的圆形魔盒按钮打开。可直接选择数字(1-5)或输入数字(>5)随机浏览。
详细说明请参阅 用户指南 。
1. **添加书签**:点击"添加"按钮或从浏览器拖拽 URL
2. **创建文件夹**:在侧边栏右键点击创建新文件夹
3. **搜索**:使用 Ctrl+F 或点击搜索图标
4. **导入/导出**:通过文件菜单访问
5. **密码保护**:在设置 → 密码设置中配置密码保护
- 启用密码保护并设置密码
- 配置密保问题用于密码恢复
- 下次启动时将需要输入密码
6. **开魔盒**:也叫开盲盒,通过点击右上角的圆形魔盒按钮打开。可直接选择数字(1-5)或输入数字(>5)随机浏览。
1. **添加书签**:点击"添加"按钮或从浏览器拖拽 URL
2. **创建文件夹**:在侧边栏右键点击创建新文件夹
3. **搜索**:使用 Ctrl+F 或点击搜索图标
4. **导入/导出**:通过文件菜单访问
5. **密码保护**:在设置 → 密码设置中配置密码保护
- 启用密码保护并设置密码
- 配置密保问题用于密码恢复
- 下次启动时将需要输入密码
6. **开魔盒**:也叫开盲盒,通过点击右上角的圆形魔盒按钮打开。可直接选择数字(1-5)或输入数字(>5)随机浏览。


详细说明请参阅 用户指南。

## 🛠️ 开发

Expand Down Expand Up @@ -108,7 +114,7 @@ url-navigator/

### 下载体验版

[URL Navigator单EXE体验版](https://github.com/yihufree/URL-Navigator/releases/download/V0.60/URLNav_20250611.zip)
[URL Navigator单EXE体验版](https://github.com/yihufree/URL-Navigator/releases/download/V0.51/URLNav_20250611v0.51.zip)

## 🌐 国际化

Expand Down
76 changes: 76 additions & 0 deletions build.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import sys
import shutil
import subprocess
import platform
import datetime

def build_exe():
"""构建EXE文件"""
print("开始构建EXE文件...")

# 清理旧的构建文件
if os.path.exists("build"):
shutil.rmtree("build")
if os.path.exists("dist"):
shutil.rmtree("dist")

# 确保资源文件夹存在
if not os.path.exists("resources"):
print("错误: 资源文件夹不存在!")
return

# 获取版本日期
version_date = datetime.datetime.now().strftime("%Y%m%d")
output_filename = f"URLNav_{version_date}"

# 构建命令
cmd = [
"pyinstaller",
f"--name={output_filename}",
"--windowed", # 无控制台窗口
"--onefile", # 单个EXE文件
"--clean", # 清理临时文件
"--icon=resources/icons/app_icon.ico", # 应用图标
"--add-data=resources;resources", # 添加整个资源目录
"--add-data=languages;languages", # 添加语言文件目录
"--noconfirm", # 不显示确认对话框
"main.py" # 主程序入口
]

# 根据操作系统调整路径分隔符
if platform.system() != "Windows":
# 对于Unix系统使用冒号分隔符
for i in range(len(cmd)):
if "--add-data=" in cmd[i]:
cmd[i] = cmd[i].replace(";", ":")

print(f"运行命令: {' '.join(cmd)}")

# 执行构建
try:
subprocess.call(cmd, shell=False) # 明确禁用shell以防止命令注入

# 检查是否成功创建EXE文件
exe_path = os.path.join("dist", f"{output_filename}.exe")
if os.path.exists(exe_path):
print(f"构建成功!EXE文件大小: {os.path.getsize(exe_path) / (1024*1024):.2f} MB")
print(f"EXE文件位置: {os.path.abspath(exe_path)}")
else:
print("构建似乎完成,但找不到EXE文件")

except Exception as e:
print(f"构建过程中出错: {e}")
return

def resource_path(relative_path):
"""获取资源文件的绝对路径,兼容开发环境和打包后环境"""
if hasattr(sys, '_MEIPASS'):
return os.path.join(sys._MEIPASS, relative_path)
return os.path.join(os.path.abspath("."), relative_path)

if __name__ == "__main__":
build_exe()
33 changes: 33 additions & 0 deletions check_password_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
检查密码设置状态
"""

from PyQt5.QtCore import QSettings

def main():
settings = QSettings("URL Navigator", "URL Navigator")

# 检查各项设置
password_enabled = settings.value("security/password_enabled", False)
password_hash = settings.value("security/password_hash", "")
password_salt = settings.value("security/password_salt", "")
security_question = settings.value("security/security_question", "")

print(f"密码保护启用: {password_enabled}")
print(f"密码哈希: {'存在' if password_hash else '不存在'}")
print(f"密码盐值: {'存在' if password_salt else '不存在'}")
print(f"密保问题: {security_question if security_question else '未设置'}")

# 如果启用了密码保护但没有密码数据,说明有问题
if password_enabled and (not password_hash or not password_salt):
print("\n问题: 密码保护已启用但密码数据缺失!")
print("建议: 运行 reset_password_protection.py 重置设置")
elif password_enabled:
print("\n状态: 密码保护正常")
else:
print("\n状态: 密码保护未启用")

if __name__ == "__main__":
main()
86 changes: 86 additions & 0 deletions fix_password_issue.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
URLNav 密码问题快速修复工具

这个工具用于解决首次启动时要求输入密码但不知道密码的问题。
"""

import sys
import os
from PyQt5.QtCore import QSettings
from PyQt5.QtWidgets import QApplication, QMessageBox

def clear_all_password_settings():
"""清除所有密码相关设置"""
try:
# 尝试不同的组织名和应用名组合
settings_combinations = [
("URL Navigator", "URL Navigator"),
("URLNav", "URLNav"),
("", "URLNav"),
("", "URL Navigator")
]

cleared_any = False

for org, app in settings_combinations:
settings = QSettings(org, app)

# 检查是否有密码相关设置
keys_to_check = [
"security/password_enabled",
"security/password_hash",
"security/password_salt",
"security/security_question",
"security/security_answer_hash",
"security/security_answer_salt"
]

has_settings = any(settings.contains(key) for key in keys_to_check)

if has_settings:
print(f"发现密码设置在: 组织='{org}', 应用='{app}'")

# 清除所有密码相关设置
for key in keys_to_check:
if settings.contains(key):
settings.remove(key)
print(f" 已清除: {key}")

settings.sync()
cleared_any = True

return cleared_any

except Exception as e:
print(f"清除设置时出错: {e}")
return False

def main():
print("URLNav 密码问题快速修复工具")
print("=" * 40)

# 创建临时应用(不显示界面)
app = QApplication(sys.argv) if not QApplication.instance() else QApplication.instance()

print("正在检查和清除密码设置...")

if clear_all_password_settings():
print("\n✅ 已成功清除所有密码设置")
print("\n现在您可以正常启动 URLNav 应用程序了。")
print("如果需要重新设置密码保护,请在应用程序的设置中进行配置。")
else:
print("\n❓ 未找到任何密码设置")
print("\n如果仍然遇到密码提示问题,可能的原因:")
print("1. 配置文件位置不同")
print("2. 应用程序代码中有其他问题")
print("\n建议联系开发者获取进一步帮助。")

print("\n修复工具执行完成。")

# 不需要显示GUI,直接退出
sys.exit(0)

if __name__ == "__main__":
main()
53 changes: 53 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
import json
from logging.handlers import RotatingFileHandler
from threading import Lock
from utils.password_manager import PasswordManager
from ui.password_dialogs import PasswordInputDialog

# 配置日志
def setup_logging():
Expand Down Expand Up @@ -54,6 +56,52 @@ def setup_logging():

logger = logging.getLogger(__name__)

def verify_password():
"""验证密码"""
try:
password_manager = PasswordManager()

# 如果未启用密码保护,直接返回True
if not password_manager.is_password_enabled():
logger.info("密码保护未启用,跳过验证")
return True

logger.info("密码保护已启用,需要验证密码")

# 创建临时应用程序实例用于显示对话框
temp_app = None
if not QApplication.instance():
temp_app = QApplication(sys.argv)

# 显示密码输入对话框
from utils.language_manager import language_manager
dialog = PasswordInputDialog(
parent=None,
language_manager=language_manager,
password_manager=password_manager
)

# 执行对话框
result = dialog.exec_()

# 清理临时应用程序
if temp_app:
temp_app.quit()

if result == QDialog.Accepted:
logger.info("密码验证成功")
return True
else:
logger.info("用户取消密码验证")
return False

except Exception as e:
logger.error(f"密码验证过程中发生错误: {e}")
import traceback
traceback.print_exc()
Comment on lines +100 to +101

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Consider using logging.exception instead of logging.error followed by traceback.print_exc() to include the traceback in the log message. This can simplify the code and ensure that the traceback is always logged when an error occurs.

Suggested change
import traceback
traceback.print_exc()
logger.exception(f"密码验证过程中发生错误: {e}")
# 如果验证过程出错,为了安全起见,拒绝访问

# 如果验证过程出错,为了安全起见,拒绝访问
return False

def main():
try:
# 设置日志
Expand Down Expand Up @@ -84,6 +132,11 @@ def main():
with open(style_path, "r", encoding="utf-8") as f:
app.setStyleSheet(f.read())

# 密码验证
if not verify_password():
logger.info("密码验证失败,程序退出")
sys.exit(0)

# 创建并显示主窗口
window = UrlNavigatorApp()
window.show()
Expand Down
Loading