diff --git a/CHANGELOG-zh-cn.md b/CHANGELOG-zh-cn.md deleted file mode 100644 index c09ca401..00000000 --- a/CHANGELOG-zh-cn.md +++ /dev/null @@ -1,134 +0,0 @@ -## ZeroNet 0.5.1 (2016-11-18) -### 新增 -- 多语言界面 -- 新插件:为站点 HTML 与 JS 文件提供的翻译助手 -- 每个站点独立的 favicon - -### 修复 -- 并行可选文件下载 - -## ZeroNet 0.5.0 (2016-11-08) -### 新增 -- 新插件:允许在 ZeroHello 列出/删除/固定/管理文件 -- 新的 API 命令来关注用户的可选文件,与可选文件的请求统计 -- 新的可选文件总大小限制 -- 新插件:保存节点到数据库并在重启时保持它们,使得更快的可选文件搜索以及在没有 Tracker 的情况下工作 -- 重写 UPnP 端口打开器 + 退出时关闭端口(感谢 sirMackk!) -- 通过懒惰 PeerHashfield 创建来减少内存占用 -- 在 /Stats 页面加载 JSON 文件统计与数据库信息 - -### 更改 -- 独立的锁定文件来获得更好的 Windows 兼容性 -- 当执行 start.py 时,即使 ZeroNet 已经运行也打开浏览器 -- 在重载时保持插件顺序来允许插件扩展另一个插件 -- 只在完整加载 sites.json 时保存来避免数据丢失 -- 将更多的 Tracker 更改为更可靠的 Tracker -- 更少的 findhashid CPU 使用率 -- 合并下载大量可选文件 -- 更多对于可选文件的其他优化 -- 如果一个站点有 1000 个节点,更积极地清理 -- 为验证错误使用警告而不是错误 -- 首先推送更新到更新的客户端 -- 损坏文件重置改进 - -### 修复 -- 修复启动时出现的站点删除错误 -- 延迟 WebSocket 消息直到连接上 -- 修复如果文件包含额外数据时的数据库导入 -- 修复大站点下载 -- 修复 diff 发送 bug (跟踪它好长时间了) -- 修复当 JSON 文件包含 [] 字符时随机出现的发布错误 -- 修复 siteDelete 与 siteCreate bug -- 修复文件写入确认对话框 - - -## ZeroNet 0.4.1 (2016-09-05) -### 新增 -- 更快启动与更少内存使用的内核改变 -- 尝试连接丢失时重新连接 Tor -- 侧边栏滑入 -- 尝试避免不完整的数据文件被覆盖 -- 更快地打开数据库 -- 在侧边栏显示用户文件大小 -- 依赖 --connection_limit 的并发 worker 数量 - - -### 更改 -- 在空闲 5 分钟后关闭数据库 -- 更好的站点大小计算 -- 允许在域名中使用“-”符号 -- 总是尝试为站点保持连接 -- 移除已合并站点的合并权限 -- 只扫描最后 3 天的新闻源来加快数据库请求 -- 更新 ZeroBundle-win 到 Python 2.7.12 - - -### 修复 -- 修复重要的安全问题:允许任意用户无需有效的来自 ID 提供者的证书发布新内容,感谢 Kaffie 指出 -- 修复在没有选择提供证书提供者时的侧边栏错误 -- 在数据库重建时跳过无效文件 -- 修复随机弹出的 WebSocket 连接错误 -- 修复新的 siteCreate 命令 -- 修复站点大小计算 -- 修复计算机唤醒后的端口打开检查 -- 修复 --size_limit 的命令行解析 - - -## ZeroNet 0.4.0 (2016-08-11) -### 新增 -- 合并站点插件 -- Live source code reloading: Faster core development by allowing me to make changes in ZeroNet source code without restarting it. -- 为合并站点设计的新 JSON 表 -- 从侧边栏重建数据库 -- 允许直接在 JSON 表中存储自定义数据:更简单与快速的 SQL 查询 -- 用户文件存档:允许站点拥有者存档不活跃的用户内容到单个文件(减少初始同步的时间/CPU/内存使用率) -- 在文件删除时同时触发数据库 onUpdated/update -- 从 ZeroFrame API 请求权限 -- 允许使用 fileWrite API 命令在 content.json 存储额外数据 -- 更快的可选文件下载 -- 使用替代源 (Gogs, Gitlab) 来下载更新 -- Track provided sites/connection and prefer to keep the ones with more sites to reduce connection number - -### 更改 -- 保持每个站点至少 5 个连接 -- 将目标站点连接从 10 更改到 15 -- ZeroHello 搜索功能稳定性/速度改进 -- 提升机械硬盘下的客户端性能 - -### 修复 -- 修复 IE11 wrapper nonce 错误 -- 修复在移动设备上的侧边栏 -- 修复站点大小计算 -- 修复 IE10 兼容性 -- Windows XP ZeroBundle 兼容性(感谢中国人民) - - -## ZeroNet 0.3.7 (2016-05-27) -### 更改 -- 通过只传输补丁来减少带宽使用 -- 其他 CPU /内存优化 - - -## ZeroNet 0.3.6 (2016-05-27) -### 新增 -- 新的 ZeroHello -- Newsfeed 函数 - -### 修复 -- 安全性修复 - - -## ZeroNet 0.3.5 (2016-02-02) -### 新增 -- 带有 .onion 隐藏服务的完整 Tor 支持 -- 使用 ZeroNet 协议的 Bootstrap - -### 修复 -- 修复 Gevent 1.0.2 兼容性 - - -## ZeroNet 0.3.4 (2015-12-28) -### 新增 -- AES, ECIES API 函数支持 -- PushState 与 ReplaceState URL 通过 API 的操作支持 -- 多用户 localstorage diff --git a/plugins/Sidebar/media/Internals.coffee b/plugins/Sidebar/media/Internals.coffee deleted file mode 100644 index 484ecdb7..00000000 --- a/plugins/Sidebar/media/Internals.coffee +++ /dev/null @@ -1,60 +0,0 @@ -class Internals extends Class - constructor: (@sidebar) -> - @tag = null - @opened = false - if window.top.location.hash == "#internals" - setTimeout (=> @open()), 10 - - createHtmltag: -> - @when_loaded = $.Deferred() - if not @container - @container = $(""" -
-
-
- -
-
- - """) - @container.appendTo(document.body) - @tag = @container.find(".internals") - - open: => - @createHtmltag() - @sidebar.fixbutton_targety = @sidebar.page_height - @stopDragY() - - onOpened: => - @sidebar.onClosed() - @log "onOpened" - - onClosed: => - $(document.body).removeClass("body-internals") - - stopDragY: => - # Animate sidebar and iframe - if @sidebar.fixbutton_targety == @sidebar.fixbutton_inity - # Closed - targety = 0 - @opened = false - else - # Opened - targety = @sidebar.fixbutton_targety - @sidebar.fixbutton_inity - @onOpened() - @opened = true - - # Revent sidebar transitions - if @tag - @tag.css("transition", "0.5s ease-out") - @tag.css("transform", "translateY(#{targety}px)").one transitionEnd, => - @tag.css("transition", "") - if not @opened - @log "cleanup" - # Revert body transformations - @log "stopdrag", "opened:", @opened, targety - if not @opened - @onClosed() - -window.Internals = Internals \ No newline at end of file diff --git a/plugins/Sidebar/media/Internals.css b/plugins/Sidebar/media/Internals.css deleted file mode 100644 index 36b2489e..00000000 --- a/plugins/Sidebar/media/Internals.css +++ /dev/null @@ -1,17 +0,0 @@ -.internals-container { width: 100%; z-index: 998; position: absolute; top: -100vh; } -.internals { background-color: #EEE; height: 100vh; transform: translateY(0px); } -.internals-middle {height: 0px; top: 50%; position: absolute; width: 100%; left: 50%; } - -.internals .mynode { - border: 0.5px solid #aaa; width: 50px; height: 50px; transform: rotateZ(45deg); margin-top: -25px; margin-left: -25px; - opacity: 1; display: inline-block; background-color: #EEE; z-index: 9; position: absolute; outline: 5px solid #EEE; -} -.internals .peers { width: 0px; height: 0px; position: absolute; left: -20px; top: -20px; text-align: center; } -.internals .peer { left: 0px; top: 0px; position: absolute; } -.internals .peer .icon { width: 20px; height: 20px; padding: 10px; display: inline-block; text-decoration: none; left: 200px; position: absolute; color: #666; } -.internals .peer .icon:before { content: "\25BC"; position: absolute; margin-top: 3px; margin-left: -1px; opacity: 0; transition: all 0.3s } -.internals .peer .icon:hover:before { opacity: 1; transition: none } -.internals .peer .line { - width: 187px; border-top: 1px solid #CCC; position: absolute; top: 20px; left: 20px; - transform: rotateZ(334deg); transform-origin: bottom left; -} \ No newline at end of file diff --git a/plugins/Stats/StatsPlugin.py b/plugins/Stats/StatsPlugin.py index e0c410db..6fb182ae 100644 --- a/plugins/Stats/StatsPlugin.py +++ b/plugins/Stats/StatsPlugin.py @@ -373,6 +373,7 @@ class UiRequestPlugin(object): gc.collect() # Implicit grabage collection yield "Done in %.1f" % (time.time() - s) + @helper.encodeResponse def actionDumpobj(self): import gc @@ -410,6 +411,7 @@ class UiRequestPlugin(object): gc.collect() # Implicit grabage collection + @helper.encodeResponse def actionListobj(self): import gc @@ -827,6 +829,7 @@ class UiRequestPlugin(object): yield "
Done. Total: %.2fs" % (time.time() - t) + @helper.encodeResponse def actionGcCollect(self): import gc self.sendHeader() diff --git a/plugins/disabled-Bootstrapper/BootstrapperDb.py b/plugins/disabled-Bootstrapper/BootstrapperDb.py index fcc428f7..3c47b76d 100644 --- a/plugins/disabled-Bootstrapper/BootstrapperDb.py +++ b/plugins/disabled-Bootstrapper/BootstrapperDb.py @@ -26,7 +26,7 @@ class BootstrapperDb(Db.Db): def updateHashCache(self): res = self.execute("SELECT * FROM hash") - self.hash_ids = {str(row["hash"]): row["hash_id"] for row in res} + self.hash_ids = {row["hash"]: row["hash_id"] for row in res} self.log.debug("Loaded %s hash_ids" % len(self.hash_ids)) def checkTables(self): diff --git a/plugins/disabled-Bootstrapper/BootstrapperPlugin.py b/plugins/disabled-Bootstrapper/BootstrapperPlugin.py index b6d9e178..474f79c1 100644 --- a/plugins/disabled-Bootstrapper/BootstrapperPlugin.py +++ b/plugins/disabled-Bootstrapper/BootstrapperPlugin.py @@ -130,6 +130,7 @@ class FileRequestPlugin(object): @PluginManager.registerTo("UiRequest") class UiRequestPlugin(object): + @helper.encodeResponse def actionStatsBootstrapper(self): self.sendHeader() diff --git a/plugins/disabled-Bootstrapper/Test/TestBootstrapper.py b/plugins/disabled-Bootstrapper/Test/TestBootstrapper.py index 983cb44c..69bdc54c 100644 --- a/plugins/disabled-Bootstrapper/Test/TestBootstrapper.py +++ b/plugins/disabled-Bootstrapper/Test/TestBootstrapper.py @@ -27,6 +27,28 @@ def bootstrapper_db(request): @pytest.mark.usefixtures("resetSettings") class TestBootstrapper: + def testHashCache(self, file_server, bootstrapper_db): + ip_type = helper.getIpType(file_server.ip) + peer = Peer(file_server.ip, 1544, connection_server=file_server) + hash1 = hashlib.sha256(b"site1").digest() + hash2 = hashlib.sha256(b"site2").digest() + hash3 = hashlib.sha256(b"site3").digest() + + # Verify empty result + res = peer.request("announce", { + "hashes": [hash1, hash2], + "port": 15441, "need_types": [ip_type], "need_num": 10, "add": [ip_type] + }) + + assert len(res["peers"][0][ip_type]) == 0 # Empty result + + hash_ids_before = bootstrapper_db.hash_ids.copy() + + bootstrapper_db.updateHashCache() + + assert hash_ids_before == bootstrapper_db.hash_ids + + def testBootstrapperDb(self, file_server, bootstrapper_db): ip_type = helper.getIpType(file_server.ip) peer = Peer(file_server.ip, 1544, connection_server=file_server) diff --git a/src/Config.py b/src/Config.py index 13a8ec44..4613940b 100644 --- a/src/Config.py +++ b/src/Config.py @@ -13,7 +13,7 @@ class Config(object): def __init__(self, argv): self.version = "0.7.0" - self.rev = 4122 + self.rev = 4126 self.argv = argv self.action = None self.pending_changes = {} @@ -409,7 +409,7 @@ class Config(object): self.config_file = argv[argv.index("--config_file") + 1] # Load config file if os.path.isfile(self.config_file): - config = configparser.ConfigParser(allow_no_value=True, strict=False) + config = configparser.RawConfigParser(allow_no_value=True, strict=False) config.read(self.config_file) for section in config.sections(): for key, val in config.items(section): diff --git a/src/Debug/DebugReloader.py b/src/Debug/DebugReloader.py index e6cdec06..29ca7029 100644 --- a/src/Debug/DebugReloader.py +++ b/src/Debug/DebugReloader.py @@ -44,6 +44,9 @@ class DebugReloader: self.last_chaged = time.time() time_modified = os.path.getmtime(path) self.log.debug("File changed: %s reloading source code (modified %.3fs ago)" % (evt, time.time() - time_modified)) + if time.time() - time_modified > 5: # Probably it's just an attribute change, ignore it + return False + time.sleep(0.1) # Wait for lock release for callback in self.callbacks: try: diff --git a/zeronet.py b/zeronet.py index 03c9865d..73339c3f 100755 --- a/zeronet.py +++ b/zeronet.py @@ -26,7 +26,12 @@ def main(): print("Failed to log error:", log_err) traceback.print_exc() from Config import config - traceback.print_exc(file=open(config.log_dir + "/error.log", "a")) + error_log_path = config.log_dir + "/error.log" + traceback.print_exc(file=open(error_log_path, "w")) + print("---") + print("Please report it: https://github.com/HelloZeroNet/ZeroNet/issues/new?assignees=&labels=&template=bug-report.md") + if sys.platform.startswith("win"): + displayErrorMessage(err, error_log_path) if main and (main.update_after_shutdown or main.restart_after_shutdown): # Updater if main.update_after_shutdown: @@ -37,6 +42,28 @@ def main(): print("Restarting...") restart() +def displayErrorMessage(err, error_log_path): + import ctypes + import urllib.parse + import subprocess + + MB_YESNOCANCEL = 0x3 + MB_ICONEXCLAIMATION = 0x30 + + ID_YES = 0x6 + ID_NO = 0x7 + ID_CANCEL = 0x2 + + err_message = "%s: %s" % (type(err).__name__, err) + + res = ctypes.windll.user32.MessageBoxW(0, "Unhandled exception: %s\nReport error?" % err_message, "ZeroNet error", MB_YESNOCANCEL | MB_ICONEXCLAIMATION) + if res == ID_YES: + import webbrowser + report_url = "https://github.com/HelloZeroNet/ZeroNet/issues/new?assignees=&labels=&template=bug-report.md&title=%s" + webbrowser.open(report_url % urllib.parse.quote("Unhandled exception: %s" % err_message)) + if res in [ID_YES, ID_NO]: + subprocess.Popen(['notepad.exe', error_log_path]) + def restart(): if "main" in sys.modules: