Rev377, Fix sidebar filetypes css class, Support running zeronet from Utf-8 directories, Fix multiuser plugin welcome message, Format Multiuser plugin to PEP8, Faster publish by using connected peers if possible, Prefix css backface-visibility
This commit is contained in:
parent
55d8e80729
commit
00940797c8
10 changed files with 175 additions and 153 deletions
|
@ -143,7 +143,7 @@ class UiWebsocketPlugin(object):
|
|||
size = size_filetypes.get(extension, 0)
|
||||
size_other -= size
|
||||
percent = 100 * (float(size) / size_total)
|
||||
body.append("<li style='width: %.0f%%' class='html back-%s' title='%s'></li>" % (percent, color, extension))
|
||||
body.append("<li style='width: %.2f%%' class='%s back-%s' title='%s'></li>" % (percent, extension, color, extension))
|
||||
|
||||
# Legend
|
||||
body.append("</ul><ul class='graph-legend'>")
|
||||
|
|
|
@ -19,8 +19,10 @@ class ActionsPlugin(object):
|
|||
|
||||
self.main = sys.modules["main"]
|
||||
|
||||
fs_encoding = sys.getfilesystemencoding()
|
||||
|
||||
icon = notificationicon.NotificationIcon(
|
||||
os.path.join(os.path.dirname(os.path.abspath(__file__)), 'trayicon.ico'),
|
||||
os.path.join(os.path.dirname(os.path.abspath(__file__).decode(fs_encoding)), 'trayicon.ico'),
|
||||
"ZeroNet %s" % config.version
|
||||
)
|
||||
self.icon = icon
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import re, time, sys
|
||||
import re
|
||||
import sys
|
||||
from Plugin import PluginManager
|
||||
from Crypt import CryptBitcoin
|
||||
|
||||
|
||||
@PluginManager.registerTo("UiRequest")
|
||||
class UiRequestPlugin(object):
|
||||
|
@ -8,34 +9,38 @@ class UiRequestPlugin(object):
|
|||
self.user_manager = sys.modules["User.UserManager"].user_manager
|
||||
super(UiRequestPlugin, self).__init__(*args, **kwargs)
|
||||
|
||||
|
||||
# Create new user and inject user welcome message if necessary
|
||||
# Return: Html body also containing the injection
|
||||
def actionWrapper(self, path):
|
||||
user_created = False
|
||||
user = self.getCurrentUser() # Get user from cookie
|
||||
def actionWrapper(self, path, extra_headers=None):
|
||||
|
||||
match = re.match("/(?P<address>[A-Za-z0-9\._-]+)(?P<inner_path>/.*|$)", path)
|
||||
if not match:
|
||||
return False
|
||||
inner_path = match.group("inner_path").lstrip("/")
|
||||
html_request = "." not in inner_path or inner_path.endswith(".html") # Only inject html to html requests
|
||||
|
||||
user_created = False
|
||||
if html_request:
|
||||
user = self.getCurrentUser() # Get user from cookie
|
||||
if not user: # No user found by cookie
|
||||
user = self.user_manager.create()
|
||||
user_created = True
|
||||
|
||||
master_address = user.master_address
|
||||
master_seed = user.master_seed
|
||||
|
||||
if user_created:
|
||||
extra_headers = [('Set-Cookie', "master_address=%s;path=/;max-age=2592000;" % user.master_address)] # Max age = 30 days
|
||||
else:
|
||||
if not extra_headers:
|
||||
extra_headers = []
|
||||
extra_headers.append(('Set-Cookie', "master_address=%s;path=/;max-age=2592000;" % user.master_address)) # = 30 days
|
||||
|
||||
loggedin = self.get.get("login") == "done"
|
||||
|
||||
back = super(UiRequestPlugin, self).actionWrapper(path, extra_headers) # Get the wrapper frame output
|
||||
back_generator = super(UiRequestPlugin, self).actionWrapper(path, extra_headers) # Get the wrapper frame output
|
||||
|
||||
if not user_created and not loggedin: return back # No injection necessary
|
||||
|
||||
if not back or not hasattr(back, "endswith"): return back # Wrapper error or not string returned, injection not possible
|
||||
if not back_generator: # Wrapper error or not string returned, injection not possible
|
||||
return False
|
||||
|
||||
if user_created:
|
||||
back = back_generator.next()
|
||||
master_seed = user.master_seed
|
||||
# Inject the welcome message
|
||||
inject_html = """
|
||||
<!-- Multiser plugin -->
|
||||
|
@ -58,9 +63,10 @@ class UiRequestPlugin(object):
|
|||
""".replace("\t", "")
|
||||
inject_html = inject_html.replace("{master_seed}", master_seed) # Set the master seed in the message
|
||||
|
||||
back = re.sub("</body>\s*</html>\s*$", inject_html, back) # Replace the </body></html> tags with the injection
|
||||
return iter([re.sub("</body>\s*</html>\s*$", inject_html, back)]) # Replace the </body></html> tags with the injection
|
||||
|
||||
elif loggedin:
|
||||
back = back_generator.next()
|
||||
inject_html = """
|
||||
<!-- Multiser plugin -->
|
||||
<script>
|
||||
|
@ -71,16 +77,15 @@ class UiRequestPlugin(object):
|
|||
</body>
|
||||
</html>
|
||||
""".replace("\t", "")
|
||||
back = re.sub("</body>\s*</html>\s*$", inject_html, back) # Replace the </body></html> tags with the injection
|
||||
|
||||
return back
|
||||
return iter([re.sub("</body>\s*</html>\s*$", inject_html, back)]) # Replace the </body></html> tags with the injection
|
||||
|
||||
else: # No injection necessary
|
||||
return back_generator
|
||||
|
||||
# Get the current user based on request's cookies
|
||||
# Return: User object or None if no match
|
||||
def getCurrentUser(self):
|
||||
cookies = self.getCookies()
|
||||
user_manager = self.user_manager
|
||||
user = None
|
||||
if "master_address" in cookies:
|
||||
users = self.user_manager.list()
|
||||
|
@ -92,10 +97,10 @@ class UiRequestPlugin(object):
|
|||
class UserManagerPlugin(object):
|
||||
# In multiuser mode do not load the users
|
||||
def load(self):
|
||||
if not self.users: self.users = {}
|
||||
if not self.users:
|
||||
self.users = {}
|
||||
return self.users
|
||||
|
||||
|
||||
# Find user by master address
|
||||
# Return: User or None
|
||||
def get(self, master_address=None):
|
||||
|
@ -124,19 +129,19 @@ class UiWebsocketPlugin(object):
|
|||
server_info["master_address"] = self.user.master_address
|
||||
return server_info
|
||||
|
||||
|
||||
# Show current user's master seed
|
||||
def actionUserShowMasterSeed(self, to):
|
||||
if not "ADMIN" in self.site.settings["permissions"]: return self.response(to, "Show master seed not allowed")
|
||||
if "ADMIN" not in self.site.settings["permissions"]:
|
||||
return self.response(to, "Show master seed not allowed")
|
||||
message = "<b style='padding-top: 5px; display: inline-block'>Your unique private key:</b>"
|
||||
message += "<div style='font-size: 84%%; background-color: #FFF0AD; padding: 5px 8px; margin: 9px 0px'>%s</div>" % self.user.master_seed
|
||||
message += "<small>(Save it, you can access your account using this information)</small>"
|
||||
self.cmd("notification", ["info", message])
|
||||
|
||||
|
||||
# Logout user
|
||||
def actionUserLogout(self, to):
|
||||
if not "ADMIN" in self.site.settings["permissions"]: return self.response(to, "Logout not allowed")
|
||||
if "ADMIN" not in self.site.settings["permissions"]:
|
||||
return self.response(to, "Logout not allowed")
|
||||
message = "<b>You have been logged out.</b> <a href='#Login' class='button' onclick='wrapper.ws.cmd(\"userLoginForm\", []); return false'>Login to another account</a>"
|
||||
message += "<script>document.cookie = 'master_address=; expires=Thu, 01 Jan 1970 00:00:00 UTC'</script>"
|
||||
self.cmd("notification", ["done", message, 1000000]) # 1000000 = Show ~forever :)
|
||||
|
@ -148,12 +153,10 @@ class UiWebsocketPlugin(object):
|
|||
else:
|
||||
self.response(to, "User not found")
|
||||
|
||||
|
||||
# Show login form
|
||||
def actionUserLoginForm(self, to):
|
||||
self.cmd("prompt", ["<b>Login</b><br>Your private key:", "password", "Login"], self.responseUserLogin)
|
||||
|
||||
|
||||
# Login form submit
|
||||
def responseUserLogin(self, master_seed):
|
||||
user_manager = sys.modules["User.UserManager"].user_manager
|
||||
|
@ -166,4 +169,3 @@ class UiWebsocketPlugin(object):
|
|||
else:
|
||||
self.cmd("notification", ["error", "Error: Invalid master seed"])
|
||||
self.actionUserLoginForm(0)
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ class Config(object):
|
|||
|
||||
def __init__(self, argv):
|
||||
self.version = "0.3.2"
|
||||
self.rev = 360
|
||||
self.rev = 377
|
||||
self.argv = argv
|
||||
self.action = None
|
||||
self.createParser()
|
||||
|
|
|
@ -312,10 +312,19 @@ class Site:
|
|||
# Update content.json on peers
|
||||
@util.Noparallel()
|
||||
def publish(self, limit=5, inner_path="content.json"):
|
||||
self.log.info("Publishing to %s/%s peers..." % (min(len(self.peers), limit), len(self.peers)))
|
||||
published = [] # Successfully published (Peer)
|
||||
publishers = [] # Publisher threads
|
||||
|
||||
connected_peers = self.getConnectedPeers()
|
||||
if len(connected_peers) > limit * 2: # Publish to already connected peers if possible
|
||||
peers = connected_peers
|
||||
else:
|
||||
peers = self.peers.values()
|
||||
|
||||
self.log.info("Publishing to %s/%s peers (connected: %s)..." % (
|
||||
min(len(self.peers), limit), len(self.peers), len(connected_peers)
|
||||
))
|
||||
|
||||
if not peers:
|
||||
return 0 # No peers found
|
||||
|
||||
|
@ -336,13 +345,15 @@ class Site:
|
|||
peer for peer in peers
|
||||
if peer.connection and not peer.connection.closed and peer.key.endswith(":0") and peer not in published
|
||||
] # Every connected passive peer that we not published to
|
||||
for peer in passive_peers:
|
||||
gevent.spawn(self.publisher, inner_path, passive_peers, published, limit=10)
|
||||
|
||||
self.log.info(
|
||||
"Successfuly published to %s peers, publishing to %s more passive peers" %
|
||||
(len(published), len(passive_peers))
|
||||
)
|
||||
|
||||
for peer in passive_peers:
|
||||
gevent.spawn(self.publisher, inner_path, passive_peers, published, limit=10)
|
||||
|
||||
return len(published)
|
||||
|
||||
# Copy this site
|
||||
|
@ -664,6 +675,9 @@ class Site:
|
|||
|
||||
return found
|
||||
|
||||
def getConnectedPeers(self):
|
||||
return [peer for peer in self.peers.values() if peer.connection and peer.connection.connected]
|
||||
|
||||
# Cleanup probably dead peers
|
||||
def cleanupPeers(self):
|
||||
peers = self.peers.values()
|
||||
|
|
|
@ -3,6 +3,7 @@ import re
|
|||
import shutil
|
||||
import json
|
||||
import time
|
||||
import sys
|
||||
|
||||
import sqlite3
|
||||
import gevent.event
|
||||
|
@ -16,7 +17,9 @@ class SiteStorage:
|
|||
|
||||
def __init__(self, site, allow_create=True):
|
||||
self.site = site
|
||||
self.fs_encoding = sys.getfilesystemencoding()
|
||||
self.directory = "%s/%s" % (config.data_dir, self.site.address) # Site data diretory
|
||||
self.allowed_dir = os.path.abspath(self.directory) # Only serve/modify file within this dir
|
||||
self.log = site.log
|
||||
self.db = None # Db class
|
||||
self.db_checked = False # Checked db tables since startup
|
||||
|
@ -204,10 +207,10 @@ class SiteStorage:
|
|||
def getPath(self, inner_path):
|
||||
inner_path = inner_path.replace("\\", "/") # Windows separator fix
|
||||
inner_path = re.sub("^%s/" % re.escape(self.directory), "", inner_path) # Remove site directory if begins with it
|
||||
file_path = self.directory + "/" + inner_path
|
||||
allowed_dir = os.path.abspath(self.directory) # Only files within this directory allowed
|
||||
if ".." in file_path or not os.path.dirname(os.path.abspath(file_path)).startswith(allowed_dir):
|
||||
raise Exception("File not allowed: %s" % file_path)
|
||||
file_path = u"%s/%s" % (self.directory, inner_path)
|
||||
file_abspath = os.path.dirname(os.path.abspath(file_path))
|
||||
if ".." in file_path or not file_abspath.startswith(self.allowed_dir):
|
||||
raise Exception(u"File not allowed: %s" % file_path)
|
||||
return file_path
|
||||
|
||||
# Get site dir relative path
|
||||
|
|
|
@ -131,6 +131,7 @@ class UiRequest(object):
|
|||
content_type = "text/html; charset=utf-8"
|
||||
headers = []
|
||||
headers.append(("Version", "HTTP/1.1"))
|
||||
headers.append(("Connection", "Keep-Alive"))
|
||||
headers.append(("Access-Control-Allow-Origin", "*")) # Allow json access
|
||||
if self.env["REQUEST_METHOD"] == "OPTIONS":
|
||||
# Allow json access
|
||||
|
@ -414,8 +415,8 @@ class UiRequest(object):
|
|||
yield "He"
|
||||
time.sleep(1)
|
||||
yield "llo!"
|
||||
yield "Running websockets: %s" % len(self.server.websockets)
|
||||
self.server.sendMessage("Hello!")
|
||||
# yield "Running websockets: %s" % len(self.server.websockets)
|
||||
# self.server.sendMessage("Hello!")
|
||||
|
||||
# - Errors -
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ def prefix(content):
|
|||
)
|
||||
content = re.sub(
|
||||
'([^-\*])(border-radius|box-shadow|appearance|transition|animation|box-sizing|' +
|
||||
'transform|filter|perspective|animation-[a-z-]+): (.*?)([;}])',
|
||||
'backface-visibility|transform|filter|perspective|animation-[a-z-]+): (.*?)([;}])',
|
||||
'\\1-webkit-\\2: \\3; -moz-\\2: \\3; -o-\\2: \\3; -ms-\\2: \\3; \\2: \\3 \\4', content
|
||||
)
|
||||
content = re.sub(
|
||||
|
|
Loading…
Reference in a new issue