2015-08-16 11:51:00 +02:00
|
|
|
import re
|
|
|
|
import os
|
2019-03-15 21:06:59 +01:00
|
|
|
import html
|
2015-08-16 11:51:00 +02:00
|
|
|
import sys
|
|
|
|
import math
|
|
|
|
import time
|
2016-03-09 15:30:04 +01:00
|
|
|
import json
|
2019-03-15 21:06:59 +01:00
|
|
|
import io
|
2019-05-21 15:52:44 +02:00
|
|
|
import urllib
|
|
|
|
import urllib.parse
|
2015-08-16 11:51:00 +02:00
|
|
|
|
2016-11-07 22:58:11 +01:00
|
|
|
import gevent
|
2015-08-16 11:51:00 +02:00
|
|
|
|
2019-11-19 01:44:26 +01:00
|
|
|
import util
|
2015-08-16 11:51:00 +02:00
|
|
|
from Config import config
|
|
|
|
from Plugin import PluginManager
|
|
|
|
from Debug import Debug
|
2016-11-18 20:13:12 +01:00
|
|
|
from Translate import Translate
|
2016-11-07 22:58:11 +01:00
|
|
|
from util import helper
|
2019-08-26 03:20:07 +02:00
|
|
|
from util.Flag import flag
|
2019-03-15 21:06:59 +01:00
|
|
|
from .ZipStream import ZipStream
|
2015-08-16 11:51:00 +02:00
|
|
|
|
2019-08-02 16:05:19 +02:00
|
|
|
plugin_dir = os.path.dirname(__file__)
|
2015-08-16 11:51:00 +02:00
|
|
|
media_dir = plugin_dir + "/media"
|
|
|
|
|
|
|
|
loc_cache = {}
|
2016-11-18 20:13:12 +01:00
|
|
|
if "_" not in locals():
|
2016-12-03 13:20:26 +01:00
|
|
|
_ = Translate(plugin_dir + "/languages/")
|
2015-08-16 11:51:00 +02:00
|
|
|
|
|
|
|
|
|
|
|
@PluginManager.registerTo("UiRequest")
|
|
|
|
class UiRequestPlugin(object):
|
|
|
|
# Inject our resources to end of original file streams
|
|
|
|
def actionUiMedia(self, path):
|
|
|
|
if path == "/uimedia/all.js" or path == "/uimedia/all.css":
|
|
|
|
# First yield the original file and header
|
|
|
|
body_generator = super(UiRequestPlugin, self).actionUiMedia(path)
|
|
|
|
for part in body_generator:
|
|
|
|
yield part
|
|
|
|
|
|
|
|
# Append our media file to the end
|
|
|
|
ext = re.match(".*(js|css)$", path).group(1)
|
|
|
|
plugin_media_file = "%s/all.%s" % (media_dir, ext)
|
|
|
|
if config.debug:
|
|
|
|
# If debugging merge *.css to all.css and *.js to all.js
|
|
|
|
from Debug import DebugMedia
|
|
|
|
DebugMedia.merge(plugin_media_file)
|
2016-11-18 20:13:12 +01:00
|
|
|
if ext == "js":
|
2019-03-15 21:06:59 +01:00
|
|
|
yield _.translateData(open(plugin_media_file).read()).encode("utf8")
|
2016-11-18 20:13:12 +01:00
|
|
|
else:
|
|
|
|
for part in self.actionFile(plugin_media_file, send_header=False):
|
|
|
|
yield part
|
2015-08-16 11:51:00 +02:00
|
|
|
elif path.startswith("/uimedia/globe/"): # Serve WebGL globe files
|
|
|
|
file_name = re.match(".*/(.*)", path).group(1)
|
2019-04-16 11:34:55 +02:00
|
|
|
plugin_media_file = "%s_globe/%s" % (media_dir, file_name)
|
2015-08-16 11:51:00 +02:00
|
|
|
if config.debug and path.endswith("all.js"):
|
|
|
|
# If debugging merge *.css to all.css and *.js to all.js
|
|
|
|
from Debug import DebugMedia
|
|
|
|
DebugMedia.merge(plugin_media_file)
|
|
|
|
for part in self.actionFile(plugin_media_file):
|
|
|
|
yield part
|
|
|
|
else:
|
|
|
|
for part in super(UiRequestPlugin, self).actionUiMedia(path):
|
|
|
|
yield part
|
|
|
|
|
2018-05-02 02:31:31 +02:00
|
|
|
def actionZip(self):
|
|
|
|
address = self.get["address"]
|
|
|
|
site = self.server.site_manager.get(address)
|
|
|
|
if not site:
|
|
|
|
return self.error404("Site not found")
|
|
|
|
|
2019-05-21 15:52:44 +02:00
|
|
|
title = site.content_manager.contents.get("content.json", {}).get("title", "")
|
2018-05-02 02:31:31 +02:00
|
|
|
filename = "%s-backup-%s.zip" % (title, time.strftime("%Y-%m-%d_%H_%M"))
|
2019-05-21 15:52:44 +02:00
|
|
|
filename_quoted = urllib.parse.quote(filename)
|
|
|
|
self.sendHeader(content_type="application/zip", extra_headers={'Content-Disposition': 'attachment; filename="%s"' % filename_quoted})
|
2018-05-02 02:31:31 +02:00
|
|
|
|
|
|
|
return self.streamZip(site.storage.getPath("."))
|
|
|
|
|
2019-05-30 04:27:01 +02:00
|
|
|
def streamZip(self, dir_path):
|
|
|
|
zs = ZipStream(dir_path)
|
2018-05-02 02:31:31 +02:00
|
|
|
while 1:
|
|
|
|
data = zs.read()
|
|
|
|
if not data:
|
|
|
|
break
|
|
|
|
yield data
|
|
|
|
|
|
|
|
|
2015-08-16 11:51:00 +02:00
|
|
|
@PluginManager.registerTo("UiWebsocket")
|
|
|
|
class UiWebsocketPlugin(object):
|
|
|
|
def sidebarRenderPeerStats(self, body, site):
|
2019-03-15 21:06:59 +01:00
|
|
|
connected = len([peer for peer in list(site.peers.values()) if peer.connection and peer.connection.connected])
|
|
|
|
connectable = len([peer_id for peer_id in list(site.peers.keys()) if not peer_id.endswith(":0")])
|
|
|
|
onion = len([peer_id for peer_id in list(site.peers.keys()) if ".onion" in peer_id])
|
|
|
|
local = len([peer for peer in list(site.peers.values()) if helper.isPrivateIp(peer.ip)])
|
2015-08-16 11:51:00 +02:00
|
|
|
peers_total = len(site.peers)
|
2017-05-06 18:08:32 +02:00
|
|
|
|
|
|
|
# Add myself
|
2019-04-15 15:06:25 +02:00
|
|
|
if site.isServing():
|
2017-05-06 18:08:32 +02:00
|
|
|
peers_total += 1
|
2019-01-23 02:11:31 +01:00
|
|
|
if any(site.connection_server.port_opened.values()):
|
2017-05-06 18:08:32 +02:00
|
|
|
connectable += 1
|
|
|
|
if site.connection_server.tor_manager.start_onions:
|
|
|
|
onion += 1
|
|
|
|
|
2015-08-16 11:51:00 +02:00
|
|
|
if peers_total:
|
|
|
|
percent_connected = float(connected) / peers_total
|
|
|
|
percent_connectable = float(connectable) / peers_total
|
Rev957, Sidebar displays onion peers in graph, Sidebar display bad file retry number, Sidebar site Update/Pause/Delete, Ratelimit sidebar update, Encoded typo, Fix onion findHashId, More retry for bad files, Log file path errors, Testcase for self findhashIds, Testcase for Tor findHashId, Better Tor version parse, UiWebsocket callback on update/pause/resume/delete, Skip invalid postMessage messages
2016-03-09 00:48:57 +01:00
|
|
|
percent_onion = float(onion) / peers_total
|
2015-08-16 11:51:00 +02:00
|
|
|
else:
|
Rev957, Sidebar displays onion peers in graph, Sidebar display bad file retry number, Sidebar site Update/Pause/Delete, Ratelimit sidebar update, Encoded typo, Fix onion findHashId, More retry for bad files, Log file path errors, Testcase for self findhashIds, Testcase for Tor findHashId, Better Tor version parse, UiWebsocket callback on update/pause/resume/delete, Skip invalid postMessage messages
2016-03-09 00:48:57 +01:00
|
|
|
percent_connectable = percent_connected = percent_onion = 0
|
2016-11-18 20:13:54 +01:00
|
|
|
|
2018-03-10 02:03:12 +01:00
|
|
|
if local:
|
2019-03-15 21:06:59 +01:00
|
|
|
local_html = _("<li class='color-yellow'><span>{_[Local]}:</span><b>{local}</b></li>")
|
2018-03-10 02:03:12 +01:00
|
|
|
else:
|
|
|
|
local_html = ""
|
|
|
|
|
2018-08-13 02:43:23 +02:00
|
|
|
peer_ips = [peer.key for peer in site.getConnectablePeers(20, allow_private=False)]
|
|
|
|
peer_ips.sort(key=lambda peer_ip: ".onion:" in peer_ip)
|
2018-07-19 20:42:04 +02:00
|
|
|
copy_link = "http://127.0.0.1:43110/%s/?zeronet_peers=%s" % (
|
|
|
|
site.content_manager.contents["content.json"].get("domain", site.address),
|
2018-08-13 02:43:23 +02:00
|
|
|
",".join(peer_ips)
|
2018-07-19 20:42:04 +02:00
|
|
|
)
|
|
|
|
|
2019-03-15 21:06:59 +01:00
|
|
|
body.append(_("""
|
2015-08-16 11:51:00 +02:00
|
|
|
<li>
|
2018-07-19 20:42:04 +02:00
|
|
|
<label>
|
|
|
|
{_[Peers]}
|
2018-09-21 02:17:53 +02:00
|
|
|
<small class="label-right"><a href='{copy_link}' id='link-copypeers' class='link-right'>{_[Copy to clipboard]}</a></small>
|
2018-07-19 20:42:04 +02:00
|
|
|
</label>
|
2015-08-16 11:51:00 +02:00
|
|
|
<ul class='graph'>
|
2016-11-18 20:13:54 +01:00
|
|
|
<li style='width: 100%' class='total back-black' title="{_[Total peers]}"></li>
|
|
|
|
<li style='width: {percent_connectable:.0%}' class='connectable back-blue' title='{_[Connectable peers]}'></li>
|
|
|
|
<li style='width: {percent_onion:.0%}' class='connected back-purple' title='{_[Onion]}'></li>
|
|
|
|
<li style='width: {percent_connected:.0%}' class='connected back-green' title='{_[Connected peers]}'></li>
|
2015-08-16 11:51:00 +02:00
|
|
|
</ul>
|
|
|
|
<ul class='graph-legend'>
|
2016-11-18 20:13:54 +01:00
|
|
|
<li class='color-green'><span>{_[Connected]}:</span><b>{connected}</b></li>
|
|
|
|
<li class='color-blue'><span>{_[Connectable]}:</span><b>{connectable}</b></li>
|
|
|
|
<li class='color-purple'><span>{_[Onion]}:</span><b>{onion}</b></li>
|
2018-03-10 02:03:12 +01:00
|
|
|
{local_html}
|
2016-11-18 20:13:54 +01:00
|
|
|
<li class='color-black'><span>{_[Total]}:</span><b>{peers_total}</b></li>
|
2015-08-16 11:51:00 +02:00
|
|
|
</ul>
|
|
|
|
</li>
|
2018-11-26 00:16:19 +01:00
|
|
|
""".replace("{local_html}", local_html)))
|
2015-08-16 11:51:00 +02:00
|
|
|
|
|
|
|
def sidebarRenderTransferStats(self, body, site):
|
|
|
|
recv = float(site.settings.get("bytes_recv", 0)) / 1024 / 1024
|
|
|
|
sent = float(site.settings.get("bytes_sent", 0)) / 1024 / 1024
|
|
|
|
transfer_total = recv + sent
|
|
|
|
if transfer_total:
|
|
|
|
percent_recv = recv / transfer_total
|
|
|
|
percent_sent = sent / transfer_total
|
|
|
|
else:
|
|
|
|
percent_recv = 0.5
|
|
|
|
percent_sent = 0.5
|
2016-11-18 20:13:54 +01:00
|
|
|
|
2019-03-15 21:06:59 +01:00
|
|
|
body.append(_("""
|
2015-08-16 11:51:00 +02:00
|
|
|
<li>
|
2016-11-18 20:13:54 +01:00
|
|
|
<label>{_[Data transfer]}</label>
|
2015-08-16 11:51:00 +02:00
|
|
|
<ul class='graph graph-stacked'>
|
2016-11-18 20:13:54 +01:00
|
|
|
<li style='width: {percent_recv:.0%}' class='received back-yellow' title="{_[Received bytes]}"></li>
|
|
|
|
<li style='width: {percent_sent:.0%}' class='sent back-green' title="{_[Sent bytes]}"></li>
|
2015-08-16 11:51:00 +02:00
|
|
|
</ul>
|
|
|
|
<ul class='graph-legend'>
|
2016-11-18 20:13:54 +01:00
|
|
|
<li class='color-yellow'><span>{_[Received]}:</span><b>{recv:.2f}MB</b></li>
|
|
|
|
<li class='color-green'<span>{_[Sent]}:</span><b>{sent:.2f}MB</b></li>
|
2015-08-16 11:51:00 +02:00
|
|
|
</ul>
|
|
|
|
</li>
|
2016-11-18 20:13:54 +01:00
|
|
|
"""))
|
2015-08-16 11:51:00 +02:00
|
|
|
|
|
|
|
def sidebarRenderFileStats(self, body, site):
|
2019-03-15 21:06:59 +01:00
|
|
|
body.append(_("""
|
2018-05-02 02:31:31 +02:00
|
|
|
<li>
|
|
|
|
<label>
|
|
|
|
{_[Files]}
|
2018-09-21 02:17:53 +02:00
|
|
|
<small class="label-right"><a href='#Site+directory' id='link-directory' class='link-right'>{_[Open site directory]}</a>
|
2018-07-19 20:40:55 +02:00
|
|
|
<a href='/ZeroNet-Internal/Zip?address={site.address}' id='link-zip' class='link-right' download='site.zip'>{_[Save as .zip]}</a></small>
|
2018-05-02 02:31:31 +02:00
|
|
|
</label>
|
|
|
|
<ul class='graph graph-stacked'>
|
|
|
|
"""))
|
2015-08-16 11:51:00 +02:00
|
|
|
|
|
|
|
extensions = (
|
|
|
|
("html", "yellow"),
|
|
|
|
("css", "orange"),
|
|
|
|
("js", "purple"),
|
2016-11-18 20:13:54 +01:00
|
|
|
("Image", "green"),
|
2016-09-04 17:46:09 +02:00
|
|
|
("json", "darkblue"),
|
2016-11-18 20:13:54 +01:00
|
|
|
("User data", "blue"),
|
|
|
|
("Other", "white"),
|
|
|
|
("Total", "black")
|
2015-08-16 11:51:00 +02:00
|
|
|
)
|
|
|
|
# Collect stats
|
|
|
|
size_filetypes = {}
|
|
|
|
size_total = 0
|
2016-09-04 17:46:09 +02:00
|
|
|
contents = site.content_manager.listContents() # Without user files
|
|
|
|
for inner_path in contents:
|
|
|
|
content = site.content_manager.contents[inner_path]
|
2018-12-05 11:05:43 +01:00
|
|
|
if "files" not in content or content["files"] is None:
|
2015-08-16 11:51:00 +02:00
|
|
|
continue
|
2019-03-15 21:06:59 +01:00
|
|
|
for file_name, file_details in list(content["files"].items()):
|
2015-08-16 11:51:00 +02:00
|
|
|
size_total += file_details["size"]
|
|
|
|
ext = file_name.split(".")[-1]
|
|
|
|
size_filetypes[ext] = size_filetypes.get(ext, 0) + file_details["size"]
|
2016-04-27 11:14:15 +02:00
|
|
|
|
2016-09-04 17:46:09 +02:00
|
|
|
# Get user file sizes
|
|
|
|
size_user_content = site.content_manager.contents.execute(
|
|
|
|
"SELECT SUM(size) + SUM(size_files) AS size FROM content WHERE ?",
|
|
|
|
{"not__inner_path": contents}
|
|
|
|
).fetchone()["size"]
|
|
|
|
if not size_user_content:
|
|
|
|
size_user_content = 0
|
2016-11-18 20:13:54 +01:00
|
|
|
size_filetypes["User data"] = size_user_content
|
2016-09-04 17:46:09 +02:00
|
|
|
size_total += size_user_content
|
|
|
|
|
2016-04-27 11:14:15 +02:00
|
|
|
# The missing difference is content.json sizes
|
|
|
|
if "json" in size_filetypes:
|
2016-09-04 17:46:09 +02:00
|
|
|
size_filetypes["json"] += max(0, site.settings["size"] - size_total)
|
2016-04-27 11:14:15 +02:00
|
|
|
size_total = size_other = site.settings["size"]
|
2015-08-16 11:51:00 +02:00
|
|
|
|
|
|
|
# Bar
|
2017-07-18 22:39:48 +02:00
|
|
|
for extension, color in extensions:
|
2016-11-18 20:13:54 +01:00
|
|
|
if extension == "Total":
|
2015-08-16 11:51:00 +02:00
|
|
|
continue
|
2016-11-18 20:13:54 +01:00
|
|
|
if extension == "Other":
|
2016-09-04 17:46:09 +02:00
|
|
|
size = max(0, size_other)
|
2016-11-18 20:13:54 +01:00
|
|
|
elif extension == "Image":
|
2015-08-16 11:51:00 +02:00
|
|
|
size = size_filetypes.get("jpg", 0) + size_filetypes.get("png", 0) + size_filetypes.get("gif", 0)
|
|
|
|
size_other -= size
|
|
|
|
else:
|
|
|
|
size = size_filetypes.get(extension, 0)
|
|
|
|
size_other -= size
|
2016-01-15 19:50:02 +01:00
|
|
|
if size_total == 0:
|
|
|
|
percent = 0
|
|
|
|
else:
|
|
|
|
percent = 100 * (float(size) / size_total)
|
2016-03-06 19:28:22 +01:00
|
|
|
percent = math.floor(percent * 100) / 100 # Floor to 2 digits
|
|
|
|
body.append(
|
2019-03-15 21:06:59 +01:00
|
|
|
"""<li style='width: %.2f%%' class='%s back-%s' title="%s"></li>""" %
|
2016-11-18 20:13:54 +01:00
|
|
|
(percent, _[extension], color, _[extension])
|
2016-03-06 19:28:22 +01:00
|
|
|
)
|
2015-08-16 11:51:00 +02:00
|
|
|
|
|
|
|
# Legend
|
|
|
|
body.append("</ul><ul class='graph-legend'>")
|
|
|
|
for extension, color in extensions:
|
2016-11-18 20:13:54 +01:00
|
|
|
if extension == "Other":
|
2016-09-04 17:46:09 +02:00
|
|
|
size = max(0, size_other)
|
2016-11-18 20:13:54 +01:00
|
|
|
elif extension == "Image":
|
2015-08-16 11:51:00 +02:00
|
|
|
size = size_filetypes.get("jpg", 0) + size_filetypes.get("png", 0) + size_filetypes.get("gif", 0)
|
2016-12-30 18:53:24 +01:00
|
|
|
elif extension == "Total":
|
2015-08-16 11:51:00 +02:00
|
|
|
size = size_total
|
|
|
|
else:
|
|
|
|
size = size_filetypes.get(extension, 0)
|
|
|
|
|
|
|
|
if extension == "js":
|
|
|
|
title = "javascript"
|
|
|
|
else:
|
|
|
|
title = extension
|
|
|
|
|
|
|
|
if size > 1024 * 1024 * 10: # Format as mB is more than 10mB
|
|
|
|
size_formatted = "%.0fMB" % (size / 1024 / 1024)
|
|
|
|
else:
|
|
|
|
size_formatted = "%.0fkB" % (size / 1024)
|
|
|
|
|
2019-03-15 21:06:59 +01:00
|
|
|
body.append("<li class='color-%s'><span>%s:</span><b>%s</b></li>" % (color, _[title], size_formatted))
|
2015-08-16 11:51:00 +02:00
|
|
|
|
|
|
|
body.append("</ul></li>")
|
|
|
|
|
|
|
|
def sidebarRenderSizeLimit(self, body, site):
|
2016-11-07 22:58:11 +01:00
|
|
|
free_space = helper.getFreeSpace() / 1024 / 1024
|
2015-08-16 11:51:00 +02:00
|
|
|
size = float(site.settings["size"]) / 1024 / 1024
|
|
|
|
size_limit = site.getSizeLimit()
|
|
|
|
percent_used = size / size_limit
|
2016-11-18 20:13:54 +01:00
|
|
|
|
2019-03-15 21:06:59 +01:00
|
|
|
body.append(_("""
|
2015-08-16 11:51:00 +02:00
|
|
|
<li>
|
2019-03-15 21:06:59 +01:00
|
|
|
<label>{_[Size limit]} <small>({_[limit used]}: {percent_used:.0%}, {_[free space]}: {free_space:,.0f}MB)</small></label>
|
2016-02-23 01:36:47 +01:00
|
|
|
<input type='text' class='text text-num' value="{size_limit}" id='input-sitelimit'/><span class='text-post'>MB</span>
|
2016-11-18 20:13:54 +01:00
|
|
|
<a href='#Set' class='button' id='button-sitelimit'>{_[Set]}</a>
|
2015-08-16 11:51:00 +02:00
|
|
|
</li>
|
2016-11-18 20:13:54 +01:00
|
|
|
"""))
|
2015-08-16 11:51:00 +02:00
|
|
|
|
Rev571, Optional file sizes to sidebar, Download all optional files option in sidebar, Optional file number in peer stats, Delete removed or changed optional files, Auto download optional files if autodownloadoptional checked, SiteReload command, Peer use global file server if no site defined, Allow browser cache video files, Allow more keepalive connections, Gevent 1.1 ranged request bugfix, Dont sent optional files details on websocket, Remove files from workermanager tasks if no longer in bad_files, Notify local client about changes on external siteSign
2015-11-09 00:44:03 +01:00
|
|
|
def sidebarRenderOptionalFileStats(self, body, site):
|
2016-11-07 23:48:48 +01:00
|
|
|
size_total = float(site.settings["size_optional"])
|
|
|
|
size_downloaded = float(site.settings["optional_downloaded"])
|
Rev571, Optional file sizes to sidebar, Download all optional files option in sidebar, Optional file number in peer stats, Delete removed or changed optional files, Auto download optional files if autodownloadoptional checked, SiteReload command, Peer use global file server if no site defined, Allow browser cache video files, Allow more keepalive connections, Gevent 1.1 ranged request bugfix, Dont sent optional files details on websocket, Remove files from workermanager tasks if no longer in bad_files, Notify local client about changes on external siteSign
2015-11-09 00:44:03 +01:00
|
|
|
|
|
|
|
if not size_total:
|
|
|
|
return False
|
|
|
|
|
|
|
|
percent_downloaded = size_downloaded / size_total
|
|
|
|
|
|
|
|
size_formatted_total = size_total / 1024 / 1024
|
|
|
|
size_formatted_downloaded = size_downloaded / 1024 / 1024
|
|
|
|
|
2019-03-15 21:06:59 +01:00
|
|
|
body.append(_("""
|
Rev571, Optional file sizes to sidebar, Download all optional files option in sidebar, Optional file number in peer stats, Delete removed or changed optional files, Auto download optional files if autodownloadoptional checked, SiteReload command, Peer use global file server if no site defined, Allow browser cache video files, Allow more keepalive connections, Gevent 1.1 ranged request bugfix, Dont sent optional files details on websocket, Remove files from workermanager tasks if no longer in bad_files, Notify local client about changes on external siteSign
2015-11-09 00:44:03 +01:00
|
|
|
<li>
|
2016-11-18 20:13:54 +01:00
|
|
|
<label>{_[Optional files]}</label>
|
Rev571, Optional file sizes to sidebar, Download all optional files option in sidebar, Optional file number in peer stats, Delete removed or changed optional files, Auto download optional files if autodownloadoptional checked, SiteReload command, Peer use global file server if no site defined, Allow browser cache video files, Allow more keepalive connections, Gevent 1.1 ranged request bugfix, Dont sent optional files details on websocket, Remove files from workermanager tasks if no longer in bad_files, Notify local client about changes on external siteSign
2015-11-09 00:44:03 +01:00
|
|
|
<ul class='graph'>
|
2016-11-18 20:13:54 +01:00
|
|
|
<li style='width: 100%' class='total back-black' title="{_[Total size]}"></li>
|
|
|
|
<li style='width: {percent_downloaded:.0%}' class='connected back-green' title='{_[Downloaded files]}'></li>
|
Rev571, Optional file sizes to sidebar, Download all optional files option in sidebar, Optional file number in peer stats, Delete removed or changed optional files, Auto download optional files if autodownloadoptional checked, SiteReload command, Peer use global file server if no site defined, Allow browser cache video files, Allow more keepalive connections, Gevent 1.1 ranged request bugfix, Dont sent optional files details on websocket, Remove files from workermanager tasks if no longer in bad_files, Notify local client about changes on external siteSign
2015-11-09 00:44:03 +01:00
|
|
|
</ul>
|
|
|
|
<ul class='graph-legend'>
|
2016-11-18 20:13:54 +01:00
|
|
|
<li class='color-green'><span>{_[Downloaded]}:</span><b>{size_formatted_downloaded:.2f}MB</b></li>
|
|
|
|
<li class='color-black'><span>{_[Total]}:</span><b>{size_formatted_total:.2f}MB</b></li>
|
Rev571, Optional file sizes to sidebar, Download all optional files option in sidebar, Optional file number in peer stats, Delete removed or changed optional files, Auto download optional files if autodownloadoptional checked, SiteReload command, Peer use global file server if no site defined, Allow browser cache video files, Allow more keepalive connections, Gevent 1.1 ranged request bugfix, Dont sent optional files details on websocket, Remove files from workermanager tasks if no longer in bad_files, Notify local client about changes on external siteSign
2015-11-09 00:44:03 +01:00
|
|
|
</ul>
|
|
|
|
</li>
|
2016-11-18 20:13:54 +01:00
|
|
|
"""))
|
Rev571, Optional file sizes to sidebar, Download all optional files option in sidebar, Optional file number in peer stats, Delete removed or changed optional files, Auto download optional files if autodownloadoptional checked, SiteReload command, Peer use global file server if no site defined, Allow browser cache video files, Allow more keepalive connections, Gevent 1.1 ranged request bugfix, Dont sent optional files details on websocket, Remove files from workermanager tasks if no longer in bad_files, Notify local client about changes on external siteSign
2015-11-09 00:44:03 +01:00
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
def sidebarRenderOptionalFileSettings(self, body, site):
|
|
|
|
if self.site.settings.get("autodownloadoptional"):
|
|
|
|
checked = "checked='checked'"
|
|
|
|
else:
|
|
|
|
checked = ""
|
2016-11-18 20:13:54 +01:00
|
|
|
|
2019-03-15 21:06:59 +01:00
|
|
|
body.append(_("""
|
Rev571, Optional file sizes to sidebar, Download all optional files option in sidebar, Optional file number in peer stats, Delete removed or changed optional files, Auto download optional files if autodownloadoptional checked, SiteReload command, Peer use global file server if no site defined, Allow browser cache video files, Allow more keepalive connections, Gevent 1.1 ranged request bugfix, Dont sent optional files details on websocket, Remove files from workermanager tasks if no longer in bad_files, Notify local client about changes on external siteSign
2015-11-09 00:44:03 +01:00
|
|
|
<li>
|
2020-02-07 16:40:04 +01:00
|
|
|
<label>{_[Help distribute added optional files]}</label>
|
Rev571, Optional file sizes to sidebar, Download all optional files option in sidebar, Optional file number in peer stats, Delete removed or changed optional files, Auto download optional files if autodownloadoptional checked, SiteReload command, Peer use global file server if no site defined, Allow browser cache video files, Allow more keepalive connections, Gevent 1.1 ranged request bugfix, Dont sent optional files details on websocket, Remove files from workermanager tasks if no longer in bad_files, Notify local client about changes on external siteSign
2015-11-09 00:44:03 +01:00
|
|
|
<input type="checkbox" class="checkbox" id="checkbox-autodownloadoptional" {checked}/><div class="checkbox-skin"></div>
|
2016-11-18 20:13:54 +01:00
|
|
|
"""))
|
Rev571, Optional file sizes to sidebar, Download all optional files option in sidebar, Optional file number in peer stats, Delete removed or changed optional files, Auto download optional files if autodownloadoptional checked, SiteReload command, Peer use global file server if no site defined, Allow browser cache video files, Allow more keepalive connections, Gevent 1.1 ranged request bugfix, Dont sent optional files details on websocket, Remove files from workermanager tasks if no longer in bad_files, Notify local client about changes on external siteSign
2015-11-09 00:44:03 +01:00
|
|
|
|
2019-08-09 13:17:48 +02:00
|
|
|
if hasattr(config, "autodownload_bigfile_size_limit"):
|
|
|
|
autodownload_bigfile_size_limit = int(site.settings.get("autodownload_bigfile_size_limit", config.autodownload_bigfile_size_limit))
|
|
|
|
body.append(_("""
|
|
|
|
<div class='settings-autodownloadoptional'>
|
|
|
|
<label>{_[Auto download big file size limit]}</label>
|
|
|
|
<input type='text' class='text text-num' value="{autodownload_bigfile_size_limit}" id='input-autodownload_bigfile_size_limit'/><span class='text-post'>MB</span>
|
|
|
|
<a href='#Set' class='button' id='button-autodownload_bigfile_size_limit'>{_[Set]}</a>
|
2020-02-07 16:40:04 +01:00
|
|
|
<a href='#Download+previous' class='button' id='button-autodownload_previous'>{_[Download previous files]}</a>
|
2019-08-09 13:17:48 +02:00
|
|
|
</div>
|
|
|
|
"""))
|
2018-03-10 02:02:58 +01:00
|
|
|
body.append("</li>")
|
|
|
|
|
Rev903, FeedQuery command only available for ADMIN sites, Show bad files in sidebar, Log unknown messages, Add and check inner_path and site address on sign/verify, Better peer cleanup limit, Log site load times, Testcase for address and inner_path verification, Re-sign testsite with new fields, Fix unnecessary loading screen display when browsing sub-folder with index.html, Fix safari notification width
2016-02-18 11:22:21 +01:00
|
|
|
def sidebarRenderBadFiles(self, body, site):
|
2019-03-15 21:06:59 +01:00
|
|
|
body.append(_("""
|
Rev903, FeedQuery command only available for ADMIN sites, Show bad files in sidebar, Log unknown messages, Add and check inner_path and site address on sign/verify, Better peer cleanup limit, Log site load times, Testcase for address and inner_path verification, Re-sign testsite with new fields, Fix unnecessary loading screen display when browsing sub-folder with index.html, Fix safari notification width
2016-02-18 11:22:21 +01:00
|
|
|
<li>
|
2018-03-10 02:03:30 +01:00
|
|
|
<label>{_[Needs to be updated]}:</label>
|
Rev903, FeedQuery command only available for ADMIN sites, Show bad files in sidebar, Log unknown messages, Add and check inner_path and site address on sign/verify, Better peer cleanup limit, Log site load times, Testcase for address and inner_path verification, Re-sign testsite with new fields, Fix unnecessary loading screen display when browsing sub-folder with index.html, Fix safari notification width
2016-02-18 11:22:21 +01:00
|
|
|
<ul class='filelist'>
|
2016-11-18 20:13:54 +01:00
|
|
|
"""))
|
Rev903, FeedQuery command only available for ADMIN sites, Show bad files in sidebar, Log unknown messages, Add and check inner_path and site address on sign/verify, Better peer cleanup limit, Log site load times, Testcase for address and inner_path verification, Re-sign testsite with new fields, Fix unnecessary loading screen display when browsing sub-folder with index.html, Fix safari notification width
2016-02-18 11:22:21 +01:00
|
|
|
|
2016-03-16 00:35:58 +01:00
|
|
|
i = 0
|
2019-03-15 21:06:59 +01:00
|
|
|
for bad_file, tries in site.bad_files.items():
|
2016-03-16 00:35:58 +01:00
|
|
|
i += 1
|
2019-03-15 21:06:59 +01:00
|
|
|
body.append(_("""<li class='color-red' title="{bad_file_path} ({tries})">{bad_filename}</li>""", {
|
2018-11-26 00:16:53 +01:00
|
|
|
"bad_file_path": bad_file,
|
|
|
|
"bad_filename": helper.getFilename(bad_file),
|
2018-10-15 13:02:13 +02:00
|
|
|
"tries": _.pluralize(tries, "{} try", "{} tries")
|
2016-11-18 20:13:54 +01:00
|
|
|
}))
|
2016-03-16 00:35:58 +01:00
|
|
|
if i > 30:
|
|
|
|
break
|
|
|
|
|
|
|
|
if len(site.bad_files) > 30:
|
2016-11-18 20:13:54 +01:00
|
|
|
num_bad_files = len(site.bad_files) - 30
|
2019-03-15 21:06:59 +01:00
|
|
|
body.append(_("""<li class='color-red'>{_[+ {num_bad_files} more]}</li>""", nested=True))
|
Rev903, FeedQuery command only available for ADMIN sites, Show bad files in sidebar, Log unknown messages, Add and check inner_path and site address on sign/verify, Better peer cleanup limit, Log site load times, Testcase for address and inner_path verification, Re-sign testsite with new fields, Fix unnecessary loading screen display when browsing sub-folder with index.html, Fix safari notification width
2016-02-18 11:22:21 +01:00
|
|
|
|
|
|
|
body.append("""
|
|
|
|
</ul>
|
|
|
|
</li>
|
|
|
|
""")
|
|
|
|
|
2015-08-16 11:51:00 +02:00
|
|
|
def sidebarRenderDbOptions(self, body, site):
|
2016-04-18 02:24:14 +02:00
|
|
|
if site.storage.db:
|
|
|
|
inner_path = site.storage.getInnerPath(site.storage.db.db_path)
|
|
|
|
size = float(site.storage.getSize(inner_path)) / 1024
|
|
|
|
feeds = len(site.storage.db.schema.get("feeds", {}))
|
|
|
|
else:
|
2019-03-15 21:06:59 +01:00
|
|
|
inner_path = _["No database found"]
|
2016-04-18 02:24:14 +02:00
|
|
|
size = 0.0
|
|
|
|
feeds = 0
|
2015-08-16 11:51:00 +02:00
|
|
|
|
2019-03-15 21:06:59 +01:00
|
|
|
body.append(_("""
|
2015-08-16 11:51:00 +02:00
|
|
|
<li>
|
2016-11-18 20:13:54 +01:00
|
|
|
<label>{_[Database]} <small>({size:.2f}kB, {_[search feeds]}: {_[{feeds} query]})</small></label>
|
|
|
|
<div class='flex'>
|
2016-11-24 19:50:30 +01:00
|
|
|
<input type='text' class='text disabled' value="{inner_path}" disabled='disabled'/>
|
2016-11-18 20:13:54 +01:00
|
|
|
<a href='#Reload' id="button-dbreload" class='button'>{_[Reload]}</a>
|
|
|
|
<a href='#Rebuild' id="button-dbrebuild" class='button'>{_[Rebuild]}</a>
|
|
|
|
</div>
|
2015-08-16 11:51:00 +02:00
|
|
|
</li>
|
2016-11-18 20:13:54 +01:00
|
|
|
""", nested=True))
|
2015-08-16 11:51:00 +02:00
|
|
|
|
|
|
|
def sidebarRenderIdentity(self, body, site):
|
2019-01-26 20:42:46 +01:00
|
|
|
auth_address = self.user.getAuthAddress(self.site.address, create=False)
|
2016-03-09 15:30:04 +01:00
|
|
|
rules = self.site.content_manager.getRules("data/users/%s/content.json" % auth_address)
|
|
|
|
if rules and rules.get("max_size"):
|
|
|
|
quota = rules["max_size"] / 1024
|
2016-08-26 11:41:17 +02:00
|
|
|
try:
|
|
|
|
content = site.content_manager.contents["data/users/%s/content.json" % auth_address]
|
2019-03-15 21:06:59 +01:00
|
|
|
used = len(json.dumps(content)) + sum([file["size"] for file in list(content["files"].values())])
|
2016-08-26 11:41:17 +02:00
|
|
|
except:
|
|
|
|
used = 0
|
2016-03-09 15:30:04 +01:00
|
|
|
used = used / 1024
|
|
|
|
else:
|
|
|
|
quota = used = 0
|
|
|
|
|
2019-03-15 21:06:59 +01:00
|
|
|
body.append(_("""
|
2015-08-16 11:51:00 +02:00
|
|
|
<li>
|
2016-11-18 20:13:54 +01:00
|
|
|
<label>{_[Identity address]} <small>({_[limit used]}: {used:.2f}kB / {quota:.2f}kB)</small></label>
|
|
|
|
<div class='flex'>
|
|
|
|
<span class='input text disabled'>{auth_address}</span>
|
|
|
|
<a href='#Change' class='button' id='button-identity'>{_[Change]}</a>
|
|
|
|
</div>
|
2015-08-16 11:51:00 +02:00
|
|
|
</li>
|
2016-11-18 20:13:54 +01:00
|
|
|
"""))
|
2015-08-16 11:51:00 +02:00
|
|
|
|
Rev957, Sidebar displays onion peers in graph, Sidebar display bad file retry number, Sidebar site Update/Pause/Delete, Ratelimit sidebar update, Encoded typo, Fix onion findHashId, More retry for bad files, Log file path errors, Testcase for self findhashIds, Testcase for Tor findHashId, Better Tor version parse, UiWebsocket callback on update/pause/resume/delete, Skip invalid postMessage messages
2016-03-09 00:48:57 +01:00
|
|
|
def sidebarRenderControls(self, body, site):
|
2019-01-26 20:42:46 +01:00
|
|
|
auth_address = self.user.getAuthAddress(self.site.address, create=False)
|
Rev957, Sidebar displays onion peers in graph, Sidebar display bad file retry number, Sidebar site Update/Pause/Delete, Ratelimit sidebar update, Encoded typo, Fix onion findHashId, More retry for bad files, Log file path errors, Testcase for self findhashIds, Testcase for Tor findHashId, Better Tor version parse, UiWebsocket callback on update/pause/resume/delete, Skip invalid postMessage messages
2016-03-09 00:48:57 +01:00
|
|
|
if self.site.settings["serving"]:
|
|
|
|
class_pause = ""
|
|
|
|
class_resume = "hidden"
|
|
|
|
else:
|
|
|
|
class_pause = "hidden"
|
|
|
|
class_resume = ""
|
|
|
|
|
2019-03-15 21:06:59 +01:00
|
|
|
body.append(_("""
|
Rev957, Sidebar displays onion peers in graph, Sidebar display bad file retry number, Sidebar site Update/Pause/Delete, Ratelimit sidebar update, Encoded typo, Fix onion findHashId, More retry for bad files, Log file path errors, Testcase for self findhashIds, Testcase for Tor findHashId, Better Tor version parse, UiWebsocket callback on update/pause/resume/delete, Skip invalid postMessage messages
2016-03-09 00:48:57 +01:00
|
|
|
<li>
|
2016-11-18 20:13:54 +01:00
|
|
|
<label>{_[Site control]}</label>
|
|
|
|
<a href='#Update' class='button noupdate' id='button-update'>{_[Update]}</a>
|
|
|
|
<a href='#Pause' class='button {class_pause}' id='button-pause'>{_[Pause]}</a>
|
|
|
|
<a href='#Resume' class='button {class_resume}' id='button-resume'>{_[Resume]}</a>
|
|
|
|
<a href='#Delete' class='button noupdate' id='button-delete'>{_[Delete]}</a>
|
Rev957, Sidebar displays onion peers in graph, Sidebar display bad file retry number, Sidebar site Update/Pause/Delete, Ratelimit sidebar update, Encoded typo, Fix onion findHashId, More retry for bad files, Log file path errors, Testcase for self findhashIds, Testcase for Tor findHashId, Better Tor version parse, UiWebsocket callback on update/pause/resume/delete, Skip invalid postMessage messages
2016-03-09 00:48:57 +01:00
|
|
|
</li>
|
2016-11-18 20:13:54 +01:00
|
|
|
"""))
|
Rev957, Sidebar displays onion peers in graph, Sidebar display bad file retry number, Sidebar site Update/Pause/Delete, Ratelimit sidebar update, Encoded typo, Fix onion findHashId, More retry for bad files, Log file path errors, Testcase for self findhashIds, Testcase for Tor findHashId, Better Tor version parse, UiWebsocket callback on update/pause/resume/delete, Skip invalid postMessage messages
2016-03-09 00:48:57 +01:00
|
|
|
|
2018-07-07 08:15:40 +02:00
|
|
|
donate_key = site.content_manager.contents.get("content.json", {}).get("donate", True)
|
2018-07-07 17:55:20 +02:00
|
|
|
site_address = self.site.address
|
2019-03-15 21:06:59 +01:00
|
|
|
body.append(_("""
|
2018-07-07 17:55:20 +02:00
|
|
|
<li>
|
|
|
|
<label>{_[Site address]}</label><br>
|
|
|
|
<div class='flex'>
|
|
|
|
<span class='input text disabled'>{site_address}</span>
|
|
|
|
"""))
|
2018-07-07 08:15:40 +02:00
|
|
|
if donate_key == False or donate_key == "":
|
|
|
|
pass
|
2019-03-15 21:06:59 +01:00
|
|
|
elif (type(donate_key) == str or type(donate_key) == str) and len(donate_key) > 0:
|
|
|
|
body.append(_("""
|
2018-07-07 17:55:20 +02:00
|
|
|
</div>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
<label>{_[Donate]}</label><br>
|
|
|
|
<div class='flex'>
|
2018-11-26 00:16:53 +01:00
|
|
|
{donate_key}
|
2018-07-07 08:15:40 +02:00
|
|
|
"""))
|
|
|
|
else:
|
2019-03-15 21:06:59 +01:00
|
|
|
body.append(_("""
|
2018-07-07 17:55:20 +02:00
|
|
|
<a href='bitcoin:{site_address}' class='button' id='button-donate'>{_[Donate]}</a>
|
2018-07-07 08:15:40 +02:00
|
|
|
"""))
|
2019-03-15 21:06:59 +01:00
|
|
|
body.append(_("""
|
2018-07-07 17:55:20 +02:00
|
|
|
</div>
|
|
|
|
</li>
|
|
|
|
"""))
|
2016-04-06 13:40:45 +02:00
|
|
|
|
2015-08-16 11:51:00 +02:00
|
|
|
def sidebarRenderOwnedCheckbox(self, body, site):
|
|
|
|
if self.site.settings["own"]:
|
|
|
|
checked = "checked='checked'"
|
|
|
|
else:
|
|
|
|
checked = ""
|
|
|
|
|
2019-03-15 21:06:59 +01:00
|
|
|
body.append(_("""
|
2016-11-18 20:13:54 +01:00
|
|
|
<h2 class='owned-title'>{_[This is my site]}</h2>
|
2015-08-16 11:51:00 +02:00
|
|
|
<input type="checkbox" class="checkbox" id="checkbox-owned" {checked}/><div class="checkbox-skin"></div>
|
2016-11-18 20:13:54 +01:00
|
|
|
"""))
|
2015-08-16 11:51:00 +02:00
|
|
|
|
|
|
|
def sidebarRenderOwnSettings(self, body, site):
|
2018-11-26 00:16:53 +01:00
|
|
|
title = site.content_manager.contents.get("content.json", {}).get("title", "")
|
|
|
|
description = site.content_manager.contents.get("content.json", {}).get("description", "")
|
2015-08-16 11:51:00 +02:00
|
|
|
|
2019-03-15 21:06:59 +01:00
|
|
|
body.append(_("""
|
2015-08-16 11:51:00 +02:00
|
|
|
<li>
|
2016-11-18 20:13:54 +01:00
|
|
|
<label for='settings-title'>{_[Site title]}</label>
|
2015-08-16 11:51:00 +02:00
|
|
|
<input type='text' class='text' value="{title}" id='settings-title'/>
|
|
|
|
</li>
|
|
|
|
|
|
|
|
<li>
|
2016-11-18 20:13:54 +01:00
|
|
|
<label for='settings-description'>{_[Site description]}</label>
|
2015-08-16 11:51:00 +02:00
|
|
|
<input type='text' class='text' value="{description}" id='settings-description'/>
|
|
|
|
</li>
|
|
|
|
|
|
|
|
<li>
|
2016-11-18 20:13:54 +01:00
|
|
|
<a href='#Save' class='button' id='button-settings'>{_[Save site settings]}</a>
|
2015-08-16 11:51:00 +02:00
|
|
|
</li>
|
2016-11-18 20:13:54 +01:00
|
|
|
"""))
|
2015-08-16 11:51:00 +02:00
|
|
|
|
|
|
|
def sidebarRenderContents(self, body, site):
|
2019-01-26 20:42:46 +01:00
|
|
|
has_privatekey = bool(self.user.getSiteData(site.address, create=False).get("privatekey"))
|
2018-09-21 02:17:53 +02:00
|
|
|
if has_privatekey:
|
2019-09-18 19:49:53 +02:00
|
|
|
tag_privatekey = _("{_[Private key saved.]} <a href='#Forget+private+key' id='privatekey-forget' class='link-right'>{_[Forget]}</a>")
|
2018-09-21 02:17:53 +02:00
|
|
|
else:
|
2019-03-15 21:06:59 +01:00
|
|
|
tag_privatekey = _("<a href='#Add+private+key' id='privatekey-add' class='link-right'>{_[Add saved private key]}</a>")
|
2018-09-21 02:17:53 +02:00
|
|
|
|
2019-03-15 21:06:59 +01:00
|
|
|
body.append(_("""
|
2015-08-16 11:51:00 +02:00
|
|
|
<li>
|
2018-09-21 02:17:53 +02:00
|
|
|
<label>{_[Content publishing]} <small class='label-right'>{tag_privatekey}</small></label>
|
2018-11-26 00:16:19 +01:00
|
|
|
""".replace("{tag_privatekey}", tag_privatekey)))
|
2016-04-25 02:17:28 +02:00
|
|
|
|
|
|
|
# Choose content you want to sign
|
2019-03-15 21:06:59 +01:00
|
|
|
body.append(_("""
|
2018-01-21 18:14:12 +01:00
|
|
|
<div class='flex'>
|
|
|
|
<input type='text' class='text' value="content.json" id='input-contents'/>
|
|
|
|
<a href='#Sign-and-Publish' id='button-sign-publish' class='button'>{_[Sign and publish]}</a>
|
|
|
|
<a href='#Sign-or-Publish' id='menu-sign-publish'>\u22EE</a>
|
|
|
|
</div>
|
|
|
|
"""))
|
|
|
|
|
2016-04-25 02:17:28 +02:00
|
|
|
contents = ["content.json"]
|
2019-03-15 21:06:59 +01:00
|
|
|
contents += list(site.content_manager.contents.get("content.json", {}).get("includes", {}).keys())
|
|
|
|
body.append(_("<div class='contents'>{_[Choose]}: "))
|
2016-12-14 00:43:46 +01:00
|
|
|
for content in contents:
|
2018-12-04 01:45:01 +01:00
|
|
|
body.append(_("<a href='{content}' class='contents-content'>{content}</a> "))
|
2016-12-14 00:43:46 +01:00
|
|
|
body.append("</div>")
|
2018-01-21 18:14:12 +01:00
|
|
|
body.append("</li>")
|
2015-08-16 11:51:00 +02:00
|
|
|
|
2019-08-26 03:20:07 +02:00
|
|
|
@flag.admin
|
2015-08-16 11:51:00 +02:00
|
|
|
def actionSidebarGetHtmlTag(self, to):
|
|
|
|
site = self.site
|
|
|
|
|
|
|
|
body = []
|
|
|
|
|
|
|
|
body.append("<div>")
|
2017-07-29 13:44:54 +02:00
|
|
|
body.append("<a href='#Close' class='close'>×</a>")
|
2019-03-15 21:06:59 +01:00
|
|
|
body.append("<h1>%s</h1>" % html.escape(site.content_manager.contents.get("content.json", {}).get("title", ""), True))
|
2015-08-16 11:51:00 +02:00
|
|
|
|
|
|
|
body.append("<div class='globe loading'></div>")
|
|
|
|
|
|
|
|
body.append("<ul class='fields'>")
|
|
|
|
|
|
|
|
self.sidebarRenderPeerStats(body, site)
|
|
|
|
self.sidebarRenderTransferStats(body, site)
|
|
|
|
self.sidebarRenderFileStats(body, site)
|
|
|
|
self.sidebarRenderSizeLimit(body, site)
|
Rev571, Optional file sizes to sidebar, Download all optional files option in sidebar, Optional file number in peer stats, Delete removed or changed optional files, Auto download optional files if autodownloadoptional checked, SiteReload command, Peer use global file server if no site defined, Allow browser cache video files, Allow more keepalive connections, Gevent 1.1 ranged request bugfix, Dont sent optional files details on websocket, Remove files from workermanager tasks if no longer in bad_files, Notify local client about changes on external siteSign
2015-11-09 00:44:03 +01:00
|
|
|
has_optional = self.sidebarRenderOptionalFileStats(body, site)
|
|
|
|
if has_optional:
|
|
|
|
self.sidebarRenderOptionalFileSettings(body, site)
|
2015-08-16 11:51:00 +02:00
|
|
|
self.sidebarRenderDbOptions(body, site)
|
|
|
|
self.sidebarRenderIdentity(body, site)
|
Rev957, Sidebar displays onion peers in graph, Sidebar display bad file retry number, Sidebar site Update/Pause/Delete, Ratelimit sidebar update, Encoded typo, Fix onion findHashId, More retry for bad files, Log file path errors, Testcase for self findhashIds, Testcase for Tor findHashId, Better Tor version parse, UiWebsocket callback on update/pause/resume/delete, Skip invalid postMessage messages
2016-03-09 00:48:57 +01:00
|
|
|
self.sidebarRenderControls(body, site)
|
|
|
|
if site.bad_files:
|
|
|
|
self.sidebarRenderBadFiles(body, site)
|
2015-08-16 11:51:00 +02:00
|
|
|
|
|
|
|
self.sidebarRenderOwnedCheckbox(body, site)
|
|
|
|
body.append("<div class='settings-owned'>")
|
|
|
|
self.sidebarRenderOwnSettings(body, site)
|
|
|
|
self.sidebarRenderContents(body, site)
|
|
|
|
body.append("</div>")
|
|
|
|
body.append("</ul>")
|
|
|
|
body.append("</div>")
|
|
|
|
|
2017-12-31 14:10:00 +01:00
|
|
|
body.append("<div class='menu template'>")
|
|
|
|
body.append("<a href='#'' class='menu-item template'>Template</a>")
|
|
|
|
body.append("</div>")
|
|
|
|
|
2015-08-16 11:51:00 +02:00
|
|
|
self.response(to, "".join(body))
|
|
|
|
|
|
|
|
def downloadGeoLiteDb(self, db_path):
|
|
|
|
import gzip
|
|
|
|
import shutil
|
Version 0.3.5, Rev830, Full Tor mode support with hidden services, Onion stats in Sidebar, GeoDB download fix using Tor, Gray out disabled sites in Stats page, Tor hidden service status in stat page, Benchmark sha256, Skyts tracker out expodie in, 2 new tracker using ZeroNet protocol, Keep SSL cert option between restarts, SSL Certificate pinning support for connections, Site lock support for connections, Certificate pinned connections using implicit SSL, Flood protection whitelist support, Foreign keys support for DB layer, Not support for SQL query helper, 0 length file get bugfix, Pex onion address support, Faster port testing, Faster uPnP port opening, Need connections more often on owned sites, Delay ZeroHello startup message if port check or Tor manager not ready yet, Use lockfiles to avoid double start, Save original socket on proxy monkey patching to get ability to connect localhost directly, Handle atomic write errors, Broken gevent https workaround helper, Rsa crypt functions, Plugin to Bootstrap using ZeroNet protocol
2016-01-05 00:20:52 +01:00
|
|
|
from util import helper
|
2015-08-16 11:51:00 +02:00
|
|
|
|
2019-05-30 04:27:40 +02:00
|
|
|
if config.offline:
|
|
|
|
return False
|
|
|
|
|
2015-08-16 11:51:00 +02:00
|
|
|
self.log.info("Downloading GeoLite2 City database...")
|
2017-10-21 11:01:57 +02:00
|
|
|
self.cmd("progress", ["geolite-info", _["Downloading GeoLite2 City database (one time only, ~20MB)..."], 0])
|
Version 0.3.5, Rev830, Full Tor mode support with hidden services, Onion stats in Sidebar, GeoDB download fix using Tor, Gray out disabled sites in Stats page, Tor hidden service status in stat page, Benchmark sha256, Skyts tracker out expodie in, 2 new tracker using ZeroNet protocol, Keep SSL cert option between restarts, SSL Certificate pinning support for connections, Site lock support for connections, Certificate pinned connections using implicit SSL, Flood protection whitelist support, Foreign keys support for DB layer, Not support for SQL query helper, 0 length file get bugfix, Pex onion address support, Faster port testing, Faster uPnP port opening, Need connections more often on owned sites, Delay ZeroHello startup message if port check or Tor manager not ready yet, Use lockfiles to avoid double start, Save original socket on proxy monkey patching to get ability to connect localhost directly, Handle atomic write errors, Broken gevent https workaround helper, Rsa crypt functions, Plugin to Bootstrap using ZeroNet protocol
2016-01-05 00:20:52 +01:00
|
|
|
db_urls = [
|
2020-01-04 16:55:08 +01:00
|
|
|
"https://raw.githubusercontent.com/aemr3/GeoLite2-Database/master/GeoLite2-City.mmdb.gz",
|
Version 0.3.5, Rev830, Full Tor mode support with hidden services, Onion stats in Sidebar, GeoDB download fix using Tor, Gray out disabled sites in Stats page, Tor hidden service status in stat page, Benchmark sha256, Skyts tracker out expodie in, 2 new tracker using ZeroNet protocol, Keep SSL cert option between restarts, SSL Certificate pinning support for connections, Site lock support for connections, Certificate pinned connections using implicit SSL, Flood protection whitelist support, Foreign keys support for DB layer, Not support for SQL query helper, 0 length file get bugfix, Pex onion address support, Faster port testing, Faster uPnP port opening, Need connections more often on owned sites, Delay ZeroHello startup message if port check or Tor manager not ready yet, Use lockfiles to avoid double start, Save original socket on proxy monkey patching to get ability to connect localhost directly, Handle atomic write errors, Broken gevent https workaround helper, Rsa crypt functions, Plugin to Bootstrap using ZeroNet protocol
2016-01-05 00:20:52 +01:00
|
|
|
"https://raw.githubusercontent.com/texnikru/GeoLite2-Database/master/GeoLite2-City.mmdb.gz"
|
|
|
|
]
|
|
|
|
for db_url in db_urls:
|
2019-03-15 21:06:59 +01:00
|
|
|
downloadl_err = None
|
Version 0.3.5, Rev830, Full Tor mode support with hidden services, Onion stats in Sidebar, GeoDB download fix using Tor, Gray out disabled sites in Stats page, Tor hidden service status in stat page, Benchmark sha256, Skyts tracker out expodie in, 2 new tracker using ZeroNet protocol, Keep SSL cert option between restarts, SSL Certificate pinning support for connections, Site lock support for connections, Certificate pinned connections using implicit SSL, Flood protection whitelist support, Foreign keys support for DB layer, Not support for SQL query helper, 0 length file get bugfix, Pex onion address support, Faster port testing, Faster uPnP port opening, Need connections more often on owned sites, Delay ZeroHello startup message if port check or Tor manager not ready yet, Use lockfiles to avoid double start, Save original socket on proxy monkey patching to get ability to connect localhost directly, Handle atomic write errors, Broken gevent https workaround helper, Rsa crypt functions, Plugin to Bootstrap using ZeroNet protocol
2016-01-05 00:20:52 +01:00
|
|
|
try:
|
|
|
|
# Download
|
|
|
|
response = helper.httpRequest(db_url)
|
2017-10-21 11:01:57 +02:00
|
|
|
data_size = response.getheader('content-length')
|
|
|
|
data_recv = 0
|
2019-03-15 21:06:59 +01:00
|
|
|
data = io.BytesIO()
|
Version 0.3.5, Rev830, Full Tor mode support with hidden services, Onion stats in Sidebar, GeoDB download fix using Tor, Gray out disabled sites in Stats page, Tor hidden service status in stat page, Benchmark sha256, Skyts tracker out expodie in, 2 new tracker using ZeroNet protocol, Keep SSL cert option between restarts, SSL Certificate pinning support for connections, Site lock support for connections, Certificate pinned connections using implicit SSL, Flood protection whitelist support, Foreign keys support for DB layer, Not support for SQL query helper, 0 length file get bugfix, Pex onion address support, Faster port testing, Faster uPnP port opening, Need connections more often on owned sites, Delay ZeroHello startup message if port check or Tor manager not ready yet, Use lockfiles to avoid double start, Save original socket on proxy monkey patching to get ability to connect localhost directly, Handle atomic write errors, Broken gevent https workaround helper, Rsa crypt functions, Plugin to Bootstrap using ZeroNet protocol
2016-01-05 00:20:52 +01:00
|
|
|
while True:
|
|
|
|
buff = response.read(1024 * 512)
|
|
|
|
if not buff:
|
|
|
|
break
|
|
|
|
data.write(buff)
|
2017-10-21 11:01:57 +02:00
|
|
|
data_recv += 1024 * 512
|
|
|
|
if data_size:
|
|
|
|
progress = int(float(data_recv) / int(data_size) * 100)
|
|
|
|
self.cmd("progress", ["geolite-info", _["Downloading GeoLite2 City database (one time only, ~20MB)..."], progress])
|
Version 0.3.5, Rev830, Full Tor mode support with hidden services, Onion stats in Sidebar, GeoDB download fix using Tor, Gray out disabled sites in Stats page, Tor hidden service status in stat page, Benchmark sha256, Skyts tracker out expodie in, 2 new tracker using ZeroNet protocol, Keep SSL cert option between restarts, SSL Certificate pinning support for connections, Site lock support for connections, Certificate pinned connections using implicit SSL, Flood protection whitelist support, Foreign keys support for DB layer, Not support for SQL query helper, 0 length file get bugfix, Pex onion address support, Faster port testing, Faster uPnP port opening, Need connections more often on owned sites, Delay ZeroHello startup message if port check or Tor manager not ready yet, Use lockfiles to avoid double start, Save original socket on proxy monkey patching to get ability to connect localhost directly, Handle atomic write errors, Broken gevent https workaround helper, Rsa crypt functions, Plugin to Bootstrap using ZeroNet protocol
2016-01-05 00:20:52 +01:00
|
|
|
self.log.info("GeoLite2 City database downloaded (%s bytes), unpacking..." % data.tell())
|
|
|
|
data.seek(0)
|
|
|
|
|
|
|
|
# Unpack
|
|
|
|
with gzip.GzipFile(fileobj=data) as gzip_file:
|
|
|
|
shutil.copyfileobj(gzip_file, open(db_path, "wb"))
|
|
|
|
|
2017-10-21 11:01:57 +02:00
|
|
|
self.cmd("progress", ["geolite-info", _["GeoLite2 City database downloaded!"], 100])
|
Version 0.3.5, Rev830, Full Tor mode support with hidden services, Onion stats in Sidebar, GeoDB download fix using Tor, Gray out disabled sites in Stats page, Tor hidden service status in stat page, Benchmark sha256, Skyts tracker out expodie in, 2 new tracker using ZeroNet protocol, Keep SSL cert option between restarts, SSL Certificate pinning support for connections, Site lock support for connections, Certificate pinned connections using implicit SSL, Flood protection whitelist support, Foreign keys support for DB layer, Not support for SQL query helper, 0 length file get bugfix, Pex onion address support, Faster port testing, Faster uPnP port opening, Need connections more often on owned sites, Delay ZeroHello startup message if port check or Tor manager not ready yet, Use lockfiles to avoid double start, Save original socket on proxy monkey patching to get ability to connect localhost directly, Handle atomic write errors, Broken gevent https workaround helper, Rsa crypt functions, Plugin to Bootstrap using ZeroNet protocol
2016-01-05 00:20:52 +01:00
|
|
|
time.sleep(2) # Wait for notify animation
|
2019-04-06 23:24:25 +02:00
|
|
|
self.log.info("GeoLite2 City database is ready at: %s" % db_path)
|
Version 0.3.5, Rev830, Full Tor mode support with hidden services, Onion stats in Sidebar, GeoDB download fix using Tor, Gray out disabled sites in Stats page, Tor hidden service status in stat page, Benchmark sha256, Skyts tracker out expodie in, 2 new tracker using ZeroNet protocol, Keep SSL cert option between restarts, SSL Certificate pinning support for connections, Site lock support for connections, Certificate pinned connections using implicit SSL, Flood protection whitelist support, Foreign keys support for DB layer, Not support for SQL query helper, 0 length file get bugfix, Pex onion address support, Faster port testing, Faster uPnP port opening, Need connections more often on owned sites, Delay ZeroHello startup message if port check or Tor manager not ready yet, Use lockfiles to avoid double start, Save original socket on proxy monkey patching to get ability to connect localhost directly, Handle atomic write errors, Broken gevent https workaround helper, Rsa crypt functions, Plugin to Bootstrap using ZeroNet protocol
2016-01-05 00:20:52 +01:00
|
|
|
return True
|
2017-07-16 22:51:01 +02:00
|
|
|
except Exception as err:
|
2019-03-15 21:06:59 +01:00
|
|
|
download_err = err
|
Version 0.3.5, Rev830, Full Tor mode support with hidden services, Onion stats in Sidebar, GeoDB download fix using Tor, Gray out disabled sites in Stats page, Tor hidden service status in stat page, Benchmark sha256, Skyts tracker out expodie in, 2 new tracker using ZeroNet protocol, Keep SSL cert option between restarts, SSL Certificate pinning support for connections, Site lock support for connections, Certificate pinned connections using implicit SSL, Flood protection whitelist support, Foreign keys support for DB layer, Not support for SQL query helper, 0 length file get bugfix, Pex onion address support, Faster port testing, Faster uPnP port opening, Need connections more often on owned sites, Delay ZeroHello startup message if port check or Tor manager not ready yet, Use lockfiles to avoid double start, Save original socket on proxy monkey patching to get ability to connect localhost directly, Handle atomic write errors, Broken gevent https workaround helper, Rsa crypt functions, Plugin to Bootstrap using ZeroNet protocol
2016-01-05 00:20:52 +01:00
|
|
|
self.log.error("Error downloading %s: %s" % (db_url, err))
|
|
|
|
pass
|
2017-10-21 11:01:57 +02:00
|
|
|
self.cmd("progress", [
|
|
|
|
"geolite-info",
|
2019-03-15 21:06:59 +01:00
|
|
|
_["GeoLite2 City database download error: {}!<br>Please download manually and unpack to data dir:<br>{}"].format(download_err, db_urls[0]),
|
2017-10-21 11:01:57 +02:00
|
|
|
-100
|
Version 0.3.5, Rev830, Full Tor mode support with hidden services, Onion stats in Sidebar, GeoDB download fix using Tor, Gray out disabled sites in Stats page, Tor hidden service status in stat page, Benchmark sha256, Skyts tracker out expodie in, 2 new tracker using ZeroNet protocol, Keep SSL cert option between restarts, SSL Certificate pinning support for connections, Site lock support for connections, Certificate pinned connections using implicit SSL, Flood protection whitelist support, Foreign keys support for DB layer, Not support for SQL query helper, 0 length file get bugfix, Pex onion address support, Faster port testing, Faster uPnP port opening, Need connections more often on owned sites, Delay ZeroHello startup message if port check or Tor manager not ready yet, Use lockfiles to avoid double start, Save original socket on proxy monkey patching to get ability to connect localhost directly, Handle atomic write errors, Broken gevent https workaround helper, Rsa crypt functions, Plugin to Bootstrap using ZeroNet protocol
2016-01-05 00:20:52 +01:00
|
|
|
])
|
2015-08-16 11:51:00 +02:00
|
|
|
|
2018-01-20 12:11:43 +01:00
|
|
|
def getLoc(self, geodb, ip):
|
|
|
|
global loc_cache
|
|
|
|
|
|
|
|
if ip in loc_cache:
|
|
|
|
return loc_cache[ip]
|
|
|
|
else:
|
|
|
|
try:
|
|
|
|
loc_data = geodb.get(ip)
|
|
|
|
except:
|
|
|
|
loc_data = None
|
|
|
|
|
|
|
|
if not loc_data or "location" not in loc_data:
|
|
|
|
loc_cache[ip] = None
|
|
|
|
return None
|
|
|
|
|
|
|
|
loc = {
|
|
|
|
"lat": loc_data["location"]["latitude"],
|
|
|
|
"lon": loc_data["location"]["longitude"],
|
|
|
|
}
|
|
|
|
if "city" in loc_data:
|
|
|
|
loc["city"] = loc_data["city"]["names"]["en"]
|
|
|
|
|
|
|
|
if "country" in loc_data:
|
|
|
|
loc["country"] = loc_data["country"]["names"]["en"]
|
|
|
|
|
|
|
|
loc_cache[ip] = loc
|
|
|
|
return loc
|
|
|
|
|
2019-11-19 01:44:26 +01:00
|
|
|
@util.Noparallel()
|
2019-04-06 23:24:25 +02:00
|
|
|
def getGeoipDb(self):
|
|
|
|
db_name = 'GeoLite2-City.mmdb'
|
|
|
|
|
|
|
|
sys_db_paths = []
|
|
|
|
if sys.platform == "linux":
|
|
|
|
sys_db_paths += ['/usr/share/GeoIP/' + db_name]
|
|
|
|
|
|
|
|
data_dir_db_path = os.path.join(config.data_dir, db_name)
|
|
|
|
|
2019-04-15 22:48:43 +02:00
|
|
|
db_paths = sys_db_paths + [data_dir_db_path]
|
2019-04-06 23:24:25 +02:00
|
|
|
|
|
|
|
for path in db_paths:
|
|
|
|
if os.path.isfile(path) and os.path.getsize(path) > 0:
|
|
|
|
return path
|
|
|
|
|
|
|
|
self.log.info("GeoIP database not found at [%s]. Downloading to: %s",
|
|
|
|
" ".join(db_paths), data_dir_db_path)
|
|
|
|
if self.downloadGeoLiteDb(data_dir_db_path):
|
|
|
|
return data_dir_db_path
|
|
|
|
return None
|
|
|
|
|
2018-01-19 02:15:43 +01:00
|
|
|
def getPeerLocations(self, peers):
|
2019-03-16 04:26:27 +01:00
|
|
|
import maxminddb
|
2019-04-06 23:24:25 +02:00
|
|
|
|
|
|
|
db_path = self.getGeoipDb()
|
|
|
|
if not db_path:
|
|
|
|
self.log.debug("Not showing peer locations: no GeoIP database")
|
|
|
|
return False
|
|
|
|
|
2018-01-19 02:15:43 +01:00
|
|
|
geodb = maxminddb.open_database(db_path)
|
|
|
|
|
2019-03-15 21:06:59 +01:00
|
|
|
peers = list(peers.values())
|
2018-01-19 02:15:43 +01:00
|
|
|
# Place bars
|
|
|
|
peer_locations = []
|
|
|
|
placed = {} # Already placed bars here
|
|
|
|
for peer in peers:
|
|
|
|
# Height of bar
|
|
|
|
if peer.connection and peer.connection.last_ping_delay:
|
|
|
|
ping = round(peer.connection.last_ping_delay * 1000)
|
|
|
|
else:
|
|
|
|
ping = None
|
2018-01-20 12:11:43 +01:00
|
|
|
loc = self.getLoc(geodb, peer.ip)
|
2018-01-19 02:15:43 +01:00
|
|
|
|
|
|
|
if not loc:
|
|
|
|
continue
|
|
|
|
# Create position array
|
|
|
|
lat, lon = loc["lat"], loc["lon"]
|
|
|
|
latlon = "%s,%s" % (lat, lon)
|
2019-01-20 03:28:49 +01:00
|
|
|
if latlon in placed and helper.getIpType(peer.ip) == "ipv4": # Dont place more than 1 bar to same place, fake repos using ip address last two part
|
2018-01-19 02:15:43 +01:00
|
|
|
lat += float(128 - int(peer.ip.split(".")[-2])) / 50
|
|
|
|
lon += float(128 - int(peer.ip.split(".")[-1])) / 50
|
|
|
|
latlon = "%s,%s" % (lat, lon)
|
|
|
|
placed[latlon] = True
|
|
|
|
peer_location = {}
|
|
|
|
peer_location.update(loc)
|
|
|
|
peer_location["lat"] = lat
|
|
|
|
peer_location["lon"] = lon
|
|
|
|
peer_location["ping"] = ping
|
|
|
|
|
|
|
|
peer_locations.append(peer_location)
|
|
|
|
|
|
|
|
# Append myself
|
2019-01-26 20:42:27 +01:00
|
|
|
for ip in self.site.connection_server.ip_external_list:
|
2019-01-24 15:20:08 +01:00
|
|
|
my_loc = self.getLoc(geodb, ip)
|
|
|
|
if my_loc:
|
|
|
|
my_loc["ping"] = 0
|
|
|
|
peer_locations.append(my_loc)
|
2018-01-19 02:15:43 +01:00
|
|
|
|
|
|
|
return peer_locations
|
|
|
|
|
2019-08-26 03:20:07 +02:00
|
|
|
@flag.admin
|
|
|
|
@flag.async_run
|
2015-08-16 11:51:00 +02:00
|
|
|
def actionSidebarGetPeers(self, to):
|
|
|
|
try:
|
2018-01-19 02:15:43 +01:00
|
|
|
peer_locations = self.getPeerLocations(self.site.peers)
|
|
|
|
globe_data = []
|
2015-08-16 11:51:00 +02:00
|
|
|
ping_times = [
|
2018-01-19 02:15:43 +01:00
|
|
|
peer_location["ping"]
|
|
|
|
for peer_location in peer_locations
|
|
|
|
if peer_location["ping"]
|
2015-08-16 11:51:00 +02:00
|
|
|
]
|
|
|
|
if ping_times:
|
|
|
|
ping_avg = sum(ping_times) / float(len(ping_times))
|
|
|
|
else:
|
|
|
|
ping_avg = 0
|
|
|
|
|
2018-01-19 02:15:43 +01:00
|
|
|
for peer_location in peer_locations:
|
|
|
|
if peer_location["ping"] == 0: # Me
|
|
|
|
height = -0.135
|
|
|
|
elif peer_location["ping"]:
|
|
|
|
height = min(0.20, math.log(1 + peer_location["ping"] / ping_avg, 300))
|
2015-08-16 11:51:00 +02:00
|
|
|
else:
|
2018-01-19 02:15:43 +01:00
|
|
|
height = -0.03
|
2015-08-16 11:51:00 +02:00
|
|
|
|
2018-01-19 02:15:43 +01:00
|
|
|
globe_data += [peer_location["lat"], peer_location["lon"], height]
|
2015-08-16 11:51:00 +02:00
|
|
|
|
|
|
|
self.response(to, globe_data)
|
2019-03-15 21:06:59 +01:00
|
|
|
except Exception as err:
|
2015-08-16 11:51:00 +02:00
|
|
|
self.log.debug("sidebarGetPeers error: %s" % Debug.formatException(err))
|
2019-03-15 21:06:59 +01:00
|
|
|
self.response(to, {"error": str(err)})
|
2015-08-16 11:51:00 +02:00
|
|
|
|
2019-08-26 03:20:07 +02:00
|
|
|
@flag.admin
|
|
|
|
@flag.no_multiuser
|
2015-08-16 11:51:00 +02:00
|
|
|
def actionSiteSetOwned(self, to, owned):
|
2018-09-30 21:56:36 +02:00
|
|
|
if self.site.address == config.updatesite:
|
|
|
|
return self.response(to, "You can't change the ownership of the updater site")
|
|
|
|
|
2015-08-16 11:51:00 +02:00
|
|
|
self.site.settings["own"] = bool(owned)
|
2017-06-19 15:33:23 +02:00
|
|
|
self.site.updateWebsocket(owned=owned)
|
Rev571, Optional file sizes to sidebar, Download all optional files option in sidebar, Optional file number in peer stats, Delete removed or changed optional files, Auto download optional files if autodownloadoptional checked, SiteReload command, Peer use global file server if no site defined, Allow browser cache video files, Allow more keepalive connections, Gevent 1.1 ranged request bugfix, Dont sent optional files details on websocket, Remove files from workermanager tasks if no longer in bad_files, Notify local client about changes on external siteSign
2015-11-09 00:44:03 +01:00
|
|
|
|
2019-08-26 03:20:07 +02:00
|
|
|
@flag.admin
|
|
|
|
@flag.no_multiuser
|
2018-09-21 02:17:53 +02:00
|
|
|
def actionUserSetSitePrivatekey(self, to, privatekey):
|
|
|
|
site_data = self.user.sites[self.site.address]
|
|
|
|
site_data["privatekey"] = privatekey
|
|
|
|
self.site.updateWebsocket(set_privatekey=bool(privatekey))
|
|
|
|
|
|
|
|
return "ok"
|
|
|
|
|
2019-08-26 03:20:07 +02:00
|
|
|
@flag.admin
|
|
|
|
@flag.no_multiuser
|
Rev571, Optional file sizes to sidebar, Download all optional files option in sidebar, Optional file number in peer stats, Delete removed or changed optional files, Auto download optional files if autodownloadoptional checked, SiteReload command, Peer use global file server if no site defined, Allow browser cache video files, Allow more keepalive connections, Gevent 1.1 ranged request bugfix, Dont sent optional files details on websocket, Remove files from workermanager tasks if no longer in bad_files, Notify local client about changes on external siteSign
2015-11-09 00:44:03 +01:00
|
|
|
def actionSiteSetAutodownloadoptional(self, to, owned):
|
|
|
|
self.site.settings["autodownloadoptional"] = bool(owned)
|
2018-09-17 15:24:44 +02:00
|
|
|
self.site.worker_manager.removeSolvedFileTasks()
|
2016-04-18 02:24:14 +02:00
|
|
|
|
2019-08-26 03:20:07 +02:00
|
|
|
@flag.no_multiuser
|
|
|
|
@flag.admin
|
2016-04-18 02:24:14 +02:00
|
|
|
def actionDbReload(self, to):
|
|
|
|
self.site.storage.closeDb()
|
|
|
|
self.site.storage.getDb()
|
|
|
|
|
|
|
|
return self.response(to, "ok")
|
2016-08-10 12:52:18 +02:00
|
|
|
|
2019-08-26 03:20:07 +02:00
|
|
|
@flag.no_multiuser
|
|
|
|
@flag.admin
|
2016-08-10 12:52:18 +02:00
|
|
|
def actionDbRebuild(self, to):
|
2019-06-23 14:21:50 +02:00
|
|
|
try:
|
|
|
|
self.site.storage.rebuildDb()
|
|
|
|
except Exception as err:
|
|
|
|
return self.response(to, {"error": str(err)})
|
2019-06-04 13:54:35 +02:00
|
|
|
|
2016-08-10 12:52:18 +02:00
|
|
|
|
|
|
|
return self.response(to, "ok")
|