Rev390, Fix sidebar error on non locatable IPs, Configurable bootstrap torrent trackers, Multi-line config file settings, Evenly distributed tracker announce to work better on passive connections, Avoid iframe sandbox escape by using nonces, Better html error messages, Display proper error on invalid startup parameters
This commit is contained in:
parent
eec0b22c1f
commit
0de6496f96
11 changed files with 117 additions and 58 deletions
|
@ -376,7 +376,7 @@ class UiWebsocketPlugin(object):
|
||||||
else:
|
else:
|
||||||
loc = geodb.get(peer.ip)
|
loc = geodb.get(peer.ip)
|
||||||
loc_cache[peer.ip] = loc
|
loc_cache[peer.ip] = loc
|
||||||
if not loc:
|
if not loc or "location" not in loc:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Create position array
|
# Create position array
|
||||||
|
|
|
@ -8,7 +8,7 @@ class Config(object):
|
||||||
|
|
||||||
def __init__(self, argv):
|
def __init__(self, argv):
|
||||||
self.version = "0.3.2"
|
self.version = "0.3.2"
|
||||||
self.rev = 378
|
self.rev = 390
|
||||||
self.argv = argv
|
self.argv = argv
|
||||||
self.action = None
|
self.action = None
|
||||||
self.createParser()
|
self.createParser()
|
||||||
|
@ -29,6 +29,14 @@ class Config(object):
|
||||||
|
|
||||||
# Create command line arguments
|
# Create command line arguments
|
||||||
def createArguments(self):
|
def createArguments(self):
|
||||||
|
trackers = [
|
||||||
|
"udp://open.demonii.com:1337",
|
||||||
|
"udp://tracker.leechers-paradise.org:6969",
|
||||||
|
"udp://9.rarbg.com:2710",
|
||||||
|
"http://tracker.aletorrenty.pl:2710/announce",
|
||||||
|
"http://retracker.telecom.kz/announce",
|
||||||
|
"http://torrent.gresille.org/announce"
|
||||||
|
]
|
||||||
# Platform specific
|
# Platform specific
|
||||||
if sys.platform.startswith("win"):
|
if sys.platform.startswith("win"):
|
||||||
coffeescript = "type %s | tools\\coffee\\coffee.cmd"
|
coffeescript = "type %s | tools\\coffee\\coffee.cmd"
|
||||||
|
@ -122,7 +130,8 @@ class Config(object):
|
||||||
self.parser.add_argument('--fileserver_port', help='FileServer bind port', default=15441, type=int, metavar='port')
|
self.parser.add_argument('--fileserver_port', help='FileServer bind port', default=15441, type=int, metavar='port')
|
||||||
self.parser.add_argument('--disable_udp', help='Disable UDP connections', action='store_true')
|
self.parser.add_argument('--disable_udp', help='Disable UDP connections', action='store_true')
|
||||||
self.parser.add_argument('--proxy', help='Socks proxy address', metavar='ip:port')
|
self.parser.add_argument('--proxy', help='Socks proxy address', metavar='ip:port')
|
||||||
self.parser.add_argument('--ip_external', help='External ip (tested on start if None)', metavar='ip')
|
self.parser.add_argument('--ip_external', help='Set reported external ip (tested on start if None)', metavar='ip')
|
||||||
|
self.parser.add_argument('--trackers', help='Bootstraping torrent trackers', default=trackers, metavar='protocol://address', nargs='*')
|
||||||
self.parser.add_argument('--use_openssl', help='Use OpenSSL liblary for speedup',
|
self.parser.add_argument('--use_openssl', help='Use OpenSSL liblary for speedup',
|
||||||
type='bool', choices=[True, False], default=use_openssl)
|
type='bool', choices=[True, False], default=use_openssl)
|
||||||
self.parser.add_argument('--disable_encryption', help='Disable connection encryption', action='store_true')
|
self.parser.add_argument('--disable_encryption', help='Disable connection encryption', action='store_true')
|
||||||
|
@ -238,7 +247,8 @@ class Config(object):
|
||||||
if section != "global": # If not global prefix key with section
|
if section != "global": # If not global prefix key with section
|
||||||
key = section + "_" + key
|
key = section + "_" + key
|
||||||
if val:
|
if val:
|
||||||
argv.insert(1, val)
|
for line in val.strip().split("\n"): # Allow multi-line values
|
||||||
|
argv.insert(1, line)
|
||||||
argv.insert(1, "--%s" % key)
|
argv.insert(1, "--%s" % key)
|
||||||
return argv
|
return argv
|
||||||
|
|
||||||
|
|
|
@ -170,11 +170,15 @@ class FileServer(ConnectionServer):
|
||||||
# Announce sites every 20 min
|
# Announce sites every 20 min
|
||||||
def announceSites(self):
|
def announceSites(self):
|
||||||
import gc
|
import gc
|
||||||
|
first_announce = True # First start
|
||||||
while 1:
|
while 1:
|
||||||
time.sleep(20 * 60) # Announce sites every 20 min
|
# Sites healthcare
|
||||||
for address, site in self.sites.items():
|
for address, site in self.sites.items():
|
||||||
if site.settings["serving"]:
|
if site.settings["serving"]:
|
||||||
site.announce() # Announce site to tracker
|
if first_announce: # Announce to all trackers on startup
|
||||||
|
site.announce()
|
||||||
|
else: # If not first run only use PEX
|
||||||
|
site.announcePex()
|
||||||
|
|
||||||
# Reset bad file retry counter
|
# Reset bad file retry counter
|
||||||
for inner_path in site.bad_files:
|
for inner_path in site.bad_files:
|
||||||
|
@ -195,6 +199,20 @@ class FileServer(ConnectionServer):
|
||||||
site = None
|
site = None
|
||||||
gc.collect() # Implicit grabage collection
|
gc.collect() # Implicit grabage collection
|
||||||
|
|
||||||
|
# Find new peers
|
||||||
|
for tracker_i in range(len(config.trackers)):
|
||||||
|
time.sleep(60 * 20 / len(config.trackers)) # Query all trackers one-by-one in 20 minutes evenly distributed
|
||||||
|
|
||||||
|
for address, site in self.sites.items():
|
||||||
|
site.announce(num = 1, pex = False)
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
|
first_announce = False
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Detects if computer back from wakeup
|
# Detects if computer back from wakeup
|
||||||
def wakeupWatcher(self):
|
def wakeupWatcher(self):
|
||||||
last_time = time.time()
|
last_time = time.time()
|
||||||
|
|
|
@ -38,6 +38,7 @@ class Site:
|
||||||
self.peers = {} # Key: ip:port, Value: Peer.Peer
|
self.peers = {} # Key: ip:port, Value: Peer.Peer
|
||||||
self.peer_blacklist = SiteManager.peer_blacklist # Ignore this peers (eg. myself)
|
self.peer_blacklist = SiteManager.peer_blacklist # Ignore this peers (eg. myself)
|
||||||
self.last_announce = 0 # Last announce time to tracker
|
self.last_announce = 0 # Last announce time to tracker
|
||||||
|
self.last_tracker_id = random.randint(0, 10) # Last announced tracker id
|
||||||
self.worker_manager = WorkerManager(self) # Handle site download from other peers
|
self.worker_manager = WorkerManager(self) # Handle site download from other peers
|
||||||
self.bad_files = {} # SHA check failed files, need to redownload {"inner.content": 1} (key: file, value: failed accept)
|
self.bad_files = {} # SHA check failed files, need to redownload {"inner.content": 1} (key: file, value: failed accept)
|
||||||
self.content_updated = None # Content.js update time
|
self.content_updated = None # Content.js update time
|
||||||
|
@ -510,12 +511,13 @@ class Site:
|
||||||
|
|
||||||
# Gather peers from tracker
|
# Gather peers from tracker
|
||||||
# Return: Complete time or False on error
|
# Return: Complete time or False on error
|
||||||
def announceTracker(self, protocol, ip, port, fileserver_port, address_hash, my_peer_id):
|
def announceTracker(self, protocol, address, fileserver_port, address_hash, my_peer_id):
|
||||||
s = time.time()
|
s = time.time()
|
||||||
if protocol == "udp": # Udp tracker
|
if protocol == "udp": # Udp tracker
|
||||||
if config.disable_udp:
|
if config.disable_udp:
|
||||||
return False # No udp supported
|
return False # No udp supported
|
||||||
tracker = UdpTrackerClient(ip, port)
|
ip, port = address.split(":")
|
||||||
|
tracker = UdpTrackerClient(ip, int(port))
|
||||||
tracker.peer_port = fileserver_port
|
tracker.peer_port = fileserver_port
|
||||||
try:
|
try:
|
||||||
tracker.connect()
|
tracker.connect()
|
||||||
|
@ -535,7 +537,7 @@ class Site:
|
||||||
}
|
}
|
||||||
req = None
|
req = None
|
||||||
try:
|
try:
|
||||||
url = "http://" + ip + "?" + urllib.urlencode(params)
|
url = "http://" + address + "?" + urllib.urlencode(params)
|
||||||
# Load url
|
# Load url
|
||||||
with gevent.Timeout(10, False): # Make sure of timeout
|
with gevent.Timeout(10, False): # Make sure of timeout
|
||||||
req = urllib2.urlopen(url, timeout=8)
|
req = urllib2.urlopen(url, timeout=8)
|
||||||
|
@ -577,10 +579,17 @@ class Site:
|
||||||
return time.time() - s
|
return time.time() - s
|
||||||
|
|
||||||
# Add myself and get other peers from tracker
|
# Add myself and get other peers from tracker
|
||||||
def announce(self, force=False):
|
def announce(self, force=False, num=5, pex=True):
|
||||||
if time.time() < self.last_announce + 30 and not force:
|
if time.time() < self.last_announce + 30 and not force:
|
||||||
return # No reannouncing within 30 secs
|
return # No reannouncing within 30 secs
|
||||||
self.last_announce = time.time()
|
self.last_announce = time.time()
|
||||||
|
|
||||||
|
trackers = config.trackers
|
||||||
|
if num == 1: # Only announce on one tracker, increment the queried tracker id
|
||||||
|
self.last_tracker_id += 1
|
||||||
|
self.last_tracker_id = self.last_tracker_id % len(trackers)
|
||||||
|
trackers = [trackers[self.last_tracker_id]] # We only going to use this one
|
||||||
|
|
||||||
errors = []
|
errors = []
|
||||||
slow = []
|
slow = []
|
||||||
address_hash = hashlib.sha1(self.address).hexdigest() # Site address hash
|
address_hash = hashlib.sha1(self.address).hexdigest() # Site address hash
|
||||||
|
@ -595,39 +604,42 @@ class Site:
|
||||||
announced = 0
|
announced = 0
|
||||||
threads = []
|
threads = []
|
||||||
|
|
||||||
for protocol, ip, port in SiteManager.TRACKERS: # Start announce threads
|
for tracker in trackers: # Start announce threads
|
||||||
thread = gevent.spawn(self.announceTracker, protocol, ip, port, fileserver_port, address_hash, my_peer_id)
|
protocol, address = tracker.split("://")
|
||||||
|
thread = gevent.spawn(self.announceTracker, protocol, address, fileserver_port, address_hash, my_peer_id)
|
||||||
threads.append(thread)
|
threads.append(thread)
|
||||||
thread.ip = ip
|
thread.address = address
|
||||||
thread.protocol = protocol
|
thread.protocol = protocol
|
||||||
|
if len(threads) > num: break # Announce limit
|
||||||
|
|
||||||
gevent.joinall(threads) # Wait for announce finish
|
gevent.joinall(threads) # Wait for announce finish
|
||||||
|
|
||||||
for thread in threads:
|
for thread in threads:
|
||||||
if thread.value:
|
if thread.value:
|
||||||
if thread.value > 1:
|
if thread.value > 1:
|
||||||
slow.append("%.2fs %s://%s" % (thread.value, thread.protocol, thread.ip))
|
slow.append("%.2fs %s://%s" % (thread.value, thread.protocol, thread.address))
|
||||||
announced += 1
|
announced += 1
|
||||||
else:
|
else:
|
||||||
errors.append("%s://%s" % (thread.protocol, thread.ip))
|
errors.append("%s://%s" % (thread.protocol, thread.address))
|
||||||
|
|
||||||
# Save peers num
|
# Save peers num
|
||||||
self.settings["peers"] = len(self.peers)
|
self.settings["peers"] = len(self.peers)
|
||||||
self.saveSettings()
|
self.saveSettings()
|
||||||
|
|
||||||
if len(errors) < len(SiteManager.TRACKERS): # Less errors than total tracker nums
|
if len(errors) < min(num, len(trackers)): # Less errors than total tracker nums
|
||||||
self.log.debug(
|
self.log.debug(
|
||||||
"Announced port %s to %s trackers in %.3fs, errors: %s, slow: %s" %
|
"Announced port %s to %s trackers in %.3fs, errors: %s, slow: %s" %
|
||||||
(fileserver_port, announced, time.time() - s, errors, slow)
|
(fileserver_port, announced, time.time() - s, errors, slow)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self.log.error("Announced to %s trackers in %.3fs, failed" % (announced, time.time() - s))
|
self.log.error("Announce to %s trackers in %.3fs, failed" % (announced, time.time() - s))
|
||||||
|
|
||||||
if not [peer for peer in self.peers.values() if peer.connection and peer.connection.connected]:
|
if pex:
|
||||||
# If no connected peer yet then wait for connections
|
if not [peer for peer in self.peers.values() if peer.connection and peer.connection.connected]:
|
||||||
gevent.spawn_later(3, self.announcePex, need_num=10) # Spawn 3 secs later
|
# If no connected peer yet then wait for connections
|
||||||
else: # Else announce immediately
|
gevent.spawn_later(3, self.announcePex, need_num=10) # Spawn 3 secs later
|
||||||
self.announcePex()
|
else: # Else announce immediately
|
||||||
|
self.announcePex()
|
||||||
|
|
||||||
# Keep connections to get the updates (required for passive clients)
|
# Keep connections to get the updates (required for passive clients)
|
||||||
def needConnections(self, num=3):
|
def needConnections(self, num=3):
|
||||||
|
|
|
@ -6,26 +6,6 @@ import os
|
||||||
from Plugin import PluginManager
|
from Plugin import PluginManager
|
||||||
from Config import config
|
from Config import config
|
||||||
|
|
||||||
TRACKERS = [
|
|
||||||
("udp", "open.demonii.com", 1337),
|
|
||||||
# ("udp", "sugoi.pomf.se", 2710),
|
|
||||||
# ("udp", "tracker.coppersurfer.tk", 80),
|
|
||||||
("udp", "tracker.leechers-paradise.org", 6969),
|
|
||||||
("udp", "9.rarbg.com", 2710),
|
|
||||||
# ("udp", "www.eddie4.nl", 6969),
|
|
||||||
# ("udp", "trackr.sytes.net", 80),
|
|
||||||
# ("udp", "tracker4.piratux.com", 6969)
|
|
||||||
# ("http", "exodus.desync.com:80/announce", None), Off
|
|
||||||
("http", "tracker.aletorrenty.pl:2710/announce", None),
|
|
||||||
# ("http", "torrent.gresille.org/announce", None), # Slow
|
|
||||||
# ("http", "announce.torrentsmd.com:6969/announce", None), # Off
|
|
||||||
# ("http", "i.bandito.org/announce", None), # Off
|
|
||||||
("http", "retracker.telecom.kz/announce", None),
|
|
||||||
("http", "torrent.gresille.org/announce", None),
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
@PluginManager.acceptPlugins
|
@PluginManager.acceptPlugins
|
||||||
class SiteManager(object):
|
class SiteManager(object):
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@ import os
|
||||||
import mimetypes
|
import mimetypes
|
||||||
import json
|
import json
|
||||||
import cgi
|
import cgi
|
||||||
|
import string
|
||||||
|
import random
|
||||||
|
|
||||||
from Config import config
|
from Config import config
|
||||||
from Site import SiteManager
|
from Site import SiteManager
|
||||||
|
@ -69,7 +71,7 @@ class UiRequest(object):
|
||||||
return self.actionConsole()
|
return self.actionConsole()
|
||||||
# Site media wrapper
|
# Site media wrapper
|
||||||
else:
|
else:
|
||||||
if self.get.get("wrapper") == "False":
|
if self.get.get("wrapper_nonce"):
|
||||||
return self.actionSiteMedia("/media" + path) # Only serve html files with frame
|
return self.actionSiteMedia("/media" + path) # Only serve html files with frame
|
||||||
else:
|
else:
|
||||||
body = self.actionWrapper(path)
|
body = self.actionWrapper(path)
|
||||||
|
@ -202,7 +204,6 @@ class UiRequest(object):
|
||||||
else: # Bad url
|
else: # Bad url
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def renderWrapper(self, site, path, inner_path, title, extra_headers):
|
def renderWrapper(self, site, path, inner_path, title, extra_headers):
|
||||||
file_inner_path = inner_path
|
file_inner_path = inner_path
|
||||||
if not file_inner_path:
|
if not file_inner_path:
|
||||||
|
@ -219,10 +220,12 @@ class UiRequest(object):
|
||||||
body_style = ""
|
body_style = ""
|
||||||
meta_tags = ""
|
meta_tags = ""
|
||||||
|
|
||||||
|
wrapper_nonce = self.getWrapperNonce()
|
||||||
|
|
||||||
if self.env.get("QUERY_STRING"):
|
if self.env.get("QUERY_STRING"):
|
||||||
query_string = "?" + self.env["QUERY_STRING"] + "&wrapper=False"
|
query_string = "?%s&wrapper_nonce=%s" % (self.env["QUERY_STRING"], wrapper_nonce)
|
||||||
else:
|
else:
|
||||||
query_string = "?wrapper=False"
|
query_string = "?wrapper_nonce=%s" % wrapper_nonce
|
||||||
|
|
||||||
if self.isProxyRequest(): # Its a remote proxy request
|
if self.isProxyRequest(): # Its a remote proxy request
|
||||||
if self.env["REMOTE_ADDR"] == "127.0.0.1": # Local client, the server address also should be 127.0.0.1
|
if self.env["REMOTE_ADDR"] == "127.0.0.1": # Local client, the server address also should be 127.0.0.1
|
||||||
|
@ -260,6 +263,13 @@ class UiRequest(object):
|
||||||
homepage=homepage
|
homepage=homepage
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Create a new wrapper nonce that allows to get one html file without the wrapper
|
||||||
|
def getWrapperNonce(self):
|
||||||
|
wrapper_nonce = ''.join(
|
||||||
|
random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for _ in range(24)
|
||||||
|
)
|
||||||
|
self.server.wrapper_nonces.append(wrapper_nonce)
|
||||||
|
return wrapper_nonce
|
||||||
|
|
||||||
# Returns if media request allowed from that referer
|
# Returns if media request allowed from that referer
|
||||||
def isMediaRequestAllowed(self, site_address, referer):
|
def isMediaRequestAllowed(self, site_address, referer):
|
||||||
|
@ -276,6 +286,14 @@ class UiRequest(object):
|
||||||
|
|
||||||
match = re.match("/media/(?P<address>[A-Za-z0-9\._-]+)/(?P<inner_path>.*)", path)
|
match = re.match("/media/(?P<address>[A-Za-z0-9\._-]+)/(?P<inner_path>.*)", path)
|
||||||
|
|
||||||
|
# Check wrapper nonce
|
||||||
|
content_type = self.getContentType(path)
|
||||||
|
if "htm" in content_type: # Valid nonce must present to render html files
|
||||||
|
wrapper_nonce = self.get["wrapper_nonce"]
|
||||||
|
if wrapper_nonce not in self.server.wrapper_nonces:
|
||||||
|
return self.error403("Wrapper nonce error.")
|
||||||
|
self.server.wrapper_nonces.remove(self.get["wrapper_nonce"])
|
||||||
|
|
||||||
referer = self.env.get("HTTP_REFERER")
|
referer = self.env.get("HTTP_REFERER")
|
||||||
if referer and match: # Only allow same site to receive media
|
if referer and match: # Only allow same site to receive media
|
||||||
if not self.isMediaRequestAllowed(match.group("address"), referer):
|
if not self.isMediaRequestAllowed(match.group("address"), referer):
|
||||||
|
@ -421,24 +439,38 @@ class UiRequest(object):
|
||||||
# - Errors -
|
# - Errors -
|
||||||
|
|
||||||
# Send bad request error
|
# Send bad request error
|
||||||
def error400(self):
|
def error400(self, message=""):
|
||||||
self.sendHeader(400)
|
self.sendHeader(400)
|
||||||
return "Bad Request"
|
return self.formatError("Bad Request", message)
|
||||||
|
|
||||||
# You are not allowed to access this
|
# You are not allowed to access this
|
||||||
def error403(self, message="Forbidden"):
|
def error403(self, message=""):
|
||||||
self.sendHeader(403)
|
self.sendHeader(403)
|
||||||
return message
|
return self.formatError("Forbidden", message)
|
||||||
|
|
||||||
# Send file not found error
|
# Send file not found error
|
||||||
def error404(self, path=None):
|
def error404(self, path=""):
|
||||||
self.sendHeader(404)
|
self.sendHeader(404)
|
||||||
return "Not Found: %s" % path.encode("utf8")
|
return self.formatError("Not Found", path.encode("utf8"))
|
||||||
|
|
||||||
# Internal server error
|
# Internal server error
|
||||||
def error500(self, message=":("):
|
def error500(self, message=":("):
|
||||||
self.sendHeader(500)
|
self.sendHeader(500)
|
||||||
return "<h1>Server error</h1>%s" % cgi.escape(message)
|
return self.formatError("Server error", cgi.escape(message))
|
||||||
|
|
||||||
|
def formatError(self, title, message):
|
||||||
|
details = {key: val for key, val in self.env.items() if hasattr(val, "endswith") and "COOKIE" not in key }
|
||||||
|
return """
|
||||||
|
<h1>%s</h1>
|
||||||
|
<h2>%s</h3>
|
||||||
|
<h3>Please <a href="https://github.com/HelloZeroNet/ZeroNet/issues">report it</a> if you think this an error.</h3>
|
||||||
|
<h4>Details:</h4>
|
||||||
|
<pre>%s</pre>
|
||||||
|
<style>
|
||||||
|
* { font-family: Consolas, Monospace; color: #333 }
|
||||||
|
pre { padding: 10px; background-color: #EEE }
|
||||||
|
</style>
|
||||||
|
""" % (title, message, json.dumps(details, indent=4))
|
||||||
|
|
||||||
|
|
||||||
# - Reload for eaiser developing -
|
# - Reload for eaiser developing -
|
||||||
|
|
|
@ -55,6 +55,7 @@ class UiServer:
|
||||||
self.port = config.ui_port
|
self.port = config.ui_port
|
||||||
if self.ip == "*":
|
if self.ip == "*":
|
||||||
self.ip = "" # Bind all
|
self.ip = "" # Bind all
|
||||||
|
self.wrapper_nonces = []
|
||||||
self.sites = SiteManager.site_manager.list()
|
self.sites = SiteManager.site_manager.list()
|
||||||
self.log = logging.getLogger(__name__)
|
self.log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ a { color: black }
|
||||||
display: block; width: 80px; height: 80px; -webkit-transition: background-color 0.2s, box-shadow 0.5s; -moz-transition: background-color 0.2s, box-shadow 0.5s; -o-transition: background-color 0.2s, box-shadow 0.5s; -ms-transition: background-color 0.2s, box-shadow 0.5s; transition: background-color 0.2s, box-shadow 0.5s ; -webkit-transform: scale(0.6); -moz-transform: scale(0.6); -o-transform: scale(0.6); -ms-transform: scale(0.6); transform: scale(0.6) ; margin-left: -20px; margin-top: -20px; /* 2x size to prevent blur on anim */
|
display: block; width: 80px; height: 80px; -webkit-transition: background-color 0.2s, box-shadow 0.5s; -moz-transition: background-color 0.2s, box-shadow 0.5s; -o-transition: background-color 0.2s, box-shadow 0.5s; -ms-transition: background-color 0.2s, box-shadow 0.5s; transition: background-color 0.2s, box-shadow 0.5s ; -webkit-transform: scale(0.6); -moz-transform: scale(0.6); -o-transform: scale(0.6); -ms-transform: scale(0.6); transform: scale(0.6) ; margin-left: -20px; margin-top: -20px; /* 2x size to prevent blur on anim */
|
||||||
/*box-shadow: inset 105px 260px 0px -200px rgba(0,0,0,0.1);*/ /* -webkit-box-shadow: inset -75px 183px 0px -200px rgba(0,0,0,0.1); -moz-box-shadow: inset -75px 183px 0px -200px rgba(0,0,0,0.1); -o-box-shadow: inset -75px 183px 0px -200px rgba(0,0,0,0.1); -ms-box-shadow: inset -75px 183px 0px -200px rgba(0,0,0,0.1); box-shadow: inset -75px 183px 0px -200px rgba(0,0,0,0.1) ; */
|
/*box-shadow: inset 105px 260px 0px -200px rgba(0,0,0,0.1);*/ /* -webkit-box-shadow: inset -75px 183px 0px -200px rgba(0,0,0,0.1); -moz-box-shadow: inset -75px 183px 0px -200px rgba(0,0,0,0.1); -o-box-shadow: inset -75px 183px 0px -200px rgba(0,0,0,0.1); -ms-box-shadow: inset -75px 183px 0px -200px rgba(0,0,0,0.1); box-shadow: inset -75px 183px 0px -200px rgba(0,0,0,0.1) ; */
|
||||||
}
|
}
|
||||||
.fixbutton-text { pointer-events: none; position: absolute; z-index: 999; width: 40px; backface-visibility: hidden; -webkit-perspective: 1000px; -moz-perspective: 1000px; -o-perspective: 1000px; -ms-perspective: 1000px; perspective: 1000px ; line-height: 0px; padding-top: 20px }
|
.fixbutton-text { pointer-events: none; position: absolute; z-index: 999; width: 40px; -webkit-backface-visibility: hidden; -moz-backface-visibility: hidden; -o-backface-visibility: hidden; -ms-backface-visibility: hidden; backface-visibility: hidden ; -webkit-perspective: 1000px; -moz-perspective: 1000px; -o-perspective: 1000px; -ms-perspective: 1000px; perspective: 1000px ; line-height: 0px; padding-top: 20px }
|
||||||
.fixbutton-burger { pointer-events: none; position: absolute; z-index: 999; width: 40px; opacity: 0; left: -20px; font-size: 40px; line-height: 0px; font-family: Verdana, sans-serif; margin-top: 17px }
|
.fixbutton-burger { pointer-events: none; position: absolute; z-index: 999; width: 40px; opacity: 0; left: -20px; font-size: 40px; line-height: 0px; font-family: Verdana, sans-serif; margin-top: 17px }
|
||||||
.fixbutton-bg:hover { background-color: #AF3BFF }
|
.fixbutton-bg:hover { background-color: #AF3BFF }
|
||||||
.fixbutton-bg:active { background-color: #9E2FEA; top: 1px; -webkit-transition: none ; -moz-transition: none ; -o-transition: none ; -ms-transition: none ; transition: none }
|
.fixbutton-bg:active { background-color: #9E2FEA; top: 1px; -webkit-transition: none ; -moz-transition: none ; -o-transition: none ; -ms-transition: none ; transition: none }
|
||||||
|
@ -45,7 +45,7 @@ a { color: black }
|
||||||
|
|
||||||
.notifications { position: absolute; top: 0px; right: 80px; display: inline-block; z-index: 999; white-space: nowrap }
|
.notifications { position: absolute; top: 0px; right: 80px; display: inline-block; z-index: 999; white-space: nowrap }
|
||||||
.notification {
|
.notification {
|
||||||
position: relative; float: right; clear: both; margin: 10px; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; -o-box-sizing: border-box; -ms-box-sizing: border-box; box-sizing: border-box ; overflow: hidden; backface-visibility: hidden; -webkit-perspective: 1000px; -moz-perspective: 1000px; -o-perspective: 1000px; -ms-perspective: 1000px; perspective: 1000px ; padding-bottom: 5px;
|
position: relative; float: right; clear: both; margin: 10px; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; -o-box-sizing: border-box; -ms-box-sizing: border-box; box-sizing: border-box ; overflow: hidden; -webkit-backface-visibility: hidden; -moz-backface-visibility: hidden; -o-backface-visibility: hidden; -ms-backface-visibility: hidden; backface-visibility: hidden ; -webkit-perspective: 1000px; -moz-perspective: 1000px; -o-perspective: 1000px; -ms-perspective: 1000px; perspective: 1000px ; padding-bottom: 5px;
|
||||||
color: #4F4F4F; font-family: 'Lucida Grande', 'Segoe UI', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px; /*border: 1px solid rgba(210, 206, 205, 0.2)*/
|
color: #4F4F4F; font-family: 'Lucida Grande', 'Segoe UI', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px; /*border: 1px solid rgba(210, 206, 205, 0.2)*/
|
||||||
}
|
}
|
||||||
.notification-icon {
|
.notification-icon {
|
||||||
|
@ -112,7 +112,7 @@ a { color: black }
|
||||||
.flipper-container { width: 40px; height: 40px; position: absolute; top: 0%; left: 50%; -webkit-transform: translate3d(-50%, -50%, 0); -moz-transform: translate3d(-50%, -50%, 0); -o-transform: translate3d(-50%, -50%, 0); -ms-transform: translate3d(-50%, -50%, 0); transform: translate3d(-50%, -50%, 0) ; -webkit-perspective: 1200; -moz-perspective: 1200; -o-perspective: 1200; -ms-perspective: 1200; perspective: 1200 ; opacity: 0 }
|
.flipper-container { width: 40px; height: 40px; position: absolute; top: 0%; left: 50%; -webkit-transform: translate3d(-50%, -50%, 0); -moz-transform: translate3d(-50%, -50%, 0); -o-transform: translate3d(-50%, -50%, 0); -ms-transform: translate3d(-50%, -50%, 0); transform: translate3d(-50%, -50%, 0) ; -webkit-perspective: 1200; -moz-perspective: 1200; -o-perspective: 1200; -ms-perspective: 1200; perspective: 1200 ; opacity: 0 }
|
||||||
.flipper { position: relative; display: block; height: inherit; width: inherit; -webkit-animation: flip 1.2s infinite ease-in-out; -moz-animation: flip 1.2s infinite ease-in-out; -o-animation: flip 1.2s infinite ease-in-out; -ms-animation: flip 1.2s infinite ease-in-out; animation: flip 1.2s infinite ease-in-out ; -webkit-transform-style: preserve-3d; }
|
.flipper { position: relative; display: block; height: inherit; width: inherit; -webkit-animation: flip 1.2s infinite ease-in-out; -moz-animation: flip 1.2s infinite ease-in-out; -o-animation: flip 1.2s infinite ease-in-out; -ms-animation: flip 1.2s infinite ease-in-out; animation: flip 1.2s infinite ease-in-out ; -webkit-transform-style: preserve-3d; }
|
||||||
.flipper .front, .flipper .back {
|
.flipper .front, .flipper .back {
|
||||||
position: absolute; top: 0; left: 0; backface-visibility: hidden; /*transform-style: preserve-3d;*/ display: block;
|
position: absolute; top: 0; left: 0; -webkit-backface-visibility: hidden; -moz-backface-visibility: hidden; -o-backface-visibility: hidden; -ms-backface-visibility: hidden; backface-visibility: hidden ; /*transform-style: preserve-3d;*/ display: block;
|
||||||
background-color: #d50000; height: 100%; width: 100%; /*outline: 1px solid transparent; /* FF AA fix */
|
background-color: #d50000; height: 100%; width: 100%; /*outline: 1px solid transparent; /* FF AA fix */
|
||||||
}
|
}
|
||||||
.flipper .back { background-color: white; z-index: 800; -webkit-transform: rotateY(-180deg) ; -moz-transform: rotateY(-180deg) ; -o-transform: rotateY(-180deg) ; -ms-transform: rotateY(-180deg) ; transform: rotateY(-180deg) }
|
.flipper .back { background-color: white; z-index: 800; -webkit-transform: rotateY(-180deg) ; -moz-transform: rotateY(-180deg) ; -o-transform: rotateY(-180deg) ; -ms-transform: rotateY(-180deg) ; transform: rotateY(-180deg) }
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
// If we are inside iframe escape from it
|
// If we are inside iframe escape from it
|
||||||
if (window.self !== window.top) window.open(window.location.toString(), "_top");
|
if (window.self !== window.top) window.open(window.location.toString(), "_top");
|
||||||
if (window.self !== window.top) window.stop();
|
if (window.self !== window.top) window.stop();
|
||||||
|
if (window.self !== window.top && document.execCommand) document.execCommand("Stop", false)
|
||||||
|
|
||||||
// Dont allow site to load in a popup
|
// Dont allow site to load in a popup
|
||||||
if (window.opener) document.write("Opener not allowed")
|
if (window.opener) document.write("Opener not allowed")
|
||||||
|
@ -51,10 +52,13 @@ if (window.opener && window.stop) window.stop()
|
||||||
|
|
||||||
|
|
||||||
<!-- Site Iframe -->
|
<!-- Site Iframe -->
|
||||||
<iframe src='{file_url}{query_string}' id='inner-iframe' sandbox="allow-forms allow-scripts allow-top-navigation allow-popups"></iframe>
|
<iframe src='about:blank' id='inner-iframe' sandbox="allow-forms allow-scripts allow-top-navigation allow-popups"></iframe>
|
||||||
|
|
||||||
<!-- Site info -->
|
<!-- Site info -->
|
||||||
<script>
|
<script>
|
||||||
|
console.log("Setting iframe src", document.getElementById("inner-iframe").src, "{file_url}{query_string}")
|
||||||
|
document.getElementById("inner-iframe").src = "about:blank"
|
||||||
|
document.getElementById("inner-iframe").src = "{file_url}{query_string}"
|
||||||
address = "{address}"
|
address = "{address}"
|
||||||
wrapper_key = "{wrapper_key}"
|
wrapper_key = "{wrapper_key}"
|
||||||
file_inner_path = "{file_inner_path}"
|
file_inner_path = "{file_inner_path}"
|
||||||
|
|
|
@ -61,7 +61,7 @@ class WorkerManager:
|
||||||
elif (task["time_started"] and time.time() >= task["time_started"] + 15) or not self.workers:
|
elif (task["time_started"] and time.time() >= task["time_started"] + 15) or not self.workers:
|
||||||
# Task started more than 15 sec ago or no workers
|
# Task started more than 15 sec ago or no workers
|
||||||
self.log.debug("Task taking more than 15 secs, find more peers: %s" % task["inner_path"])
|
self.log.debug("Task taking more than 15 secs, find more peers: %s" % task["inner_path"])
|
||||||
task["site"].announce() # Find more peers
|
task["site"].announce(num=1) # Find more peers
|
||||||
if task["peers"]: # Release the peer lock
|
if task["peers"]: # Release the peer lock
|
||||||
self.log.debug("Task peer lock release: %s" % task["inner_path"])
|
self.log.debug("Task peer lock release: %s" % task["inner_path"])
|
||||||
task["peers"] = []
|
task["peers"] = []
|
||||||
|
|
|
@ -14,6 +14,8 @@ update_after_shutdown = False # If set True then update and restart zeronet aft
|
||||||
# Load config
|
# Load config
|
||||||
from Config import config
|
from Config import config
|
||||||
config.parse(silent=True) # Plugins need to access the configuration
|
config.parse(silent=True) # Plugins need to access the configuration
|
||||||
|
if not config.arguments: # Config parse failed, show the help screen and exit
|
||||||
|
config.parse()
|
||||||
|
|
||||||
# Create necessary files and dirs
|
# Create necessary files and dirs
|
||||||
if not os.path.isdir(config.log_dir):
|
if not os.path.isdir(config.log_dir):
|
||||||
|
|
Loading…
Reference in a new issue