Skip to content

Commit

Permalink
Version 0.3.6, Rev879, Fix sidebar error on description missing, New …
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
shortcutme committed Feb 2, 2016
1 parent f7eaf7b commit 687a848
Show file tree
Hide file tree
Showing 15 changed files with 144 additions and 29 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ __pycache__/

# Data dir
data/*
.db
48 changes: 48 additions & 0 deletions plugins/Newsfeed/NewsfeedPlugin.py
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions plugins/Newsfeed/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import NewsfeedPlugin
4 changes: 2 additions & 2 deletions plugins/Sidebar/SidebarPlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ def sidebarRenderOwnedCheckbox(self, body, site):

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"""
Expand Down Expand Up @@ -484,4 +484,4 @@ def actionSiteSetAutodownloadoptional(self, to, owned):
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 modified plugins/Trayicon/trayicon.ico
Binary file not shown.
13 changes: 13 additions & 0 deletions plugins/disabled-Multiuser/MultiuserPlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,16 @@ def responseUserLogin(self, master_seed):
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"])
14 changes: 7 additions & 7 deletions src/Config.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
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()

Expand Down Expand Up @@ -129,7 +130,7 @@ def createArguments(self):
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')

Expand Down Expand Up @@ -254,13 +255,12 @@ def parseCommandline(self, argv, silent=False):
# 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
Expand Down
5 changes: 3 additions & 2 deletions src/Db/DbCursor.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,14 @@ def execute(self, query, params=None):
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()
Expand Down
16 changes: 10 additions & 6 deletions src/Site/Site.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,12 @@ def loadSettings(self):
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
Expand Down Expand Up @@ -171,7 +172,7 @@ def getReachableBadFiles(self):

# 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)

Expand Down Expand Up @@ -353,6 +354,9 @@ def publish(self, limit=5, inner_path="content.json"):
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
Expand Down
Binary file removed src/Test/testdata/bootstrapper.db
Binary file not shown.
5 changes: 4 additions & 1 deletion src/Ui/UiRequest.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,10 @@ def actionWrapper(self, path, extra_headers=None):
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)

Expand Down Expand Up @@ -478,6 +480,7 @@ def error400(self, message=""):
# 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
Expand Down
53 changes: 47 additions & 6 deletions src/Ui/UiWebsocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import time
import sys
import hashlib
import os

import gevent

Expand All @@ -21,6 +22,7 @@ def __init__(self, ws, site, server, user, request):
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
Expand Down Expand Up @@ -53,7 +55,7 @@ def start(self):
""",
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",
"""
Expand Down Expand Up @@ -81,7 +83,6 @@ def start(self):
0
])


for notification in self.site.notifications: # Send pending notification messages
self.cmd("notification", notification)
self.site.notifications = []
Expand Down Expand Up @@ -149,16 +150,16 @@ def handleRequest(self, data):

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:]
Expand Down Expand Up @@ -332,7 +333,7 @@ def cbSitePublish(self, to, thread, notification=True):
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")
Expand Down Expand Up @@ -406,6 +407,7 @@ def actionFileQuery(self, to, dir_inner_path, query):
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)})
Expand Down Expand Up @@ -594,10 +596,49 @@ def actionSiteSetLimit(self, to, size_limit):
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()

def actionServerPortcheck(self, to):
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 modified src/Ui/media/img/favicon.ico
Binary file not shown.
2 changes: 1 addition & 1 deletion src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ def checker():
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")
Expand Down
11 changes: 7 additions & 4 deletions src/util/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down

0 comments on commit 687a848

Please sign in to comment.