Merge branch 'HelloZeroNet-py3' into massive-rework
# Conflicts: # src/File/FileServer.py
This commit is contained in:
commit
545fe9442c
38 changed files with 588 additions and 120 deletions
6
.github/workflows/tests.yml
vendored
6
.github/workflows/tests.yml
vendored
|
@ -1,6 +1,6 @@
|
|||
name: tests
|
||||
|
||||
on: [push]
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
|
@ -9,10 +9,10 @@ jobs:
|
|||
strategy:
|
||||
max-parallel: 16
|
||||
matrix:
|
||||
python-version: [3.5, 3.6, 3.7, 3.8]
|
||||
python-version: [3.5, 3.6, 3.7, 3.8, 3.9]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v1
|
||||
|
|
12
README.md
12
README.md
|
@ -1,6 +1,6 @@
|
|||
# ZeroNet [](https://travis-ci.org/HelloZeroNet/ZeroNet) [](https://zeronet.io/docs/faq/) [](https://zeronet.io/docs/help_zeronet/donate/)  [](https://hub.docker.com/r/nofish/zeronet)
|
||||
|
||||
Decentralized websites using Bitcoin crypto and the BitTorrent network - https://zeronet.io
|
||||
Decentralized websites using Bitcoin crypto and the BitTorrent network - https://zeronet.io / [onion](http://zeronet34m3r5ngdu54uj57dcafpgdjhxsgq5kla5con4qvcmfzpvhad.onion)
|
||||
|
||||
|
||||
## Why?
|
||||
|
@ -83,12 +83,12 @@ Decentralized websites using Bitcoin crypto and the BitTorrent network - https:/
|
|||
__Tip:__ Start with `./ZeroNet.sh --ui_ip '*' --ui_restrict your.ip.address` to allow remote connections on the web interface.
|
||||
|
||||
### Android (arm, arm64, x86)
|
||||
- minimum Android version supported 16 (JellyBean).
|
||||
- Google Play Store Link https://play.google.com/store/apps/details?id=in.canews.zeronet
|
||||
|
||||
[<img src="https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png"
|
||||
- minimum Android version supported 16 (JellyBean)
|
||||
- [<img src="https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png"
|
||||
alt="Download from Google Play"
|
||||
height="80">](https://play.google.com/store/apps/details?id=in.canews.zeronet)
|
||||
height="80">](https://play.google.com/store/apps/details?id=in.canews.zeronetmobile)
|
||||
- APK download: https://github.com/canewsin/zeronet_mobile/releases
|
||||
- XDA Labs: https://labs.xda-developers.com/store/app/in.canews.zeronet
|
||||
|
||||
#### Docker
|
||||
There is an official image, built from source at: https://hub.docker.com/r/nofish/zeronet/
|
||||
|
|
|
@ -146,6 +146,7 @@ class ActionsPlugin:
|
|||
|
||||
yield "\n"
|
||||
res = {}
|
||||
res_time_taken = {}
|
||||
multiplers = []
|
||||
for test in tests:
|
||||
s = time.time()
|
||||
|
@ -182,11 +183,35 @@ class ActionsPlugin:
|
|||
yield self.formatResult(time_taken, time_standard)
|
||||
yield "\n"
|
||||
res[key] = "ok"
|
||||
res_time_taken[key] = time_taken
|
||||
multiplers.append(time_standard / max(time_taken, 0.001))
|
||||
except Exception as err:
|
||||
res[key] = err
|
||||
yield "Failed!\n! Error: %s\n\n" % Debug.formatException(err)
|
||||
|
||||
yield "\n== Result ==\n"
|
||||
|
||||
# Check verification speed
|
||||
if "testVerify {'lib_verify': 'sslcrypto'}" in res_time_taken:
|
||||
speed_order = ["sslcrypto_fallback", "sslcrypto", "libsecp256k1"]
|
||||
time_taken = {}
|
||||
for lib_verify in speed_order:
|
||||
time_taken[lib_verify] = res_time_taken["testVerify {'lib_verify': '%s'}" % lib_verify]
|
||||
|
||||
time_taken["sslcrypto_fallback"] *= 10 # fallback benchmark only run 20 times instead of 200
|
||||
speedup_sslcrypto = time_taken["sslcrypto_fallback"] / time_taken["sslcrypto"]
|
||||
speedup_libsecp256k1 = time_taken["sslcrypto_fallback"] / time_taken["libsecp256k1"]
|
||||
|
||||
yield "\n* Verification speedup:\n"
|
||||
yield " - OpenSSL: %.1fx (reference: 7.0x)\n" % speedup_sslcrypto
|
||||
yield " - libsecp256k1: %.1fx (reference: 23.8x)\n" % speedup_libsecp256k1
|
||||
|
||||
if speedup_sslcrypto < 2:
|
||||
res["Verification speed"] = "error: OpenSSL speedup low: %.1fx" % speedup_sslcrypto
|
||||
|
||||
if speedup_libsecp256k1 < speedup_sslcrypto:
|
||||
res["Verification speed"] = "error: libsecp256k1 speedup low: %.1fx" % speedup_libsecp256k1
|
||||
|
||||
if not res:
|
||||
yield "! No tests found"
|
||||
if config.action == "test":
|
||||
|
@ -194,17 +219,22 @@ class ActionsPlugin:
|
|||
else:
|
||||
num_failed = len([res_key for res_key, res_val in res.items() if res_val != "ok"])
|
||||
num_success = len([res_key for res_key, res_val in res.items() if res_val == "ok"])
|
||||
yield "* Result:\n"
|
||||
yield "\n* Tests:\n"
|
||||
yield " - Total: %s tests\n" % len(res)
|
||||
yield " - Success: %s tests\n" % num_success
|
||||
yield " - Failed: %s tests\n" % num_failed
|
||||
if any(multiplers):
|
||||
multipler_avg = sum(multiplers) / len(multiplers)
|
||||
multipler_title = self.getMultiplerTitle(multipler_avg)
|
||||
yield " - Average speed factor: %.2fx (%s)" % (multipler_avg, multipler_title)
|
||||
if num_failed == 0 and config.action == "test":
|
||||
sys.exit(1)
|
||||
yield " - Average speed factor: %.2fx (%s)\n" % (multipler_avg, multipler_title)
|
||||
|
||||
# Display errors
|
||||
for res_key, res_val in res.items():
|
||||
if res_val != "ok":
|
||||
yield " ! %s %s\n" % (res_key, res_val)
|
||||
|
||||
if num_failed != 0 and config.action == "test":
|
||||
sys.exit(1)
|
||||
|
||||
def testHttps(self, num_run=1):
|
||||
"""
|
||||
|
@ -323,13 +353,14 @@ class ActionsPlugin:
|
|||
valid = "G1GXaDauZ8vX/N9Jn+MRiGm9h+I94zUhDnNYFaqMGuOiBHB+kp4cRPZOL7l1yqK5BHa6J+W97bMjvTXtxzljp6w="
|
||||
assert sign == valid, "%s != %s" % (sign, valid)
|
||||
|
||||
def testVerify(self, num_run=1, lib_verify="btctools"):
|
||||
def testVerify(self, num_run=1, lib_verify="sslcrypto"):
|
||||
"""
|
||||
Test verification of generated signatures
|
||||
"""
|
||||
from Crypt import CryptBitcoin
|
||||
CryptBitcoin.loadLib(lib_verify, silent=True)
|
||||
|
||||
|
||||
data = "Hello" * 1024
|
||||
privatekey = "5JsunC55XGVqFQj5kPGK4MWgTL26jKbnPhjnmchSNPo75XXCwtk"
|
||||
address = CryptBitcoin.privatekeyToAddress(privatekey)
|
||||
|
@ -340,6 +371,9 @@ class ActionsPlugin:
|
|||
yield "."
|
||||
assert ok, "does not verify from %s" % address
|
||||
|
||||
if lib_verify == "sslcrypto":
|
||||
yield("(%s)" % CryptBitcoin.sslcrypto.ecc.get_backend())
|
||||
|
||||
def testPortCheckers(self):
|
||||
"""
|
||||
Test all active open port checker
|
||||
|
@ -361,7 +395,6 @@ class ActionsPlugin:
|
|||
"""
|
||||
from Peer import PeerPortchecker
|
||||
peer_portchecker = PeerPortchecker.PeerPortchecker(None)
|
||||
s = time.time()
|
||||
announce_func = getattr(peer_portchecker, func_name)
|
||||
res = announce_func(3894)
|
||||
yield res
|
||||
|
|
|
@ -39,7 +39,7 @@ function setState(elem, text) {
|
|||
}
|
||||
}
|
||||
formatted = formatted.replace(/(\! Error:.*)/, "<div class='test error'>$1</div>");
|
||||
formatted = formatted.replace(/(\* Result:[^]*)/, "<div class='test summary'>$1</div>");
|
||||
formatted = formatted.replace(/(\== Result ==[^]*)/, "<div class='test summary'>$1</div>");
|
||||
var is_bottom = document.body.scrollTop + document.body.clientHeight >= document.body.scrollHeight - 5;
|
||||
elem.innerHTML = formatted.trim();
|
||||
if (is_bottom)
|
||||
|
|
6
plugins/ContentFilter/languages/jp.json
Normal file
6
plugins/ContentFilter/languages/jp.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"Hide all content from <b>%s</b>?": "<b>%s</b> のコンテンツをすべて隠しますか?",
|
||||
"Mute": "ミュート",
|
||||
"Unmute <b>%s</b>?": "<b>%s</b> のミュートを解除しますか?",
|
||||
"Unmute": "ミュート解除"
|
||||
}
|
5
plugins/MergerSite/languages/jp.json
Normal file
5
plugins/MergerSite/languages/jp.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"Add <b>%s</b> new site?": "サイト: <b>%s</b> を追加しますか?",
|
||||
"Added <b>%s</b> new site": "サイト: <b>%s</b> を追加しました",
|
||||
"Site deleted: <b>%s</b>": "サイト: <b>%s</b> を削除しました"
|
||||
}
|
|
@ -139,7 +139,7 @@ class UiWebsocketPlugin(object):
|
|||
wheres = {}
|
||||
wheres_raw = []
|
||||
if "bigfile" in filter:
|
||||
wheres["size >"] = 1024 * 1024 * 10
|
||||
wheres["size >"] = 1024 * 1024 * 1
|
||||
if "downloaded" in filter:
|
||||
wheres_raw.append("(is_downloaded = 1 OR is_pinned = 1)")
|
||||
if "pinned" in filter:
|
||||
|
@ -166,11 +166,14 @@ class UiWebsocketPlugin(object):
|
|||
row["address"] = address
|
||||
|
||||
if row["size"] > 1024 * 1024:
|
||||
has_info = self.addBigfileInfo(row)
|
||||
has_bigfile_info = self.addBigfileInfo(row)
|
||||
else:
|
||||
has_info = False
|
||||
has_bigfile_info = False
|
||||
|
||||
if not has_info:
|
||||
if not has_bigfile_info and "bigfile" in filter:
|
||||
continue
|
||||
|
||||
if not has_bigfile_info:
|
||||
if row["is_downloaded"]:
|
||||
row["bytes_downloaded"] = row["size"]
|
||||
row["downloaded_percent"] = 100
|
||||
|
|
7
plugins/OptionalManager/languages/jp.json
Normal file
7
plugins/OptionalManager/languages/jp.json
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"Pinned %s files": "%s 件のファイルを固定",
|
||||
"Removed pin from %s files": "%s 件のファイルの固定を解除",
|
||||
"You started to help distribute <b>%s</b>.<br><small>Directory: %s</small>": "あなたはサイト: <b>%s</b> の配布の援助を開始しました。<br><small>ディレクトリ: %s</small>",
|
||||
"Help distribute all new optional files on site <b>%s</b>": "サイト: <b>%s</b> のすべての新しいオプションファイルの配布を援助しますか?",
|
||||
"Yes, I want to help!": "はい、やります!"
|
||||
}
|
|
@ -1,8 +1,11 @@
|
|||
{
|
||||
"Copy to clipboard": "クリップボードにコピー",
|
||||
"Peers": "ピア",
|
||||
"Connected": "接続済み",
|
||||
"Connectable": "利用可能",
|
||||
"Connectable peers": "ピアに接続可能",
|
||||
"Onion": "Onion",
|
||||
"Local": "ローカル",
|
||||
|
||||
"Data transfer": "データ転送",
|
||||
"Received": "受信",
|
||||
|
@ -11,6 +14,8 @@
|
|||
"Sent bytes": "送信バイト数",
|
||||
|
||||
"Files": "ファイル",
|
||||
"Browse files": "ファイルを見る",
|
||||
"Save as .zip": "ZIP形式で保存",
|
||||
"Total": "合計",
|
||||
"Image": "画像",
|
||||
"Other": "その他",
|
||||
|
@ -23,18 +28,23 @@
|
|||
|
||||
"Optional files": "オプション ファイル",
|
||||
"Downloaded": "ダウンロード済み",
|
||||
"Help distribute added optional files": "オプションファイルの配布を支援する",
|
||||
"Auto download big file size limit": "大きなファイルの自動ダウンロードのサイズ制限",
|
||||
"Download previous files": "以前のファイルのダウンロード",
|
||||
"Optional files download started": "オプションファイルのダウンロードを開始",
|
||||
"Optional files downloaded": "オプションファイルのダウンロードが完了しました",
|
||||
"Download and help distribute all files": "ダウンロードしてすべてのファイルの配布を支援する",
|
||||
"Total size": "合計サイズ",
|
||||
"Downloaded files": "ダウンロードされたファイル",
|
||||
|
||||
"Database": "データベース",
|
||||
"search feeds": "フィードを検索する",
|
||||
"{feeds} query": "{フィード} お問い合わせ",
|
||||
"{feeds} query": "{feeds} お問い合わせ",
|
||||
"Reload": "再読込",
|
||||
"Rebuild": "再ビルド",
|
||||
"No database found": "データベースが見つかりません",
|
||||
|
||||
"Identity address": "Identity address",
|
||||
"Identity address": "あなたの識別アドレス",
|
||||
"Change": "編集",
|
||||
|
||||
"Site control": "サイト管理",
|
||||
|
@ -52,15 +62,23 @@
|
|||
"{} tries": "{} 試行",
|
||||
"+ {num_bad_files} more": "+ {num_bad_files} more",
|
||||
|
||||
"This is my site": "This is my site",
|
||||
"This is my site": "これは私のサイトです",
|
||||
"Site title": "サイトタイトル",
|
||||
"Site description": "サイトの説明",
|
||||
"Save site settings": "サイトの設定を保存する",
|
||||
"Open site directory": "サイトのディレクトリを開く",
|
||||
|
||||
"Content publishing": "コンテンツを公開する",
|
||||
"Add saved private key": "秘密鍵の追加と保存",
|
||||
"Save": "保存",
|
||||
"Private key saved.": "秘密鍵が保存されています",
|
||||
"Private key saved for site signing": "サイトに署名するための秘密鍵を保存",
|
||||
"Forgot": "わすれる",
|
||||
"Saved private key removed": "保存された秘密鍵を削除しました",
|
||||
"Choose": "選択",
|
||||
"Sign": "Sign",
|
||||
"Sign": "署名",
|
||||
"Publish": "公開する",
|
||||
"Sign and publish": "署名して公開",
|
||||
|
||||
"This function is disabled on this proxy": "この機能はこのプロキシで無効になっています",
|
||||
"GeoLite2 City database download error: {}!<br>Please download manually and unpack to data dir:<br>{}": "GeoLite2 Cityデータベースのダウンロードエラー: {}!<br>手動でダウンロードして、フォルダに解凍してください。:<br>{}",
|
||||
|
@ -74,9 +92,13 @@
|
|||
"Database rebuilt!": "データベースが再構築されました!",
|
||||
"Site updated!": "サイトが更新されました!",
|
||||
"Delete this site": "このサイトを削除する",
|
||||
"Blacklist": "NG",
|
||||
"Blacklist this site": "NGリストに入れる",
|
||||
"Reason": "理由",
|
||||
"Delete and Blacklist": "削除してNG",
|
||||
"File write error: ": "ファイル書き込みエラー:",
|
||||
"Site settings saved!": "サイト設定が保存されました!",
|
||||
"Enter your private key:": "秘密鍵を入力してください:",
|
||||
" Signed!": " Signed!",
|
||||
" Signed!": " 署名しました!",
|
||||
"WebGL not supported": "WebGLはサポートされていません"
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
.menu {
|
||||
font-family: Roboto, 'Segoe UI', 'Helvetica Neue';
|
||||
font-family: Roboto, 'Segoe UI', 'Helvetica Neue'; z-index: 999;
|
||||
}
|
||||
|
||||
.drag-bg { width: 100%; height: 100%; position: fixed; }
|
||||
|
|
|
@ -111,7 +111,7 @@
|
|||
|
||||
|
||||
.menu {
|
||||
font-family: Roboto, 'Segoe UI', 'Helvetica Neue';
|
||||
font-family: Roboto, 'Segoe UI', 'Helvetica Neue'; z-index: 999;
|
||||
}
|
||||
|
||||
.drag-bg { width: 100%; height: 100%; position: fixed; }
|
||||
|
|
|
@ -2,7 +2,8 @@ import time
|
|||
import html
|
||||
import os
|
||||
import json
|
||||
from collections import OrderedDict
|
||||
import sys
|
||||
import itertools
|
||||
|
||||
from Plugin import PluginManager
|
||||
from Config import config
|
||||
|
@ -35,40 +36,9 @@ class UiRequestPlugin(object):
|
|||
else:
|
||||
return 0
|
||||
|
||||
# /Stats entry point
|
||||
@helper.encodeResponse
|
||||
def actionStats(self):
|
||||
import gc
|
||||
import sys
|
||||
from Ui import UiRequest
|
||||
from Crypt import CryptConnection
|
||||
def renderHead(self):
|
||||
import main
|
||||
|
||||
|
||||
hpy = None
|
||||
if self.get.get("size") == "1": # Calc obj size
|
||||
try:
|
||||
import guppy
|
||||
hpy = guppy.hpy()
|
||||
except:
|
||||
pass
|
||||
self.sendHeader()
|
||||
|
||||
if "Multiuser" in PluginManager.plugin_manager.plugin_names and not config.multiuser_local:
|
||||
yield "This function is disabled on this proxy"
|
||||
return
|
||||
|
||||
s = time.time()
|
||||
|
||||
# Style
|
||||
yield """
|
||||
<style>
|
||||
* { font-family: monospace }
|
||||
table td, table th { text-align: right; padding: 0px 10px }
|
||||
.connections td { white-space: nowrap }
|
||||
.serving-False { opacity: 0.3 }
|
||||
</style>
|
||||
"""
|
||||
from Crypt import CryptConnection
|
||||
|
||||
# Memory
|
||||
yield "rev%s | " % config.rev
|
||||
|
@ -99,9 +69,13 @@ class UiRequestPlugin(object):
|
|||
pass
|
||||
yield "<br>"
|
||||
|
||||
def renderConnectionsTable(self):
|
||||
import main
|
||||
|
||||
# Connections
|
||||
yield "<b>Connections</b> (%s, total made: %s, in: %s, out: %s):<br>" % (
|
||||
len(main.file_server.connections), main.file_server.last_connection_id, main.file_server.num_incoming, main.file_server.num_outgoing
|
||||
len(main.file_server.connections), main.file_server.last_connection_id,
|
||||
main.file_server.num_incoming, main.file_server.num_outgoing
|
||||
)
|
||||
yield "<table class='connections'><tr> <th>id</th> <th>type</th> <th>ip</th> <th>open</th> <th>crypt</th> <th>ping</th>"
|
||||
yield "<th>buff</th> <th>bad</th> <th>idle</th> <th>open</th> <th>delay</th> <th>cpu</th> <th>out</th> <th>in</th> <th>last sent</th>"
|
||||
|
@ -140,6 +114,7 @@ class UiRequestPlugin(object):
|
|||
])
|
||||
yield "</table>"
|
||||
|
||||
def renderTrackers(self):
|
||||
# Trackers
|
||||
yield "<br><br><b>Trackers:</b><br>"
|
||||
yield "<table class='trackers'><tr> <th>address</th> <th>request</th> <th>successive errors</th> <th>last_request</th></tr>"
|
||||
|
@ -168,12 +143,13 @@ class UiRequestPlugin(object):
|
|||
])
|
||||
yield "</table>"
|
||||
|
||||
# Tor hidden services
|
||||
def renderTor(self):
|
||||
import main
|
||||
yield "<br><br><b>Tor hidden services (status: %s):</b><br>" % main.file_server.tor_manager.status
|
||||
for site_address, onion in list(main.file_server.tor_manager.site_onions.items()):
|
||||
yield "- %-34s: %s<br>" % (site_address, onion)
|
||||
|
||||
# Db
|
||||
def renderDbStats(self):
|
||||
yield "<br><br><b>Db</b>:<br>"
|
||||
for db in Db.opened_dbs:
|
||||
tables = [row["name"] for row in db.execute("SELECT name FROM sqlite_master WHERE type = 'table'").fetchall()]
|
||||
|
@ -185,8 +161,7 @@ class UiRequestPlugin(object):
|
|||
time.time() - db.last_query_time, db.db_path, db_size, json.dumps(table_rows, sort_keys=True)
|
||||
)
|
||||
|
||||
|
||||
# Sites
|
||||
def renderSites(self):
|
||||
yield "<br><br><b>Sites</b>:"
|
||||
yield "<table>"
|
||||
yield "<tr><th>address</th> <th>connected</th> <th title='connected/good/total'>peers</th> <th>content.json</th> <th>out</th> <th>in</th> </tr>"
|
||||
|
@ -226,7 +201,7 @@ class UiRequestPlugin(object):
|
|||
yield "<br></td></tr>"
|
||||
yield "</table>"
|
||||
|
||||
# Big files
|
||||
def renderBigfiles(self):
|
||||
yield "<br><br><b>Big files</b>:<br>"
|
||||
for site in list(self.server.sites.values()):
|
||||
if not site.settings.get("has_bigfile"):
|
||||
|
@ -250,7 +225,8 @@ class UiRequestPlugin(object):
|
|||
yield "</table>"
|
||||
yield "</div>"
|
||||
|
||||
# Cmd stats
|
||||
def renderRequests(self):
|
||||
import main
|
||||
yield "<div style='float: left'>"
|
||||
yield "<br><br><b>Sent commands</b>:<br>"
|
||||
yield "<table>"
|
||||
|
@ -268,9 +244,18 @@ class UiRequestPlugin(object):
|
|||
yield "</div>"
|
||||
yield "<div style='clear: both'></div>"
|
||||
|
||||
# No more if not in debug mode
|
||||
if not config.debug:
|
||||
return
|
||||
def renderMemory(self):
|
||||
import gc
|
||||
from Ui import UiRequest
|
||||
|
||||
hpy = None
|
||||
if self.get.get("size") == "1": # Calc obj size
|
||||
try:
|
||||
import guppy
|
||||
hpy = guppy.hpy()
|
||||
except Exception:
|
||||
pass
|
||||
self.sendHeader()
|
||||
|
||||
# Object types
|
||||
|
||||
|
@ -371,6 +356,48 @@ class UiRequestPlugin(object):
|
|||
for module_name, module in objs:
|
||||
yield " - %.3fkb: %s %s<br>" % (self.getObjSize(module, hpy), module_name, html.escape(repr(module)))
|
||||
|
||||
# /Stats entry point
|
||||
@helper.encodeResponse
|
||||
def actionStats(self):
|
||||
import gc
|
||||
|
||||
self.sendHeader()
|
||||
|
||||
if "Multiuser" in PluginManager.plugin_manager.plugin_names and not config.multiuser_local:
|
||||
yield "This function is disabled on this proxy"
|
||||
return
|
||||
|
||||
s = time.time()
|
||||
|
||||
# Style
|
||||
yield """
|
||||
<style>
|
||||
* { font-family: monospace }
|
||||
table td, table th { text-align: right; padding: 0px 10px }
|
||||
.connections td { white-space: nowrap }
|
||||
.serving-False { opacity: 0.3 }
|
||||
</style>
|
||||
"""
|
||||
|
||||
renderers = [
|
||||
self.renderHead(),
|
||||
self.renderConnectionsTable(),
|
||||
self.renderTrackers(),
|
||||
self.renderTor(),
|
||||
self.renderDbStats(),
|
||||
self.renderSites(),
|
||||
self.renderBigfiles(),
|
||||
self.renderRequests()
|
||||
|
||||
]
|
||||
|
||||
for part in itertools.chain(*renderers):
|
||||
yield part
|
||||
|
||||
if config.debug:
|
||||
for part in self.renderMemory():
|
||||
yield part
|
||||
|
||||
gc.collect() # Implicit grabage collection
|
||||
yield "Done in %.1f" % (time.time() - s)
|
||||
|
||||
|
@ -457,7 +484,7 @@ class UiRequestPlugin(object):
|
|||
yield "%.1fkb <span title=\"%s\">%s</span>... " % (
|
||||
float(sys.getsizeof(obj)) / 1024, html.escape(str(obj)), html.escape(str(obj)[0:100].ljust(100))
|
||||
)
|
||||
except:
|
||||
except Exception:
|
||||
continue
|
||||
for ref in refs:
|
||||
yield " ["
|
||||
|
@ -485,3 +512,116 @@ class UiRequestPlugin(object):
|
|||
import gc
|
||||
self.sendHeader()
|
||||
yield str(gc.collect())
|
||||
|
||||
# /About entry point
|
||||
@helper.encodeResponse
|
||||
def actionEnv(self):
|
||||
import main
|
||||
|
||||
self.sendHeader()
|
||||
|
||||
yield """
|
||||
<style>
|
||||
* { font-family: monospace; white-space: pre; }
|
||||
h2 { font-size: 100%; margin-bottom: 0px; }
|
||||
small { opacity: 0.5; }
|
||||
table { border-collapse: collapse; }
|
||||
td { padding-right: 10px; }
|
||||
</style>
|
||||
"""
|
||||
|
||||
if "Multiuser" in PluginManager.plugin_manager.plugin_names and not config.multiuser_local:
|
||||
yield "This function is disabled on this proxy"
|
||||
return
|
||||
|
||||
yield from main.actions.testEnv(format="html")
|
||||
|
||||
|
||||
@PluginManager.registerTo("Actions")
|
||||
class ActionsPlugin:
|
||||
def formatTable(self, *rows, format="text"):
|
||||
if format == "html":
|
||||
return self.formatTableHtml(*rows)
|
||||
else:
|
||||
return self.formatTableText(*rows)
|
||||
|
||||
def formatHead(self, title, format="text"):
|
||||
if format == "html":
|
||||
return "<h2>%s</h2>" % title
|
||||
else:
|
||||
return "\n* %s\n" % title
|
||||
|
||||
def formatTableHtml(self, *rows):
|
||||
yield "<table>"
|
||||
for row in rows:
|
||||
yield "<tr>"
|
||||
for col in row:
|
||||
yield "<td>%s</td>" % html.escape(str(col))
|
||||
yield "</tr>"
|
||||
yield "</table>"
|
||||
|
||||
def formatTableText(self, *rows):
|
||||
for row in rows:
|
||||
yield " "
|
||||
for col in row:
|
||||
yield " " + str(col)
|
||||
yield "\n"
|
||||
|
||||
def testEnv(self, format="text"):
|
||||
import gevent
|
||||
import msgpack
|
||||
import pkg_resources
|
||||
import importlib
|
||||
import coincurve
|
||||
import sqlite3
|
||||
from Crypt import CryptBitcoin
|
||||
|
||||
yield "\n"
|
||||
|
||||
yield from self.formatTable(
|
||||
["ZeroNet version:", "%s rev%s" % (config.version, config.rev)],
|
||||
["Python:", "%s" % sys.version],
|
||||
["Platform:", "%s" % sys.platform],
|
||||
["Crypt verify lib:", "%s" % CryptBitcoin.lib_verify_best],
|
||||
["OpenSSL:", "%s" % CryptBitcoin.sslcrypto.ecc.get_backend()],
|
||||
["Libsecp256k1:", "%s" % type(coincurve._libsecp256k1.lib).__name__],
|
||||
["SQLite:", "%s, API: %s" % (sqlite3.sqlite_version, sqlite3.version)],
|
||||
format=format
|
||||
)
|
||||
|
||||
|
||||
yield self.formatHead("Libraries:")
|
||||
rows = []
|
||||
for lib_name in ["gevent", "greenlet", "msgpack", "base58", "merkletools", "rsa", "socks", "pyasn1", "gevent_ws", "websocket", "maxminddb"]:
|
||||
try:
|
||||
module = importlib.import_module(lib_name)
|
||||
if "__version__" in dir(module):
|
||||
version = module.__version__
|
||||
elif "version" in dir(module):
|
||||
version = module.version
|
||||
else:
|
||||
version = "unknown version"
|
||||
|
||||
if type(version) is tuple:
|
||||
version = ".".join(map(str, version))
|
||||
|
||||
rows.append(["- %s:" % lib_name, version, "at " + module.__file__])
|
||||
except Exception as err:
|
||||
rows.append(["! Error importing %s:", repr(err)])
|
||||
|
||||
"""
|
||||
try:
|
||||
yield " - %s<br>" % html.escape(repr(pkg_resources.get_distribution(lib_name)))
|
||||
except Exception as err:
|
||||
yield " ! %s<br>" % html.escape(repr(err))
|
||||
"""
|
||||
|
||||
yield from self.formatTable(*rows, format=format)
|
||||
|
||||
yield self.formatHead("Library config:", format=format)
|
||||
|
||||
yield from self.formatTable(
|
||||
["- gevent:", gevent.config.loop.__module__],
|
||||
["- msgpack unpacker:", msgpack.Unpacker.__module__],
|
||||
format=format
|
||||
)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"ZeroNet Twitter": "ZeroNet Twitter",
|
||||
"ZeroNet Reddit": "ZeroNet Reddit",
|
||||
"ZeroNet Github": "ZeroNet Github",
|
||||
"Report bug/request feature": "Rapport d'erreur/Demanger une fonctionnalité",
|
||||
"Report bug/request feature": "Rapport d'erreur/Demander une fonctionnalité",
|
||||
"!Open ZeroNet": "!Ouvrir ZeroNet",
|
||||
"Quit": "Quitter",
|
||||
"(active)": "(actif)",
|
||||
|
|
14
plugins/Trayicon/languages/jp.json
Normal file
14
plugins/Trayicon/languages/jp.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"ZeroNet Twitter": "ZeroNet Twitter",
|
||||
"ZeroNet Reddit": "ZeroNet Reddit",
|
||||
"ZeroNet Github": "ZeroNet Github",
|
||||
"Report bug/request feature": "バグ報告/要望",
|
||||
"!Open ZeroNet": "!ZeroNetをブラウザで開く",
|
||||
"Quit": "閉じる",
|
||||
"(active)": "(アクティブ)",
|
||||
"(passive)": "(パッシブ)",
|
||||
"Connections: %s": "接続数: %s",
|
||||
"Received: %.2f MB | Sent: %.2f MB": "受信: %.2f MB | 送信: %.2f MB",
|
||||
"Show console window": "コンソールを表示",
|
||||
"Start ZeroNet when Windows starts": "Windows起動時にZeroNetも起動する"
|
||||
}
|
62
plugins/UiConfig/languages/jp.json
Normal file
62
plugins/UiConfig/languages/jp.json
Normal file
|
@ -0,0 +1,62 @@
|
|||
{
|
||||
"ZeroNet config": "ZeroNetの設定",
|
||||
"Web Interface": "WEBインターフェース",
|
||||
"Open web browser on ZeroNet startup": "ZeroNet起動時に自動でブラウザーを開く",
|
||||
|
||||
"Network": "ネットワーク",
|
||||
"Offline mode": "オフラインモード",
|
||||
"Disable network communication.": "通信を無効化します",
|
||||
"File server network": "ファイルサーバネットワーク",
|
||||
"Accept incoming peers using IPv4 or IPv6 address. (default: dual)": "IPv4とIPv6からの受信を許可(既定: 両方)",
|
||||
"Dual (IPv4 & IPv6)": "両方 (IPv4 & IPv6)",
|
||||
"File server port": "ファイルサーバのポート",
|
||||
"Other peers will use this port to reach your served sites. (default: randomize)": "他のピアはこのポートを使用してあなたが所持しているサイトにアクセスします (既定: ランダム)",
|
||||
"File server external ip": "ファイルサーバの外部IP",
|
||||
"Detect automatically": "自動検出",
|
||||
"Your file server is accessible on these ips. (default: detect automatically)": "あなたのファイルサーバへはここで設定したIPでアクセスできます (既定: 自動検出)",
|
||||
|
||||
"Disable: Don't connect to peers on Tor network": "無効: Torネットワーク上のピアに接続しない",
|
||||
"Enable: Only use Tor for Tor network peers": "有効: Torネットワーク上のピアに対してのみTorを使って接続する",
|
||||
"Always: Use Tor for every connections to hide your IP address (slower)": "常時: 全ての接続にTorを使いIPを秘匿する(低速)",
|
||||
|
||||
"Disable": "無効",
|
||||
"Enable": "有効",
|
||||
"Always": "常時",
|
||||
|
||||
"Use Tor bridges": "Torブリッジを使用",
|
||||
"Use obfuscated bridge relays to avoid network level Tor block (even slower)": "難読化されたブリッジリレーを使用してネットワークレベルのTorブロックを避ける(超低速)",
|
||||
|
||||
"Discover new peers using these adresses": "ここで設定したアドレスを用いてピアを発見します",
|
||||
|
||||
"Trackers files": "トラッカーファイル",
|
||||
"Load additional list of torrent trackers dynamically, from a file": "ファイルからトレントラッカーの追加リストを動的に読み込みます",
|
||||
"Eg.: data/trackers.json": "例: data/trackers.json",
|
||||
|
||||
"Proxy for tracker connections": "トラッカーへの接続に使うプロキシ",
|
||||
"Custom": "カスタム",
|
||||
"Custom socks proxy address for trackers": "トラッカーに接続するためのカスタムsocksプロキシのアドレス",
|
||||
|
||||
"Performance": "性能",
|
||||
"Level of logging to file": "ログレベル",
|
||||
"Everything": "全て",
|
||||
"Only important messages": "重要なメッセージのみ",
|
||||
"Only errors": "エラーのみ",
|
||||
"Threads for async file system reads": "非同期ファイルシステムの読み込みに使うスレッド",
|
||||
"Threads for async file system writes": "非同期ファイルシステムの書き込みに使うスレッド",
|
||||
"Threads for cryptographic functions": "暗号機能に使うスレッド",
|
||||
"Threads for database operations": "データベースの操作に使うスレッド",
|
||||
"Sync read": "同期読み取り",
|
||||
"Sync write": "同期書き込み",
|
||||
"Sync execution": "同期実行",
|
||||
"1 thread": "1スレッド",
|
||||
"2 threads": "2スレッド",
|
||||
"3 threads": "3スレッド",
|
||||
"4 threads": "4スレッド",
|
||||
"5 threads": "5スレッド",
|
||||
"10 threads": "10スレッド",
|
||||
|
||||
" configuration item value changed": " の項目の値が変更されました",
|
||||
"Save settings": "設定を保存",
|
||||
"Some changed settings requires restart": "一部の変更の適用には再起動が必要です。",
|
||||
"Restart ZeroNet client": "ZeroNetクライアントを再起動"
|
||||
}
|
|
@ -73,11 +73,17 @@ class UiFileManagerPlugin(object):
|
|||
return super().error404(path)
|
||||
|
||||
path_parts = self.parsePath(path)
|
||||
if not path_parts:
|
||||
return super().error404(path)
|
||||
|
||||
site = self.server.site_manager.get(path_parts["request_address"])
|
||||
|
||||
if not site or not site.content_manager.contents.get("content.json"):
|
||||
return super().error404(path)
|
||||
|
||||
if path_parts["inner_path"] in site.content_manager.contents.get("content.json").get("files", {}):
|
||||
return super().error404(path)
|
||||
|
||||
self.sendHeader(200)
|
||||
path_redirect = "/list" + re.sub("^/media/", "/", path)
|
||||
self.log.debug("Index.html not found: %s, redirecting to: %s" % (path, path_redirect))
|
||||
|
|
20
plugins/UiFileManager/languages/jp.json
Normal file
20
plugins/UiFileManager/languages/jp.json
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"New file name:": "新しいファイルの名前:",
|
||||
"Delete": "削除",
|
||||
"Cancel": "キャンセル",
|
||||
"Selected:": "選択済み: ",
|
||||
"Delete and remove optional:": "オプションを削除",
|
||||
" files": " ファイル",
|
||||
" (modified)": " (編集済み)",
|
||||
" (new)": " (新しい)",
|
||||
" (optional)": " (オプション)",
|
||||
" (ignored from content.json)": " (content.jsonから無視されます)",
|
||||
"Total: ": "合計: ",
|
||||
" dir, ": " のディレクトリ, ",
|
||||
" file in ": " のファイル, ",
|
||||
"+ New": "+ 新規作成",
|
||||
"Edit": "編集",
|
||||
"View": "閲覧",
|
||||
"Save": "保存",
|
||||
"Save: done!": "保存完了!"
|
||||
}
|
15
plugins/UiFileManager/media/js/Config.coffee
Normal file
15
plugins/UiFileManager/media/js/Config.coffee
Normal file
|
@ -0,0 +1,15 @@
|
|||
window.BINARY_EXTENSIONS = [
|
||||
"3dm", "3ds", "3g2", "3gp", "7z", "a", "aac", "adp", "ai", "aif", "aiff", "alz", "ape", "apk", "appimage", "ar", "arj", "asc", "asf", "au", "avi", "bak",
|
||||
"baml", "bh", "bin", "bk", "bmp", "btif", "bz2", "bzip2", "cab", "caf", "cgm", "class", "cmx", "cpio", "cr2", "cur", "dat", "dcm", "deb", "dex", "djvu",
|
||||
"dll", "dmg", "dng", "doc", "docm", "docx", "dot", "dotm", "dra", "DS_Store", "dsk", "dts", "dtshd", "dvb", "dwg", "dxf", "ecelp4800", "ecelp7470",
|
||||
"ecelp9600", "egg", "eol", "eot", "epub", "exe", "f4v", "fbs", "fh", "fla", "flac", "flatpak", "fli", "flv", "fpx", "fst", "fvt", "g3", "gh", "gif",
|
||||
"gpg", "graffle", "gz", "gzip", "h261", "h263", "h264", "icns", "ico", "ief", "img", "ipa", "iso", "jar", "jpeg", "jpg", "jpgv", "jpm", "jxr", "key",
|
||||
"ktx", "lha", "lib", "lvp", "lz", "lzh", "lzma", "lzo", "m3u", "m4a", "m4v", "mar", "mdi", "mht", "mid", "midi", "mj2", "mka", "mkv", "mmr", "mng",
|
||||
"mobi", "mov", "movie", "mp3", "mp4", "mp4a", "mpeg", "mpg", "mpga", "msgpack", "mxu", "nef", "npx", "numbers", "nupkg", "o", "oga", "ogg", "ogv",
|
||||
"otf", "pages", "pbm", "pcx", "pdb", "pdf", "pea", "pgm", "pic", "png", "pnm", "pot", "potm", "potx", "ppa", "ppam", "ppm", "pps", "ppsm", "ppsx",
|
||||
"ppt", "pptm", "pptx", "psd", "pya", "pyc", "pyo", "pyv", "qt", "rar", "ras", "raw", "resources", "rgb", "rip", "rlc", "rmf", "rmvb", "rpm", "rtf",
|
||||
"rz", "s3m", "s7z", "scpt", "sgi", "shar", "sig", "sil", "sketch", "slk", "smv", "snap", "snk", "so", "stl", "sub", "suo", "swf", "tar", "tbz2", "tbz",
|
||||
"tga", "tgz", "thmx", "tif", "tiff", "tlz", "ttc", "ttf", "txz", "udf", "uvh", "uvi", "uvm", "uvp", "uvs", "uvu", "viv", "vob", "war", "wav", "wax",
|
||||
"wbmp", "wdp", "weba", "webm", "webp", "whl", "wim", "wm", "wma", "wmv", "wmx", "woff2", "woff", "wrm", "wvx", "xbm", "xif", "xla", "xlam", "xls",
|
||||
"xlsb", "xlsm", "xlsx", "xlt", "xltm", "xltx", "xm", "xmind", "xpi", "xpm", "xwd", "xz", "z", "zip", "zipx"
|
||||
]
|
|
@ -1,5 +1,3 @@
|
|||
BINARY_EXTENSIONS = ["png", "gif", "jpg", "pdf", "doc", "msgpack", "zip", "rar", "gz", "tar", "exe"]
|
||||
|
||||
class FileList extends Class
|
||||
constructor: (@site, @inner_path, @is_owner=false) ->
|
||||
@need_update = true
|
||||
|
@ -179,7 +177,7 @@ class FileList extends Class
|
|||
ext = item.name.split(".").pop()
|
||||
|
||||
is_editing = inner_path == Page.file_editor?.inner_path
|
||||
is_editable = not is_dir and item.size < 1024 * 1024 and ext not in BINARY_EXTENSIONS
|
||||
is_editable = not is_dir and item.size < 1024 * 1024 and ext not in window.BINARY_EXTENSIONS
|
||||
is_modified = @item_list.isModified(inner_path)
|
||||
is_added = @item_list.isAdded(inner_path)
|
||||
optional_info = @item_list.getOptionalInfo(inner_path)
|
||||
|
|
|
@ -1918,6 +1918,15 @@
|
|||
}));
|
||||
|
||||
|
||||
/* ---- Config.coffee ---- */
|
||||
|
||||
|
||||
(function() {
|
||||
window.BINARY_EXTENSIONS = ["3dm", "3ds", "3g2", "3gp", "7z", "a", "aac", "adp", "ai", "aif", "aiff", "alz", "ape", "apk", "appimage", "ar", "arj", "asc", "asf", "au", "avi", "bak", "baml", "bh", "bin", "bk", "bmp", "btif", "bz2", "bzip2", "cab", "caf", "cgm", "class", "cmx", "cpio", "cr2", "cur", "dat", "dcm", "deb", "dex", "djvu", "dll", "dmg", "dng", "doc", "docm", "docx", "dot", "dotm", "dra", "DS_Store", "dsk", "dts", "dtshd", "dvb", "dwg", "dxf", "ecelp4800", "ecelp7470", "ecelp9600", "egg", "eol", "eot", "epub", "exe", "f4v", "fbs", "fh", "fla", "flac", "flatpak", "fli", "flv", "fpx", "fst", "fvt", "g3", "gh", "gif", "gpg", "graffle", "gz", "gzip", "h261", "h263", "h264", "icns", "ico", "ief", "img", "ipa", "iso", "jar", "jpeg", "jpg", "jpgv", "jpm", "jxr", "key", "ktx", "lha", "lib", "lvp", "lz", "lzh", "lzma", "lzo", "m3u", "m4a", "m4v", "mar", "mdi", "mht", "mid", "midi", "mj2", "mka", "mkv", "mmr", "mng", "mobi", "mov", "movie", "mp3", "mp4", "mp4a", "mpeg", "mpg", "mpga", "msgpack", "mxu", "nef", "npx", "numbers", "nupkg", "o", "oga", "ogg", "ogv", "otf", "pages", "pbm", "pcx", "pdb", "pdf", "pea", "pgm", "pic", "png", "pnm", "pot", "potm", "potx", "ppa", "ppam", "ppm", "pps", "ppsm", "ppsx", "ppt", "pptm", "pptx", "psd", "pya", "pyc", "pyo", "pyv", "qt", "rar", "ras", "raw", "resources", "rgb", "rip", "rlc", "rmf", "rmvb", "rpm", "rtf", "rz", "s3m", "s7z", "scpt", "sgi", "shar", "sig", "sil", "sketch", "slk", "smv", "snap", "snk", "so", "stl", "sub", "suo", "swf", "tar", "tbz2", "tbz", "tga", "tgz", "thmx", "tif", "tiff", "tlz", "ttc", "ttf", "txz", "udf", "uvh", "uvi", "uvm", "uvp", "uvs", "uvu", "viv", "vob", "war", "wav", "wax", "wbmp", "wdp", "weba", "webm", "webp", "whl", "wim", "wm", "wma", "wmv", "wmx", "woff2", "woff", "wrm", "wvx", "xbm", "xif", "xla", "xlam", "xls", "xlsb", "xlsm", "xlsx", "xlt", "xltm", "xltx", "xm", "xmind", "xpi", "xpm", "xwd", "xz", "z", "zip", "zipx"];
|
||||
|
||||
}).call(this);
|
||||
|
||||
|
||||
/* ---- FileEditor.coffee ---- */
|
||||
|
||||
|
||||
|
@ -2187,7 +2196,6 @@
|
|||
|
||||
}).call(this);
|
||||
|
||||
|
||||
/* ---- FileItemList.coffee ---- */
|
||||
|
||||
|
||||
|
@ -2477,14 +2485,12 @@
|
|||
|
||||
|
||||
(function() {
|
||||
var BINARY_EXTENSIONS, FileList,
|
||||
var FileList,
|
||||
bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
|
||||
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
|
||||
hasProp = {}.hasOwnProperty,
|
||||
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
|
||||
|
||||
BINARY_EXTENSIONS = ["png", "gif", "jpg", "pdf", "doc", "msgpack", "zip", "rar", "gz", "tar", "exe"];
|
||||
|
||||
FileList = (function(superClass) {
|
||||
extend(FileList, superClass);
|
||||
|
||||
|
@ -2759,7 +2765,7 @@
|
|||
is_dir = (ref = item.type) === "dir" || ref === "parent";
|
||||
ext = item.name.split(".").pop();
|
||||
is_editing = inner_path === ((ref1 = Page.file_editor) != null ? ref1.inner_path : void 0);
|
||||
is_editable = !is_dir && item.size < 1024 * 1024 && indexOf.call(BINARY_EXTENSIONS, ext) < 0;
|
||||
is_editable = !is_dir && item.size < 1024 * 1024 && indexOf.call(window.BINARY_EXTENSIONS, ext) < 0;
|
||||
is_modified = this.item_list.isModified(inner_path);
|
||||
is_added = this.item_list.isAdded(inner_path);
|
||||
optional_info = this.item_list.getOptionalInfo(inner_path);
|
||||
|
|
|
@ -14,7 +14,7 @@ class Config(object):
|
|||
|
||||
def __init__(self, argv):
|
||||
self.version = "0.7.2"
|
||||
self.rev = 4538
|
||||
self.rev = 4555
|
||||
self.argv = argv
|
||||
self.action = None
|
||||
self.test_parser = None
|
||||
|
|
|
@ -7,6 +7,8 @@ import hashlib
|
|||
from util.Electrum import dbl_format
|
||||
from Config import config
|
||||
|
||||
import util.OpensslFindPatch
|
||||
|
||||
lib_verify_best = "sslcrypto"
|
||||
|
||||
from lib import sslcrypto
|
||||
|
@ -28,6 +30,8 @@ def loadLib(lib_name, silent=False):
|
|||
)
|
||||
elif lib_name == "sslcrypto":
|
||||
sslcurve = sslcurve_native
|
||||
if sslcurve_native == sslcurve_fallback:
|
||||
logging.warning("SSLCurve fallback loaded instead of native")
|
||||
elif lib_name == "sslcrypto_fallback":
|
||||
sslcurve = sslcurve_fallback
|
||||
|
||||
|
|
|
@ -28,7 +28,11 @@ def formatExceptionMessage(err):
|
|||
return "%s: %s" % (err_type, err_message)
|
||||
|
||||
|
||||
python_lib_dir = os.path.dirname(os.__file__)
|
||||
python_lib_dirs = [path.replace("\\", "/") for path in sys.path if re.sub(r".*[\\/]", "", path) in ("site-packages", "dist-packages")]
|
||||
python_lib_dirs.append(os.path.dirname(os.__file__).replace("\\", "/")) # TODO: check if returns the correct path for PyPy
|
||||
|
||||
root_dir = os.path.realpath(os.path.dirname(__file__) + "/../../")
|
||||
root_dir = root_dir.replace("\\", "/")
|
||||
|
||||
|
||||
def formatTraceback(items, limit=None, fold_builtin=True):
|
||||
|
@ -40,30 +44,63 @@ def formatTraceback(items, limit=None, fold_builtin=True):
|
|||
for path, line in items:
|
||||
i += 1
|
||||
is_last = i == len(items)
|
||||
dir_name, file_name = os.path.split(path.replace("\\", "/"))
|
||||
path = path.replace("\\", "/")
|
||||
|
||||
plugin_match = re.match(".*/plugins/(.+)$", dir_name)
|
||||
if plugin_match:
|
||||
file_title = "%s/%s" % (plugin_match.group(1), file_name)
|
||||
is_prev_builtin = False
|
||||
elif path.startswith(python_lib_dir):
|
||||
if is_prev_builtin and not is_last and fold_builtin:
|
||||
if path.startswith("src/gevent/"):
|
||||
file_title = "<gevent>/" + path[len("src/gevent/"):]
|
||||
is_builtin = True
|
||||
is_skippable_builtin = False
|
||||
elif path in ("<frozen importlib._bootstrap>", "<frozen importlib._bootstrap_external>"):
|
||||
file_title = "(importlib)"
|
||||
is_builtin = True
|
||||
is_skippable_builtin = True
|
||||
else:
|
||||
is_skippable_builtin = False
|
||||
for base in python_lib_dirs:
|
||||
if path.startswith(base + "/"):
|
||||
file_title = path[len(base + "/"):]
|
||||
module_name, *tail = file_title.split("/")
|
||||
if module_name.endswith(".py"):
|
||||
module_name = module_name[:-3]
|
||||
file_title = "/".join(["<%s>" % module_name] + tail)
|
||||
is_builtin = True
|
||||
break
|
||||
else:
|
||||
is_builtin = False
|
||||
for base in (root_dir + "/src", root_dir + "/plugins", root_dir):
|
||||
if path.startswith(base + "/"):
|
||||
file_title = path[len(base + "/"):]
|
||||
break
|
||||
else:
|
||||
# For unknown paths, do our best to hide absolute path
|
||||
file_title = path
|
||||
for needle in ("/zeronet/", "/core/"):
|
||||
if needle in file_title.lower():
|
||||
file_title = "?/" + file_title[file_title.lower().rindex(needle) + len(needle):]
|
||||
|
||||
# Path compression: A/AB/ABC/X/Y.py -> ABC/X/Y.py
|
||||
# E.g.: in 'Db/DbCursor.py' the directory part is unnecessary
|
||||
if not file_title.startswith("/"):
|
||||
prev_part = ""
|
||||
for i, part in enumerate(file_title.split("/") + [""]):
|
||||
if not part.startswith(prev_part):
|
||||
break
|
||||
prev_part = part
|
||||
file_title = "/".join(file_title.split("/")[i - 1:])
|
||||
|
||||
if is_skippable_builtin and fold_builtin:
|
||||
pass
|
||||
elif is_builtin and is_prev_builtin and not is_last and fold_builtin:
|
||||
if back[-1] != "...":
|
||||
back.append("...")
|
||||
continue
|
||||
else:
|
||||
file_title = path.replace(python_lib_dir, "").replace("\\", "/").strip("/").replace("site-packages/", "")
|
||||
is_prev_builtin = True
|
||||
else:
|
||||
file_title = file_name
|
||||
is_prev_builtin = False
|
||||
|
||||
if file_title == prev_file_title:
|
||||
back.append("%s" % line)
|
||||
else:
|
||||
back.append("%s line %s" % (file_title, line))
|
||||
|
||||
prev_file_title = file_title
|
||||
is_prev_builtin = is_builtin
|
||||
|
||||
if limit and i >= limit:
|
||||
back.append("...")
|
||||
|
|
|
@ -760,10 +760,6 @@ class FileServer(ConnectionServer):
|
|||
self.stream_server.start()
|
||||
except Exception as err:
|
||||
log.error("Error listening on: %s:%s: %s" % (self.ip, self.port, err))
|
||||
if "ui_server" in dir(sys.modules["main"]):
|
||||
log.debug("Stopping UI Server.")
|
||||
sys.modules["main"].ui_server.stop()
|
||||
return False
|
||||
|
||||
if config.debug:
|
||||
# Auto reload FileRequest on change
|
||||
|
|
52
src/Test/TestDebug.py
Normal file
52
src/Test/TestDebug.py
Normal file
|
@ -0,0 +1,52 @@
|
|||
from Debug import Debug
|
||||
import gevent
|
||||
import os
|
||||
import re
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
class TestDebug:
|
||||
@pytest.mark.parametrize("items,expected", [
|
||||
(["@/src/A/B/C.py:17"], ["A/B/C.py line 17"]), # basic test
|
||||
(["@/src/Db/Db.py:17"], ["Db.py line 17"]), # path compression
|
||||
(["%s:1" % __file__], ["TestDebug.py line 1"]),
|
||||
(["@/plugins/Chart/ChartDb.py:100"], ["ChartDb.py line 100"]), # plugins
|
||||
(["@/main.py:17"], ["main.py line 17"]), # root
|
||||
(["@\\src\\Db\\__init__.py:17"], ["Db/__init__.py line 17"]), # Windows paths
|
||||
(["<frozen importlib._bootstrap>:1"], []), # importlib builtins
|
||||
(["<frozen importlib._bootstrap_external>:1"], []), # importlib builtins
|
||||
(["/home/ivanq/ZeroNet/src/main.py:13"], ["?/src/main.py line 13"]), # best-effort anonymization
|
||||
(["C:\\ZeroNet\\core\\src\\main.py:13"], ["?/src/main.py line 13"]),
|
||||
(["/root/main.py:17"], ["/root/main.py line 17"]),
|
||||
(["{gevent}:13"], ["<gevent>/__init__.py line 13"]), # modules
|
||||
(["{os}:13"], ["<os> line 13"]), # python builtin modules
|
||||
(["src/gevent/event.py:17"], ["<gevent>/event.py line 17"]), # gevent-overriden __file__
|
||||
(["@/src/Db/Db.py:17", "@/src/Db/DbQuery.py:1"], ["Db.py line 17", "DbQuery.py line 1"]), # mutliple args
|
||||
(["@/src/Db/Db.py:17", "@/src/Db/Db.py:1"], ["Db.py line 17", "1"]), # same file
|
||||
(["{os}:1", "@/src/Db/Db.py:17"], ["<os> line 1", "Db.py line 17"]), # builtins
|
||||
(["{gevent}:1"] + ["{os}:3"] * 4 + ["@/src/Db/Db.py:17"], ["<gevent>/__init__.py line 1", "...", "Db.py line 17"])
|
||||
])
|
||||
def testFormatTraceback(self, items, expected):
|
||||
q_items = []
|
||||
for item in items:
|
||||
file, line = item.rsplit(":", 1)
|
||||
if file.startswith("@"):
|
||||
file = Debug.root_dir + file[1:]
|
||||
file = file.replace("{os}", os.__file__)
|
||||
file = file.replace("{gevent}", gevent.__file__)
|
||||
q_items.append((file, int(line)))
|
||||
assert Debug.formatTraceback(q_items) == expected
|
||||
|
||||
def testFormatException(self):
|
||||
try:
|
||||
raise ValueError("Test exception")
|
||||
except Exception:
|
||||
assert re.match(r"ValueError: Test exception in TestDebug.py line [0-9]+", Debug.formatException())
|
||||
try:
|
||||
os.path.abspath(1)
|
||||
except Exception:
|
||||
assert re.search(r"in TestDebug.py line [0-9]+ > <(posixpath|ntpath)> line ", Debug.formatException())
|
||||
|
||||
def testFormatStack(self):
|
||||
assert re.match(r"TestDebug.py line [0-9]+ > <_pytest>/python.py line [0-9]+", Debug.formatStack())
|
|
@ -8,11 +8,13 @@
|
|||
"or configure Tor to become a full member of the ZeroNet network.": "または、TorをZeroNetネットワークのメンバーになるように設定してください。",
|
||||
|
||||
"Select account you want to use in this site:": "このサイトで使用するアカウントを選択:",
|
||||
"No certificate": "証明書がありません",
|
||||
"currently selected": "現在選択中",
|
||||
"Unique to site": "サイト固有",
|
||||
|
||||
"Content signing failed": "コンテンツの署名に失敗",
|
||||
"Content publish queued for {0:.0f} seconds.": "コンテンツの公開は{0:.0f}秒のキューに入れられました。",
|
||||
"Content published to {0}/{1} peers.": "サイトの更新を通知済 {0}/{1} ピア",
|
||||
"Content published to {0} peers.": "{0}ピアに公開されたコンテンツ。",
|
||||
"No peers found, but your content is ready to access.": "ピアは見つかりませんでしたが、コンテンツにアクセスする準備ができました。",
|
||||
"Your network connection is restricted. Please, open <b>{0}</b> port": "ネットワーク接続が制限されています。ポート <b>{0}</b> を開いて、",
|
||||
|
@ -43,6 +45,7 @@
|
|||
"No peers found": "ピアが見つかりません",
|
||||
"Running out of size limit (": "サイズ制限を使い果たしました (",
|
||||
"Set limit to \" + site_info.next_size_limit + \"MB": "制限を \" + site_info.next_size_limit + \"MB に設定",
|
||||
"Cloning site...": "サイトを複製中…",
|
||||
"Site size limit changed to {0}MB": "サイトのサイズ制限が {0}MB に変更されました",
|
||||
" New version of this page has just released.<br>Reload to see the modified content.": " このページの新しいバージョンが公開されました。<br>変更されたコンテンツを見るには再読み込みしてください。",
|
||||
"This site requests permission:": "このサイトは権限を要求しています:",
|
||||
|
@ -52,6 +55,12 @@
|
|||
"Trackers announcing": "トラッカーをお知らせ",
|
||||
"Error": "エラー",
|
||||
"Done": "完了",
|
||||
"Tracker connection error detected.": "トラッカー接続エラーが検出されました。"
|
||||
"Tracker connection error detected.": "トラッカー接続エラーが検出されました。",
|
||||
|
||||
"Update <b>ZeroNet client</b> to latest version?": "<b>ZeroNetクライアント</b>を最新版に更新しますか?",
|
||||
"Update": "更新",
|
||||
"Restart <b>ZeroNet client</b>?": "ZeroNetクライアントを再起動しますか?",
|
||||
"Restart": "再起動",
|
||||
"Shut down <b>ZeroNet client</b>?": "<b>ZeroNetクライアント</b>を終了しますか?",
|
||||
"Shut down": "終了"
|
||||
}
|
||||
|
|
|
@ -33,6 +33,9 @@ content_types = {
|
|||
"html": "text/html",
|
||||
"js": "application/javascript",
|
||||
"json": "application/json",
|
||||
"oga": "audio/ogg",
|
||||
"ogg": "application/ogg",
|
||||
"ogv": "video/ogg",
|
||||
"sig": "application/pgp-signature",
|
||||
"txt": "text/plain",
|
||||
"webmanifest": "application/manifest+json",
|
||||
|
|
|
@ -9,9 +9,16 @@ class Infopanel
|
|||
else
|
||||
@open()
|
||||
|
||||
unfold: =>
|
||||
@elem.toggleClass("unfolded")
|
||||
return false
|
||||
|
||||
updateEvents: =>
|
||||
@elem.off("click")
|
||||
@elem.find(".close").off("click")
|
||||
@elem.find(".line").off("click")
|
||||
|
||||
@elem.find(".line").on("click", @unfold)
|
||||
|
||||
if @elem.hasClass("closed")
|
||||
@elem.on "click", =>
|
||||
|
|
|
@ -658,7 +658,7 @@ class Wrapper
|
|||
else
|
||||
@announcer_line = @loading.printLine(status_line)
|
||||
|
||||
if status_db.error.length > (status_db.announced.length + status_db.announcing.length)
|
||||
if status_db.error.length > (status_db.announced.length + status_db.announcing.length) and status_db.announced.length < 3
|
||||
@loading.showTrackerTorBridge(@server_info)
|
||||
|
||||
updateProgress: (site_info) ->
|
||||
|
|
|
@ -131,6 +131,7 @@ a { color: black }
|
|||
padding: 4px; border-top-left-radius: 6px; border-bottom-left-radius: 6px; font-size: 10px;
|
||||
opacity: 0; margin-left: 0px; pointer-events: none; transition: all 0.6s;
|
||||
}
|
||||
.infopanel.unfolded .message .line { overflow: visible; white-space: normal; }
|
||||
.body-sidebar .infopanel { right: 425px; }
|
||||
.body-sidebar .infopanel.closed { right: 0px; }
|
||||
|
||||
|
|
|
@ -144,6 +144,7 @@ a { color: black }
|
|||
padding: 4px; border-top-left-radius: 6px; border-bottom-left-radius: 6px; font-size: 10px;
|
||||
opacity: 0; margin-left: 0px; pointer-events: none; -webkit-transition: all 0.6s; -moz-transition: all 0.6s; -o-transition: all 0.6s; -ms-transition: all 0.6s; transition: all 0.6s ;
|
||||
}
|
||||
.infopanel.unfolded .message .line { overflow: visible; white-space: normal; }
|
||||
.body-sidebar .infopanel { right: 425px; }
|
||||
.body-sidebar .infopanel.closed { right: 0px; }
|
||||
|
||||
|
|
|
@ -548,6 +548,7 @@ $.extend( $.easing,
|
|||
this.close = bind(this.close, this);
|
||||
this.hide = bind(this.hide, this);
|
||||
this.updateEvents = bind(this.updateEvents, this);
|
||||
this.unfold = bind(this.unfold, this);
|
||||
this.show = bind(this.show, this);
|
||||
this.visible = false;
|
||||
}
|
||||
|
@ -564,9 +565,16 @@ $.extend( $.easing,
|
|||
}
|
||||
};
|
||||
|
||||
Infopanel.prototype.unfold = function() {
|
||||
this.elem.toggleClass("unfolded");
|
||||
return false;
|
||||
};
|
||||
|
||||
Infopanel.prototype.updateEvents = function() {
|
||||
this.elem.off("click");
|
||||
this.elem.find(".close").off("click");
|
||||
this.elem.find(".line").off("click");
|
||||
this.elem.find(".line").on("click", this.unfold);
|
||||
if (this.elem.hasClass("closed")) {
|
||||
return this.elem.on("click", (function(_this) {
|
||||
return function() {
|
||||
|
@ -779,7 +787,6 @@ $.extend( $.easing,
|
|||
|
||||
}).call(this);
|
||||
|
||||
|
||||
/* ---- Notifications.coffee ---- */
|
||||
|
||||
|
||||
|
@ -1910,7 +1917,7 @@ $.extend( $.easing,
|
|||
} else {
|
||||
this.announcer_line = this.loading.printLine(status_line);
|
||||
}
|
||||
if (status_db.error.length > (status_db.announced.length + status_db.announcing.length)) {
|
||||
if (status_db.error.length > (status_db.announced.length + status_db.announcing.length) && status_db.announced.length < 3) {
|
||||
return this.loading.showTrackerTorBridge(this.server_info);
|
||||
}
|
||||
};
|
||||
|
@ -2004,6 +2011,7 @@ $.extend( $.easing,
|
|||
|
||||
}).call(this);
|
||||
|
||||
|
||||
/* ---- WrapperZeroFrame.coffee ---- */
|
||||
|
||||
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 1.3 KiB |
1
src/Ui/media/img/logo-white.svg
Normal file
1
src/Ui/media/img/logo-white.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg version="1.1" viewBox="0 0 2050 2050" xmlns="http://www.w3.org/2000/svg"><g fill="white"><path d="m299 1211v-787.6l725.7-423.4 725.3 420-175.34 325.7-549.86-340.7-373.5 221v381.2z"/><path d="m1749.4 842.6v787.6l-725.4 423.3-724.5-419.5 219.38-278.79 505.12 293.39 373.2-221.2v-381z"/><path d="M299.5 1634L1750 786.4V420L299 1267.4z"/></g></svg>
|
After Width: | Height: | Size: 350 B |
|
@ -38,7 +38,7 @@ else if (window.opener && window.opener.location.toString()) {
|
|||
|
||||
<!-- Fixed button -->
|
||||
<div class='fixbutton'>
|
||||
<div class='fixbutton-text'><img width=22 src='/uimedia/img/logo-white.png'/></div>
|
||||
<div class='fixbutton-text'><img width=30 src='/uimedia/img/logo-white.svg'/></div>
|
||||
<div class='fixbutton-burger'>≡</div>
|
||||
<a class='fixbutton-bg' href="{homepage}/"></a>
|
||||
</div>
|
||||
|
|
|
@ -579,7 +579,7 @@ class Actions(object):
|
|||
func_name = "test" + test_name[0].upper() + test_name[1:]
|
||||
if hasattr(self, func_name):
|
||||
func = getattr(self, func_name)
|
||||
print("- Running %s" % test_name, end="")
|
||||
print("- Running test: %s" % test_name, end="")
|
||||
s = time.time()
|
||||
ret = func(*args, **kwargs)
|
||||
if type(ret) is types.GeneratorType:
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import logging
|
||||
import os
|
||||
import sys
|
||||
from ctypes.util import find_library
|
||||
from lib.sslcrypto.openssl import discovery
|
||||
import ctypes.util
|
||||
|
||||
from Config import config
|
||||
|
||||
find_library_original = ctypes.util.find_library
|
||||
|
||||
|
||||
def getOpensslPath():
|
||||
if config.openssl_lib_file:
|
||||
|
@ -47,11 +48,22 @@ def getOpensslPath():
|
|||
logging.debug("OpenSSL lib not found in: %s (%s)" % (path, err))
|
||||
|
||||
lib_path = (
|
||||
find_library('ssl.so') or find_library('ssl') or
|
||||
find_library('crypto') or find_library('libcrypto') or 'libeay32'
|
||||
find_library_original('ssl.so') or find_library_original('ssl') or
|
||||
find_library_original('crypto') or find_library_original('libcrypto') or 'libeay32'
|
||||
)
|
||||
|
||||
return lib_path
|
||||
|
||||
|
||||
discovery.discover = getOpensslPath
|
||||
def patchCtypesOpensslFindLibrary():
|
||||
def findLibraryPatched(name):
|
||||
if name in ("ssl", "crypto", "libeay32"):
|
||||
lib_path = getOpensslPath()
|
||||
return lib_path
|
||||
else:
|
||||
return find_library_original(name)
|
||||
|
||||
ctypes.util.find_library = findLibraryPatched
|
||||
|
||||
|
||||
patchCtypesOpensslFindLibrary()
|
||||
|
|
|
@ -339,7 +339,7 @@ def _communicate_with_igd(port=15441,
|
|||
success = True
|
||||
break
|
||||
|
||||
# Wait another 10sec for competition or any positibe result
|
||||
# Wait another 10sec for competition or any positive result
|
||||
for _ in range(10):
|
||||
all_done = all([thread.value is not None for thread in threads])
|
||||
any_succeed = any([thread.value for thread in threads])
|
||||
|
|
Loading…
Reference in a new issue