Version 0.3.6, Rev879, Fix sidebar error on description missing, New trayicon, New favicon, Disable some functions on MultiUser proxies, New homepage, Replace only the last ? in SQL queries, Alwaays grant ADMIN permission to homepage site, Announce before publish if no peers, configSet, serverShutdown, ADMIN WebsocketAPI command, Stop Tor client before updating, Ignore peer ip packing error, Ignore db files from git, Fix safari ajax error when UiPassword enabled

This commit is contained in:
HelloZeroNet 2016-02-02 11:40:45 +01:00
parent f7eaf7b222
commit 687a848292
15 changed files with 144 additions and 29 deletions

1
.gitignore vendored
View file

@ -13,3 +13,4 @@ __pycache__/
# Data dir
data/*
.db

View file

@ -0,0 +1,48 @@
from Plugin import PluginManager
import re
@PluginManager.registerTo("UiWebsocket")
class UiWebsocketPlugin(object):
def actionFeedFollow(self, to, feeds):
self.user.setFeedFollow(self.site.address, feeds)
self.response(to, "ok")
def actionFeedListFollow(self, to):
feeds = self.user.sites[self.site.address].get("follow", {})
self.response(to, feeds)
def actionFeedQuery(self, to):
from Site import SiteManager
rows = []
for address, site_data in self.user.sites.iteritems():
feeds = site_data.get("follow")
if not feeds:
continue
for name, query_set in feeds.iteritems():
site = SiteManager.site_manager.get(address)
try:
query, params = query_set
if ":params" in query:
query = query.replace(":params", ",".join(["?"]*len(params)))
res = site.storage.query(query+" ORDER BY date_added DESC LIMIT 10", params)
else:
res = site.storage.query(query+" ORDER BY date_added DESC LIMIT 10")
except Exception, err: # Log error
self.log.error("%s feed query %s error: %s" % (address, name, err))
continue
for row in res:
row = dict(row)
row["site"] = address
row["feed_name"] = name
rows.append(row)
return self.response(to, rows)
@PluginManager.registerTo("User")
class UserPlugin(object):
# Set queries that user follows
def setFeedFollow(self, address, feeds):
site_data = self.getSiteData(address)
site_data["follow"] = feeds
self.save()
return site_data

View file

@ -0,0 +1 @@
import NewsfeedPlugin

View file

@ -290,7 +290,7 @@ class UiWebsocketPlugin(object):
def sidebarRenderOwnSettings(self, body, site):
title = cgi.escape(site.content_manager.contents["content.json"]["title"], True)
description = cgi.escape(site.content_manager.contents["content.json"]["description"], True)
description = cgi.escape(site.content_manager.contents["content.json"].get("description", ""), True)
privatekey = cgi.escape(self.user.getSiteData(site.address, create=False).get("privatekey", ""))
body.append(u"""
@ -484,4 +484,4 @@ class UiWebsocketPlugin(object):
return self.response(to, "You don't have permission to run this command")
self.site.settings["autodownloadoptional"] = bool(owned)
self.site.update()
self.site.worker_manager.removeGoodFileTasks()
self.site.worker_manager.removeGoodFileTasks()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -169,3 +169,16 @@ class UiWebsocketPlugin(object):
else:
self.cmd("notification", ["error", "Error: Invalid master seed"])
self.actionUserLoginForm(0)
# Disable not Multiuser safe functions
def actionConfigSet(self, to, *args, **kwargs):
self.cmd("notification", ["info", "This function is disabled on this proxy"])
def actionServerShutdown(self, to, *args, **kwargs):
self.cmd("notification", ["info", "This function is disabled on this proxy"])
def actionServerUpdate(self, to, *args, **kwargs):
self.cmd("notification", ["info", "This function is disabled on this proxy"])
def actionSiteClone(self, to, *args, **kwargs):
self.cmd("notification", ["info", "This function is disabled on this proxy"])

View file

@ -7,10 +7,11 @@ import ConfigParser
class Config(object):
def __init__(self, argv):
self.version = "0.3.5"
self.rev = 860
self.version = "0.3.6"
self.rev = 879
self.argv = argv
self.action = None
self.config_file = "zeronet.conf"
self.createParser()
self.createArguments()
@ -129,7 +130,7 @@ class Config(object):
self.parser.add_argument('--ui_restrict', help='Restrict web access', default=False, metavar='ip', nargs='*')
self.parser.add_argument('--open_browser', help='Open homepage in web browser automatically',
nargs='?', const="default_browser", metavar='browser_name')
self.parser.add_argument('--homepage', help='Web interface Homepage', default='1EU1tbG9oC1A8jz2ouVwGZyQ5asrNsE4Vr',
self.parser.add_argument('--homepage', help='Web interface Homepage', default='1HeLLo4uzjaLetFx6NH3PMwFP3qbRbTf3D',
metavar='address')
self.parser.add_argument('--size_limit', help='Default site size limit in MB', default=10, metavar='size')
@ -254,13 +255,12 @@ class Config(object):
# Parse config file
def parseConfig(self, argv):
# Find config file path from parameters
config_file = "zeronet.conf"
if "--config_file" in argv:
config_file = argv[argv.index("--config_file") + 1]
self.config_file = argv[argv.index("--config_file") + 1]
# Load config file
if os.path.isfile(config_file):
if os.path.isfile(self.config_file):
config = ConfigParser.ConfigParser(allow_no_value=True)
config.read(config_file)
config.read(self.config_file)
for section in config.sections():
for key, val in config.items(section):
if section != "global": # If not global prefix key with section

View file

@ -32,13 +32,14 @@ class DbCursor:
query_wheres.append(key+" = ?")
values.append(value)
wheres = " AND ".join(query_wheres)
query = query.replace("?", wheres)
query = re.sub("(.*)[?]", "\\1%s" % wheres, query) # Replace the last ?
params = values
else:
# Convert param dict to INSERT INTO table (key, key2) VALUES (?, ?) format
keys = ", ".join(params.keys())
values = ", ".join(['?' for key in params.keys()])
query = query.replace("?", "(%s) VALUES (%s)" % (keys, values))
keysvalues = "(%s) VALUES (%s)" % (keys, values)
query = re.sub("(.*)[?]", "\\1%s" % keysvalues, query) # Replace the last ?
params = tuple(params.values())
s = time.time()

View file

@ -80,11 +80,12 @@ class Site(object):
if self.address in sites_settings:
self.settings = sites_settings[self.address]
else:
if self.address == config.homepage: # Add admin permissions to homepage
permissions = ["ADMIN"]
else:
permissions = []
self.settings = {"own": False, "serving": True, "permissions": permissions} # Default
self.settings = {"own": False, "serving": True, "permissions": []} # Default
# Add admin permissions to homepage
if self.address == config.homepage and "ADMIN" not in self.settings["permissions"]:
self.settings["permissions"].append("ADMIN")
return
# Save site settings to data/sites.json
@ -171,7 +172,7 @@ class Site(object):
# Retry download bad files
def retryBadFiles(self, force=False):
for bad_file, tries in self.bad_files.iteritems():
for bad_file, tries in self.bad_files.items():
if force or random.randint(0, min(20, tries)) == 0: # Larger number tries = less likely to check every 15min
self.needFile(bad_file, update=True, blocking=False)
@ -353,6 +354,9 @@ class Site(object):
published = [] # Successfully published (Peer)
publishers = [] # Publisher threads
if not self.peers:
self.announce()
connected_peers = self.getConnectedPeers()
if len(connected_peers) > limit * 2: # Publish to already connected peers if possible
peers = connected_peers

Binary file not shown.

View file

@ -188,8 +188,10 @@ class UiRequest(object):
inner_path = match.group("inner_path").lstrip("/")
if "." in inner_path and not inner_path.endswith(".html"):
return self.actionSiteMedia("/media" + path) # Only serve html files with frame
if self.env.get("HTTP_X_REQUESTED_WITH") or self.env.get("HTTP_ORIGIN"):
if self.env.get("HTTP_X_REQUESTED_WITH"):
return self.error403("Ajax request not allowed to load wrapper") # No ajax allowed on wrapper
# if self.env.get("HTTP_ORIGIN") and self.env.get("HTTP_ORIGIN").strip("/") != self.env.get("HTTP_HOST", "").strip("/"):
# return self.error403("Origin does not match")
site = SiteManager.site_manager.get(address)
@ -478,6 +480,7 @@ class UiRequest(object):
# You are not allowed to access this
def error403(self, message="", details=True):
self.sendHeader(403)
self.log.debug("Error 403: %s" % message)
return self.formatError("Forbidden", message, details=details)
# Send file not found error

View file

@ -2,6 +2,7 @@ import json
import time
import sys
import hashlib
import os
import gevent
@ -21,6 +22,7 @@ class UiWebsocket(object):
self.user = user
self.log = site.log
self.request = request
self.permissions = []
self.server = server
self.next_message_id = 1
self.waiting_cb = {} # Waiting for callback. Key: message_id, Value: function pointer
@ -53,7 +55,7 @@ class UiWebsocket(object):
""",
10000
])
elif config.tor == "always" and not file_server.tor_manager.start_onions == False:
elif config.tor == "always" and file_server.tor_manager.start_onions is not False:
self.site.notifications.append([
"error",
"""
@ -81,7 +83,6 @@ class UiWebsocket(object):
0
])
for notification in self.site.notifications: # Send pending notification messages
self.cmd("notification", notification)
self.site.notifications = []
@ -149,16 +150,16 @@ class UiWebsocket(object):
cmd = req.get("cmd")
params = req.get("params")
permissions = self.getPermissions(req["id"])
self.permissions = self.getPermissions(req["id"])
admin_commands = (
"sitePause", "siteResume", "siteDelete", "siteList", "siteSetLimit", "siteClone",
"channelJoinAllsite", "serverUpdate", "serverPortcheck", "certSet"
"channelJoinAllsite", "serverUpdate", "serverPortcheck", "certSet", "configSet"
)
if cmd == "response": # It's a response to a command
return self.actionResponse(req["to"], req["result"])
elif cmd in admin_commands and "ADMIN" not in permissions: # Admin commands
elif cmd in admin_commands and "ADMIN" not in self.permissions: # Admin commands
return self.response(req["id"], {"error:", "You don't have permission to run %s" % cmd})
else: # Normal command
func_name = "action" + cmd[0].upper() + cmd[1:]
@ -332,7 +333,7 @@ class UiWebsocket(object):
site.updateWebsocket() # Send updated site data to local websocket clients
else:
if len(site.peers) == 0:
if sys.modules["main"].file_server.port_opened:
if sys.modules["main"].file_server.port_opened or sys.modules["main"].file_server.tor_manager.start_onions:
if notification:
self.cmd("notification", ["info", "No peers found, but your content is ready to access.", 5000])
self.response(to, "ok")
@ -406,6 +407,7 @@ class UiWebsocket(object):
def actionDbQuery(self, to, query, params=None, wait_for=None):
rows = []
try:
assert query.upper().startswith("SELECT"), "Only SELECT query supported"
res = self.site.storage.query(query, params)
except Exception, err: # Response the error to client
return self.response(to, {"error": str(err)})
@ -594,6 +596,8 @@ class UiWebsocket(object):
def actionServerUpdate(self, to):
self.cmd("updating")
sys.modules["main"].update_after_shutdown = True
if sys.modules["main"].file_server.tor_manager.tor_process:
sys.modules["main"].file_server.tor_manager.stopTor()
sys.modules["main"].file_server.stop()
sys.modules["main"].ui_server.stop()
@ -601,3 +605,40 @@ class UiWebsocket(object):
sys.modules["main"].file_server.port_opened = None
res = sys.modules["main"].file_server.openport()
self.response(to, res)
def actionServerShutdown(self, to):
sys.modules["main"].file_server.stop()
sys.modules["main"].ui_server.stop()
def actionConfigSet(self, to, key, value):
if not os.path.isfile(config.config_file):
content = ""
else:
content = open(config.config_file).read()
lines = content.splitlines()
global_line_i = None
key_line_i = None
i = 0
for line in lines:
if line.strip() == "[global]":
global_line_i = i
if line.startswith(key+" = "):
key_line_i = i
i += 1
if value == None: # Delete line
if key_line_i:
del lines[key_line_i]
else: # Add / update
new_line = "%s = %s" % (key, value)
if key_line_i: # Already in the config, change the line
lines[key_line_i] = new_line
elif global_line_i is None: # No global section yet, append to end of file
lines.append("[global]")
lines.append(new_line)
else: # Has global section, append the line after it
lines.insert(global_line_i+1, new_line)
open(config.config_file, "w").write("\n".join(lines))
self.response(to, "ok")

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -241,7 +241,7 @@ class Actions(object):
while 1:
s = time.time()
time.sleep(1)
print time.time()-s
print "Switch time:", time.time()-s
gevent.spawn(checker)
logging.info("Opening a simple connection server")

View file

@ -51,10 +51,13 @@ def shellquote(*args):
def packPeers(peers):
packed_peers = {"ip4": [], "onion": []}
for peer in peers:
if peer.ip.endswith(".onion"):
packed_peers["onion"].append(peer.packMyAddress())
else:
packed_peers["ip4"].append(peer.packMyAddress())
try:
if peer.ip.endswith(".onion"):
packed_peers["onion"].append(peer.packMyAddress())
else:
packed_peers["ip4"].append(peer.packMyAddress())
except Exception, err:
logging.error("Error packing peer address: %s" % peer)
return packed_peers