diff --git a/src/Config.py b/src/Config.py index 8fb8d133..41a57406 100644 --- a/src/Config.py +++ b/src/Config.py @@ -8,7 +8,7 @@ class Config(object): def __init__(self, argv): self.version = "0.3.2" - self.rev = 445 + self.rev = 448 self.argv = argv self.action = None self.createParser() @@ -203,12 +203,12 @@ class Config(object): original_print_message = self.parser._print_message original_exit = self.parser.exit - def silent(parser, function_name): + def silencer(parser, function_name): parser.exited = True return None self.parser.exited = False - self.parser._print_message = lambda *args, **kwargs: silent(self.parser, "_print_message") - self.parser.exit = lambda *args, **kwargs: silent(self.parser, "exit") + self.parser._print_message = lambda *args, **kwargs: silencer(self.parser, "_print_message") + self.parser.exit = lambda *args, **kwargs: silencer(self.parser, "exit") argv = self.argv[:] # Copy command line arguments if parse_config: diff --git a/src/Content/ContentManager.py b/src/Content/ContentManager.py index 0211b8fc..fa0ae8f1 100644 --- a/src/Content/ContentManager.py +++ b/src/Content/ContentManager.py @@ -528,49 +528,46 @@ class ContentManager(object): return file_dir -def testSign(): - global config - from Site import Site - site = Site("12Hw8rTgzrNo4DSh2AkqwPRqDyTticwJyH") - content_manager = ContentManager(site) - content_manager.sign( - "data/users/1KRxE1s3oDyNDawuYWpzbLUwNm8oDbeEp6/content.json", "5JCGE6UUruhfmAfcZ2GYjvrswkaiq7uLo6Gmtf2ep2Jh2jtNzWR" - ) - - -def testVerify(): - from Site import Site - site = Site("12Hw8rTgzrNo4DSh2AkqwPRqDyTticwJyH") - - content_manager = ContentManager(site) - print "Loaded contents:", content_manager.contents.keys() - - file = open(site.storage.getPath("data/users/1KRxE1s3oDyNDawuYWpzbLUwNm8oDbeEp6/content.json")) - print "content.json valid:", content_manager.verifyFile( - "data/users/1KRxE1s3oDyNDawuYWpzbLUwNm8oDbeEp6/content.json", file, ignore_same=False - ) - - file = open(site.storage.getPath("data/users/1KRxE1s3oDyNDawuYWpzbLUwNm8oDbeEp6/messages.json")) - print "messages.json valid:", content_manager.verifyFile( - "data/users/1KRxE1s3oDyNDawuYWpzbLUwNm8oDbeEp6/messages.json", file, ignore_same=False - ) - - -def testInfo(): - from Site import Site - site = Site("12Hw8rTgzrNo4DSh2AkqwPRqDyTticwJyH") - - content_manager = ContentManager(site) - print content_manager.contents.keys() - - print content_manager.getFileInfo("index.html") - print content_manager.getIncludeInfo("data/users/1KRxE1s3oDyNDawuYWpzbLUwNm8oDbeEp6/content.json") - print content_manager.getValidSigners("data/users/1KRxE1s3oDyNDawuYWpzbLUwNm8oDbeEp6/content.json") - print content_manager.getValidSigners("data/users/content.json") - print content_manager.getValidSigners("content.json") - - if __name__ == "__main__": + def testSign(): + global config + from Site import Site + site = Site("12Hw8rTgzrNo4DSh2AkqwPRqDyTticwJyH") + content_manager = ContentManager(site) + content_manager.sign( + "data/users/1KRxE1s3oDyNDawuYWpzbLUwNm8oDbeEp6/content.json", "5JCGE6UUruhfmAfcZ2GYjvrswkaiq7uLo6Gmtf2ep2Jh2jtNzWR" + ) + + def testVerify(): + from Site import Site + site = Site("12Hw8rTgzrNo4DSh2AkqwPRqDyTticwJyH") + + content_manager = ContentManager(site) + print "Loaded contents:", content_manager.contents.keys() + + file = open(site.storage.getPath("data/users/1KRxE1s3oDyNDawuYWpzbLUwNm8oDbeEp6/content.json")) + print "content.json valid:", content_manager.verifyFile( + "data/users/1KRxE1s3oDyNDawuYWpzbLUwNm8oDbeEp6/content.json", file, ignore_same=False + ) + + file = open(site.storage.getPath("data/users/1KRxE1s3oDyNDawuYWpzbLUwNm8oDbeEp6/messages.json")) + print "messages.json valid:", content_manager.verifyFile( + "data/users/1KRxE1s3oDyNDawuYWpzbLUwNm8oDbeEp6/messages.json", file, ignore_same=False + ) + + def testInfo(): + from Site import Site + site = Site("12Hw8rTgzrNo4DSh2AkqwPRqDyTticwJyH") + + content_manager = ContentManager(site) + print content_manager.contents.keys() + + print content_manager.getFileInfo("index.html") + print content_manager.getIncludeInfo("data/users/1KRxE1s3oDyNDawuYWpzbLUwNm8oDbeEp6/content.json") + print content_manager.getValidSigners("data/users/1KRxE1s3oDyNDawuYWpzbLUwNm8oDbeEp6/content.json") + print content_manager.getValidSigners("data/users/content.json") + print content_manager.getValidSigners("content.json") + import sys import logging os.chdir("../..") diff --git a/src/Crypt/CryptConnection.py b/src/Crypt/CryptConnection.py index 5608b740..fb2c0920 100644 --- a/src/Crypt/CryptConnection.py +++ b/src/Crypt/CryptConnection.py @@ -5,7 +5,7 @@ import ssl from Config import config from util import SslPatch -from util import utils +from util import helper class CryptConnectionManager: @@ -65,7 +65,7 @@ class CryptConnectionManager: return True # Files already exits proc = subprocess.Popen( - "%s req -x509 -newkey rsa:2048 -sha256 -batch -keyout %s -out %s -nodes -config %s" % utils.shellquote( + "%s req -x509 -newkey rsa:2048 -sha256 -batch -keyout %s -out %s -nodes -config %s" % helper.shellquote( self.openssl_bin, config.data_dir+"/key-rsa.pem", config.data_dir+"/cert-rsa.pem", @@ -99,7 +99,7 @@ class CryptConnectionManager: # Create ECC cert proc = subprocess.Popen( - "%s req -new -key %s -x509 -nodes -out %s -config %s" % utils.shellquote( + "%s req -new -key %s -x509 -nodes -out %s -config %s" % helper.shellquote( self.openssl_bin, config.data_dir+"/key-ecc.pem", config.data_dir+"/cert-ecc.pem", @@ -118,4 +118,4 @@ class CryptConnectionManager: return False """ -manager = CryptConnectionManager() \ No newline at end of file +manager = CryptConnectionManager() diff --git a/src/Debug/DebugMedia.py b/src/Debug/DebugMedia.py index abe49a79..27256d09 100644 --- a/src/Debug/DebugMedia.py +++ b/src/Debug/DebugMedia.py @@ -5,7 +5,7 @@ import logging import time from Config import config -from util import utils +from util import helper # Find files with extension in path @@ -23,7 +23,7 @@ def findCoffeescriptCompiler(): coffeescript_compiler = None try: import distutils.spawn - coffeescript_compiler = utils.shellquote(distutils.spawn.find_executable("coffee")) + " --no-header -p" + coffeescript_compiler = helper.shellquote(distutils.spawn.find_executable("coffee")) + " --no-header -p" except: pass if coffeescript_compiler: @@ -75,7 +75,7 @@ def merge(merged_path): return False # No coffeescript compiler, skip this file # Replace / with os separators and escape it - file_path_escaped = utils.shellquote(os.path.join(*file_path.split("/"))) + file_path_escaped = helper.shellquote(os.path.join(*file_path.split("/"))) if "%s" in config.coffeescript_compiler: # Replace %s with coffeescript file command = config.coffeescript_compiler % file_path_escaped diff --git a/src/File/FileRequest.py b/src/File/FileRequest.py index 96ed4c2f..bb4dc3f4 100644 --- a/src/File/FileRequest.py +++ b/src/File/FileRequest.py @@ -9,7 +9,9 @@ import gevent from Debug import Debug from Config import config -from util import RateLimit, StreamingMsgpack +from util import RateLimit +from util import StreamingMsgpack +from util import helper FILE_BUFF = 1024 * 512 @@ -27,9 +29,6 @@ class FileRequest(object): self.log = server.log self.responded = False # Responded to the request - def unpackAddress(self, packed): - return socket.inet_ntoa(packed[0:4]), struct.unpack_from("H", packed, 4)[0] - def send(self, msg, streaming=False): if not self.connection.closed: self.connection.send(msg, streaming) @@ -221,8 +220,8 @@ class FileRequest(object): added += 1 connected_peer.connect(self.connection) # Assign current connection to peer - for peer in params["peers"]: # Add sent peers to site - address = self.unpackAddress(peer) + for addr_packed in params["peers"]: # Add sent peers to site + address = helper.unpackAddress(addr_packed) got_peer_keys.append("%s:%s" % address) if site.addPeer(*address): added += 1 diff --git a/src/Peer/Peer.py b/src/Peer/Peer.py index 09f4702e..77b689b7 100644 --- a/src/Peer/Peer.py +++ b/src/Peer/Peer.py @@ -1,17 +1,16 @@ import logging import gevent import time -import sys -import socket -import struct from cStringIO import StringIO from Debug import Debug from Config import config +from util import helper if config.use_tempfiles: import tempfile + # Communicate remote peers class Peer(object): __slots__ = ( @@ -77,12 +76,8 @@ class Peer(object): def __repr__(self): return "<%s>" % self.__str__() - # Peer ip:port to packed 6byte format - def packAddress(self): - return socket.inet_aton(self.ip) + struct.pack("H", self.port) - - def unpackAddress(self, packed): - return socket.inet_ntoa(packed[0:4]), struct.unpack_from("H", packed, 4)[0] + def packMyAddress(self): + return helper.packAddress(self.ip, self.port) # Found a peer on tracker def found(self): @@ -209,13 +204,13 @@ class Peer(object): if not site: site = self.site # If no site defined request peers for this site # give him/her 5 connectible peers - packed_peers = [peer.packAddress() for peer in self.site.getConnectablePeers(5)] + packed_peers = [peer.packMyAddress() for peer in self.site.getConnectablePeers(5)] response = self.request("pex", {"site": site.address, "peers": packed_peers, "need": need_num}) if not response or "error" in response: return False added = 0 for peer in response.get("peers", []): - address = self.unpackAddress(peer) + address = helper.unpackAddress(peer) if site.addPeer(*address): added += 1 if added: diff --git a/src/Site/Site.py b/src/Site/Site.py index 7d6f0fe5..61ae9ccc 100644 --- a/src/Site/Site.py +++ b/src/Site/Site.py @@ -24,7 +24,7 @@ from Debug import Debug from Content import ContentManager from SiteStorage import SiteStorage from Crypt import CryptHash -from util import utils +from util import helper import SiteManager @@ -92,7 +92,7 @@ class Site: def saveSettings(self): sites_settings = json.load(open("%s/sites.json" % config.data_dir)) sites_settings[self.address] = self.settings - utils.atomicWrite("%s/sites.json" % config.data_dir, json.dumps(sites_settings, indent=2, sort_keys=True)) + helper.atomicWrite("%s/sites.json" % config.data_dir, json.dumps(sites_settings, indent=2, sort_keys=True)) # Max site size in MB def getSizeLimit(self): @@ -172,7 +172,7 @@ class Site: ) gevent.spawn(self.announce) if check_size: # Check the size first - valid = self.downloadContent(download_files=False) # Just download content.json files + valid = self.downloadContent("content.json", download_files=False) # Just download content.json files if not valid: return False # Cant download content.jsons or size is not fits diff --git a/src/Site/SiteStorage.py b/src/Site/SiteStorage.py index 02f58f5f..9368fbb6 100644 --- a/src/Site/SiteStorage.py +++ b/src/Site/SiteStorage.py @@ -57,7 +57,7 @@ class SiteStorage: def getDb(self): if not self.db: self.log.debug("No database, waiting for dbschema.json...") - self.site.needFile("dbschema.json", priority=1) + self.site.needFile("dbschema.json", priority=3) self.has_db = self.isFile("dbschema.json") # Recheck if dbschema exist if self.has_db: self.openDb() diff --git a/src/Test/TestCryptBitcoin.py b/src/Test/TestCryptBitcoin.py index dad17d0d..bebf906e 100644 --- a/src/Test/TestCryptBitcoin.py +++ b/src/Test/TestCryptBitcoin.py @@ -42,3 +42,16 @@ class TestCryptBitcoin: # Signed by bad privatekey sign_bad = CryptBitcoin.sign("hello", privatekey_bad) assert not CryptBitcoin.verify("hello", address, sign_bad) + + def testNewPrivatekey(self): + assert CryptBitcoin.newPrivatekey() != CryptBitcoin.newPrivatekey() + assert CryptBitcoin.privatekeyToAddress(CryptBitcoin.newPrivatekey()) + + def testNewSeed(self): + assert CryptBitcoin.newSeed() != CryptBitcoin.newSeed() + assert CryptBitcoin.privatekeyToAddress( + CryptBitcoin.hdPrivatekey(CryptBitcoin.newSeed(), 0) + ) + assert CryptBitcoin.privatekeyToAddress( + CryptBitcoin.hdPrivatekey(CryptBitcoin.newSeed(), 2**256) + ) diff --git a/src/Test/TestHelper.py b/src/Test/TestHelper.py new file mode 100644 index 00000000..c017dea9 --- /dev/null +++ b/src/Test/TestHelper.py @@ -0,0 +1,17 @@ +class Spy: + def __init__(self, obj, func_name): + self.obj = obj + self.func_name = func_name + self.func_original = getattr(self.obj, func_name) + self.calls = [] + + def __enter__(self, *args, **kwargs): + def loggedFunc(cls, *args, **kwags): + print "Logging", self, args, kwargs + self.calls.append(args) + return self.func_original(cls, *args, **kwargs) + setattr(self.obj, self.func_name, loggedFunc) + return self.calls + + def __exit__(self, *args, **kwargs): + setattr(self.obj, self.func_name, self.func_original) \ No newline at end of file diff --git a/src/Test/TestWorker.py b/src/Test/TestWorker.py index 36a329ef..f5d1abf7 100644 --- a/src/Test/TestWorker.py +++ b/src/Test/TestWorker.py @@ -1,22 +1,21 @@ -import time -import os - -import gevent import pytest import mock +import time -from Crypt import CryptConnection from Connection import ConnectionServer from Config import config from Site import Site +from File import FileRequest +import TestHelper @pytest.mark.usefixtures("resetTempSettings") @pytest.mark.usefixtures("resetSettings") class TestWorker: def testDownload(self, file_server, site, site_temp): + client = ConnectionServer("127.0.0.1", 1545) - assert site.storage.directory == config.data_dir+"/"+site.address - assert site_temp.storage.directory == config.data_dir+"-temp/"+site.address + assert site.storage.directory == config.data_dir + "/" + site.address + assert site_temp.storage.directory == config.data_dir + "-temp/" + site.address # Init source server site.connection_server = file_server @@ -26,10 +25,29 @@ class TestWorker: site_temp.connection_server = client site_temp.announce = mock.MagicMock(return_value=True) # Don't try to find peers from the net - # Download to client from source site_temp.addPeer("127.0.0.1", 1544) - site_temp.download().join(timeout=5) + with TestHelper.Spy(FileRequest, "route") as requests: + def boostRequest(inner_path): + # I really want these file + if inner_path == "index.html": + print "needFile" + site_temp.needFile("data/img/multiuser.png", priority=9, blocking=False) + site_temp.needFile("data/img/direct_domains.png", priority=10, blocking=False) + site_temp.onFileDone.append(boostRequest) + site_temp.download(blind_includes=True).join(timeout=5) + file_requests = [request[2]["inner_path"] for request in requests if request[0] in ("getFile", "streamFile")] + # Test priority + assert file_requests[0:2] == ["content.json", "index.html"] # Must-have files + assert file_requests[2:4] == ["data/img/direct_domains.png", "data/img/multiuser.png"] # Directly requested files + assert file_requests[4:6] == ["css/all.css", "js/all.js"] # Important assets + assert file_requests[6] == "dbschema.json" # Database map + assert "-default" in file_requests[-1] # Put default files for cloning to the end - assert not site_temp.bad_files + # Check files + bad_files = site_temp.storage.verifyFiles(quick_check=True) + + # -1 because data/users/1J6... user has invalid cert + assert len(site_temp.content_manager.contents) == len(site.content_manager.contents) - 1 + assert not bad_files site_temp.storage.deleteFiles() diff --git a/src/Ui/UiRequest.py b/src/Ui/UiRequest.py index decd05f5..d2a34ac7 100644 --- a/src/Ui/UiRequest.py +++ b/src/Ui/UiRequest.py @@ -330,7 +330,7 @@ class UiRequest(object): return self.actionFile(file_path) else: # File not exits, try to download site = SiteManager.site_manager.need(address, all_file=False) - result = site.needFile(match.group("inner_path"), priority=1) # Wait until file downloads + result = site.needFile(match.group("inner_path"), priority=5) # Wait until file downloads if result: return self.actionFile(file_path) else: diff --git a/src/Ui/media/Fixbutton.coffee b/src/Ui/media/Fixbutton.coffee index 1eb4f2e7..9e644a4e 100644 --- a/src/Ui/media/Fixbutton.coffee +++ b/src/Ui/media/Fixbutton.coffee @@ -1,12 +1,12 @@ class Fixbutton constructor: -> @dragging = false - $(".fixbutton-bg").on "mouseover", => + $(".fixbutton-bg").on "mouseover", -> $(".fixbutton-bg").stop().animate({"scale": 0.7}, 800, "easeOutElastic") $(".fixbutton-burger").stop().animate({"opacity": 1.5, "left": 0}, 800, "easeOutElastic") $(".fixbutton-text").stop().animate({"opacity": 0, "left": 20}, 300, "easeOutCubic") - $(".fixbutton-bg").on "mouseout", => + $(".fixbutton-bg").on "mouseout", -> if $(".fixbutton").hasClass("dragging") return true $(".fixbutton-bg").stop().animate({"scale": 0.6}, 300, "easeOutCubic") @@ -18,13 +18,13 @@ class Fixbutton return false ### - $(".fixbutton-bg").on "mousedown", => + $(".fixbutton-bg").on "mousedown", -> # $(".fixbutton-burger").stop().animate({"scale": 0.7, "left": 0}, 300, "easeOutCubic") #$("#inner-iframe").toggleClass("back") #$(".wrapper-iframe").stop().animate({"scale": 0.9}, 600, "easeOutCubic") #$("body").addClass("back") - $(".fixbutton-bg").on "mouseup", => + $(".fixbutton-bg").on "mouseup", -> # $(".fixbutton-burger").stop().animate({"scale": 1, "left": 0}, 600, "easeOutElastic") diff --git a/src/Ui/media/Loading.coffee b/src/Ui/media/Loading.coffee index 25cce3eb..a18ae4f9 100644 --- a/src/Ui/media/Loading.coffee +++ b/src/Ui/media/Loading.coffee @@ -21,7 +21,7 @@ class Loading if $(".console .button-setlimit").length == 0 # Not displaying it yet line = @printLine("Site size: #{parseInt(site_info.settings.size/1024/1024)}MB is larger than default allowed #{parseInt(site_info.size_limit)}MB", "warning") button = $("Open site and set size limit to #{site_info.next_size_limit}MB") - button.on "click", (=> return window.wrapper.setSizeLimit(site_info.next_size_limit) ) + button.on "click", (-> return window.wrapper.setSizeLimit(site_info.next_size_limit) ) line.after(button) setTimeout (=> @printLine('Ready.') @@ -54,7 +54,7 @@ class Loading if not @screen_visible then return false $(".loadingscreen .console .cursor").remove() # Remove previous cursor if type == "error" then text = "#{text}" else text = text+" " - + line = $("
#{text}
").appendTo(".loadingscreen .console") if type == "warning" then line.addClass("console-warning") return line diff --git a/src/Ui/media/Wrapper.coffee b/src/Ui/media/Wrapper.coffee index e811dee6..4625a99c 100644 --- a/src/Ui/media/Wrapper.coffee +++ b/src/Ui/media/Wrapper.coffee @@ -33,8 +33,6 @@ class Wrapper $("#inner-iframe").focus() - @ - # Incoming message from UiServer websocket onMessageWebsocket: (e) => diff --git a/src/Ui/media/Wrapper.css b/src/Ui/media/Wrapper.css index f22099e2..5c91e88e 100644 --- a/src/Ui/media/Wrapper.css +++ b/src/Ui/media/Wrapper.css @@ -1,11 +1,11 @@ -body { margin: 0px; padding: 0px; height: 100%; background-color: #D2CECD; overflow: hidden } +body { margin: 0; padding: 0; height: 100%; background-color: #D2CECD; overflow: hidden } body.back { background-color: #090909 } a { color: black } .template { display: none !important } -#inner-iframe { width: 100%; height: 100%; position: absolute; border: 0px } /*; transition: all 0.8s cubic-bezier(0.68, -0.55, 0.265, 1.55), opacity 0.8s ease-in-out*/ -#inner-iframe.back { transform: scale(0.95) translate(-300px, 0px); opacity: 0.4 } +#inner-iframe { width: 100%; height: 100%; position: absolute; border: 0 } /*; transition: all 0.8s cubic-bezier(0.68, -0.55, 0.265, 1.55), opacity 0.8s ease-in-out*/ +#inner-iframe.back { transform: scale(0.95) translate(-300px, 0); opacity: 0.4 } .button { padding: 5px 10px; margin-left: 10px; background-color: #FFF85F; border-bottom: 2px solid #CDBD1E; border-radius: 2px; text-decoration: none; transition: all 0.5s; background-position: left center; } .button:hover { background-color: #FFF400; border-bottom: 2px solid #4D4D4C; transition: none } @@ -29,17 +29,17 @@ a { color: black } .fixbutton-bg { border-radius: 80px; background-color: rgba(180, 180, 180, 0.5); cursor: pointer; display: block; width: 80px; height: 80px; transition: background-color 0.2s, box-shadow 0.5s; 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);*/ /* box-shadow: inset -75px 183px 0px -200px rgba(0,0,0,0.1); */ + /*box-shadow: inset 105px 260px 0 -200px rgba(0,0,0,0.1);*/ /* box-shadow: inset -75px 183px 0 -200px rgba(0,0,0,0.1); */ } -.fixbutton-text { pointer-events: none; position: absolute; z-index: 999; width: 40px; backface-visibility: hidden; 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-text { pointer-events: none; position: absolute; z-index: 999; width: 40px; backface-visibility: hidden; perspective: 1000px; line-height: 0; padding-top: 20px } +.fixbutton-burger { pointer-events: none; position: absolute; z-index: 999; width: 40px; opacity: 0; left: -20px; font-size: 40px; line-height: 0; font-family: Verdana, sans-serif; margin-top: 17px } .fixbutton-bg:hover { background-color: #AF3BFF } .fixbutton-bg:active { background-color: #9E2FEA; top: 1px; transition: none } /* Notification */ -.notifications { position: absolute; top: 0px; right: 80px; display: inline-block; z-index: 999; white-space: nowrap } +.notifications { position: absolute; top: 0; right: 80px; display: inline-block; z-index: 999; white-space: nowrap } .notification { position: relative; float: right; clear: both; margin: 10px; box-sizing: border-box; overflow: hidden; backface-visibility: hidden; 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)*/ @@ -50,18 +50,18 @@ a { color: black } } .notification .body { max-width: 560px; padding-left: 14px; padding-right: 60px; height: 40px; vertical-align: middle; display: table; - background-color: white; left: 50px; top: 0px; position: relative; padding-top: 5px; padding-bottom: 5px; + background-color: white; left: 50px; top: 0; position: relative; padding-top: 5px; padding-bottom: 5px; } .notification.long .body { padding-top: 10px; padding-bottom: 10px } .notification .message { display: table-cell; vertical-align: middle } .notification.visible { max-width: 350px } -.notification .close { position: absolute; top: 0px; right: 0px; font-size: 19px; line-height: 13px; color: #DDD; padding: 7px; text-decoration: none } +.notification .close { position: absolute; top: 0; right: 0; font-size: 19px; line-height: 13px; color: #DDD; padding: 7px; text-decoration: none } .notification .close:hover { color: black } .notification .close:active, .notification .close:focus { color: #AF3BFF } .notification small { color: #AAA } -.body-white .notification { box-shadow: 0px 1px 9px rgba(0,0,0,0.1) } +.body-white .notification { box-shadow: 0 1px 9px rgba(0,0,0,0.1) } /* Notification select */ .notification .select { @@ -126,7 +126,7 @@ a { color: black } .progressbar { background: #26C281; position: fixed; z-index: 100; top: 0; left: 0; width: 0%; height: 2px; transition: width 0.5s, opacity 1s; display: none } .progressbar .peg { - display: block; position: absolute; right: 0px; width: 100px; height: 100%; + display: block; position: absolute; right: 0; width: 100px; height: 100%; box-shadow: 0 0 10px #AF3BFF, 0 0 5px #29d; opacity: 1.0; transform: rotate(3deg) translate(0px, -4px); } diff --git a/src/Ui/media/all.css b/src/Ui/media/all.css index b29b9068..bcf20b3a 100644 --- a/src/Ui/media/all.css +++ b/src/Ui/media/all.css @@ -3,14 +3,14 @@ /* ---- src/Ui/media/Wrapper.css ---- */ -body { margin: 0px; padding: 0px; height: 100%; background-color: #D2CECD; overflow: hidden } +body { margin: 0; padding: 0; height: 100%; background-color: #D2CECD; overflow: hidden } body.back { background-color: #090909 } a { color: black } .template { display: none !important } -#inner-iframe { width: 100%; height: 100%; position: absolute; border: 0px } /*; transition: all 0.8s cubic-bezier(0.68, -0.55, 0.265, 1.55), opacity 0.8s ease-in-out*/ -#inner-iframe.back { -webkit-transform: scale(0.95) translate(-300px, 0px); -moz-transform: scale(0.95) translate(-300px, 0px); -o-transform: scale(0.95) translate(-300px, 0px); -ms-transform: scale(0.95) translate(-300px, 0px); transform: scale(0.95) translate(-300px, 0px) ; opacity: 0.4 } +#inner-iframe { width: 100%; height: 100%; position: absolute; border: 0 } /*; transition: all 0.8s cubic-bezier(0.68, -0.55, 0.265, 1.55), opacity 0.8s ease-in-out*/ +#inner-iframe.back { -webkit-transform: scale(0.95) translate(-300px, 0); -moz-transform: scale(0.95) translate(-300px, 0); -o-transform: scale(0.95) translate(-300px, 0); -ms-transform: scale(0.95) translate(-300px, 0); transform: scale(0.95) translate(-300px, 0) ; opacity: 0.4 } .button { padding: 5px 10px; margin-left: 10px; background-color: #FFF85F; border-bottom: 2px solid #CDBD1E; -webkit-border-radius: 2px; -moz-border-radius: 2px; -o-border-radius: 2px; -ms-border-radius: 2px; border-radius: 2px ; text-decoration: none; -webkit-transition: all 0.5s; -moz-transition: all 0.5s; -o-transition: all 0.5s; -ms-transition: all 0.5s; transition: all 0.5s ; background-position: left center; } .button:hover { background-color: #FFF400; border-bottom: 2px solid #4D4D4C; -webkit-transition: none ; -moz-transition: none ; -o-transition: none ; -ms-transition: none ; transition: none } @@ -34,17 +34,17 @@ a { color: black } .fixbutton-bg { -webkit-border-radius: 80px; -moz-border-radius: 80px; -o-border-radius: 80px; -ms-border-radius: 80px; border-radius: 80px ; background-color: rgba(180, 180, 180, 0.5); cursor: pointer; 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 0 -200px rgba(0,0,0,0.1);*/ /* -webkit-box-shadow: inset -75px 183px 0 -200px rgba(0,0,0,0.1); -moz-box-shadow: inset -75px 183px 0 -200px rgba(0,0,0,0.1); -o-box-shadow: inset -75px 183px 0 -200px rgba(0,0,0,0.1); -ms-box-shadow: inset -75px 183px 0 -200px rgba(0,0,0,0.1); box-shadow: inset -75px 183px 0 -200px rgba(0,0,0,0.1) ; */ } -.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-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: 0; padding-top: 20px } +.fixbutton-burger { pointer-events: none; position: absolute; z-index: 999; width: 40px; opacity: 0; left: -20px; font-size: 40px; line-height: 0; font-family: Verdana, sans-serif; margin-top: 17px } .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 } /* Notification */ -.notifications { position: absolute; top: 0px; right: 80px; display: inline-block; z-index: 999; white-space: nowrap } +.notifications { position: absolute; top: 0; right: 80px; display: inline-block; z-index: 999; white-space: nowrap } .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; -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)*/ @@ -55,18 +55,18 @@ a { color: black } } .notification .body { max-width: 560px; padding-left: 14px; padding-right: 60px; height: 40px; vertical-align: middle; display: table; - background-color: white; left: 50px; top: 0px; position: relative; padding-top: 5px; padding-bottom: 5px; + background-color: white; left: 50px; top: 0; position: relative; padding-top: 5px; padding-bottom: 5px; } .notification.long .body { padding-top: 10px; padding-bottom: 10px } .notification .message { display: table-cell; vertical-align: middle } .notification.visible { max-width: 350px } -.notification .close { position: absolute; top: 0px; right: 0px; font-size: 19px; line-height: 13px; color: #DDD; padding: 7px; text-decoration: none } +.notification .close { position: absolute; top: 0; right: 0; font-size: 19px; line-height: 13px; color: #DDD; padding: 7px; text-decoration: none } .notification .close:hover { color: black } .notification .close:active, .notification .close:focus { color: #AF3BFF } .notification small { color: #AAA } -.body-white .notification { -webkit-box-shadow: 0px 1px 9px rgba(0,0,0,0.1) ; -moz-box-shadow: 0px 1px 9px rgba(0,0,0,0.1) ; -o-box-shadow: 0px 1px 9px rgba(0,0,0,0.1) ; -ms-box-shadow: 0px 1px 9px rgba(0,0,0,0.1) ; box-shadow: 0px 1px 9px rgba(0,0,0,0.1) } +.body-white .notification { -webkit-box-shadow: 0 1px 9px rgba(0,0,0,0.1) ; -moz-box-shadow: 0 1px 9px rgba(0,0,0,0.1) ; -o-box-shadow: 0 1px 9px rgba(0,0,0,0.1) ; -ms-box-shadow: 0 1px 9px rgba(0,0,0,0.1) ; box-shadow: 0 1px 9px rgba(0,0,0,0.1) } /* Notification select */ .notification .select { @@ -131,7 +131,7 @@ a { color: black } .progressbar { background: #26C281; position: fixed; z-index: 100; top: 0; left: 0; width: 0%; height: 2px; -webkit-transition: width 0.5s, opacity 1s; -moz-transition: width 0.5s, opacity 1s; -o-transition: width 0.5s, opacity 1s; -ms-transition: width 0.5s, opacity 1s; transition: width 0.5s, opacity 1s ; display: none } .progressbar .peg { - display: block; position: absolute; right: 0px; width: 100px; height: 100%; + display: block; position: absolute; right: 0; width: 100px; height: 100%; -webkit-box-shadow: 0 0 10px #AF3BFF, 0 0 5px #29d; -moz-box-shadow: 0 0 10px #AF3BFF, 0 0 5px #29d; -o-box-shadow: 0 0 10px #AF3BFF, 0 0 5px #29d; -ms-box-shadow: 0 0 10px #AF3BFF, 0 0 5px #29d; box-shadow: 0 0 10px #AF3BFF, 0 0 5px #29d ; opacity: 1.0; -webkit-transform: rotate(3deg) translate(0px, -4px); -moz-transform: rotate(3deg) translate(0px, -4px); -o-transform: rotate(3deg) translate(0px, -4px); -ms-transform: rotate(3deg) translate(0px, -4px); transform: rotate(3deg) translate(0px, -4px) ; } diff --git a/src/Ui/media/all.js b/src/Ui/media/all.js index f4caf715..a18312fb 100644 --- a/src/Ui/media/all.js +++ b/src/Ui/media/all.js @@ -149,11 +149,12 @@ }).call(this); + /* ---- src/Ui/media/lib/jquery.cssanim.js ---- */ jQuery.cssHooks['scale'] = { - get: function(elem, computed, extra) { + get: function(elem, computed) { var match = window.getComputedStyle(elem)[transform_property].match("[0-9\.]+") if (match) { var scale = parseFloat(match[0]) @@ -256,6 +257,7 @@ if (window.getComputedStyle(document.body).transform) { }).call(this); + /* ---- src/Ui/media/lib/jquery.easing.1.3.js ---- */ @@ -475,49 +477,41 @@ jQuery.extend( jQuery.easing, Fixbutton = (function() { function Fixbutton() { this.dragging = false; - $(".fixbutton-bg").on("mouseover", (function(_this) { - return function() { - $(".fixbutton-bg").stop().animate({ - "scale": 0.7 - }, 800, "easeOutElastic"); - $(".fixbutton-burger").stop().animate({ - "opacity": 1.5, - "left": 0 - }, 800, "easeOutElastic"); - return $(".fixbutton-text").stop().animate({ - "opacity": 0, - "left": 20 - }, 300, "easeOutCubic"); - }; - })(this)); - $(".fixbutton-bg").on("mouseout", (function(_this) { - return function() { - if ($(".fixbutton").hasClass("dragging")) { - return true; - } - $(".fixbutton-bg").stop().animate({ - "scale": 0.6 - }, 300, "easeOutCubic"); - $(".fixbutton-burger").stop().animate({ - "opacity": 0, - "left": -20 - }, 300, "easeOutCubic"); - return $(".fixbutton-text").stop().animate({ - "opacity": 1, - "left": 0 - }, 300, "easeOutBack"); - }; - })(this)); + $(".fixbutton-bg").on("mouseover", function() { + $(".fixbutton-bg").stop().animate({ + "scale": 0.7 + }, 800, "easeOutElastic"); + $(".fixbutton-burger").stop().animate({ + "opacity": 1.5, + "left": 0 + }, 800, "easeOutElastic"); + return $(".fixbutton-text").stop().animate({ + "opacity": 0, + "left": 20 + }, 300, "easeOutCubic"); + }); + $(".fixbutton-bg").on("mouseout", function() { + if ($(".fixbutton").hasClass("dragging")) { + return true; + } + $(".fixbutton-bg").stop().animate({ + "scale": 0.6 + }, 300, "easeOutCubic"); + $(".fixbutton-burger").stop().animate({ + "opacity": 0, + "left": -20 + }, 300, "easeOutCubic"); + return $(".fixbutton-text").stop().animate({ + "opacity": 1, + "left": 0 + }, 300, "easeOutBack"); + }); /*$(".fixbutton-bg").on "click", -> return false */ - $(".fixbutton-bg").on("mousedown", (function(_this) { - return function() {}; - })(this)); - $(".fixbutton-bg").on("mouseup", (function(_this) { - return function() {}; - })(this)); + $(".fixbutton-bg").on("mousedown", function() {}); + $(".fixbutton-bg").on("mouseup", function() {}); } return Fixbutton; @@ -529,6 +523,7 @@ jQuery.extend( jQuery.easing, }).call(this); + /* ---- src/Ui/media/Loading.coffee ---- */ @@ -562,11 +557,9 @@ jQuery.extend( jQuery.easing, if ($(".console .button-setlimit").length === 0) { line = this.printLine("Site size: " + (parseInt(site_info.settings.size / 1024 / 1024)) + "MB is larger than default allowed " + (parseInt(site_info.size_limit)) + "MB", "warning"); button = $("Open site and set size limit to " + site_info.next_size_limit + "MB"); - button.on("click", ((function(_this) { - return function() { - return window.wrapper.setSizeLimit(site_info.next_size_limit); - }; - })(this))); + button.on("click", (function() { + return window.wrapper.setSizeLimit(site_info.next_size_limit); + })); line.after(button); return setTimeout(((function(_this) { return function() { @@ -634,6 +627,7 @@ jQuery.extend( jQuery.easing, }).call(this); + /* ---- src/Ui/media/Notifications.coffee ---- */ @@ -753,6 +747,7 @@ jQuery.extend( jQuery.easing, }).call(this); + /* ---- src/Ui/media/Wrapper.coffee ---- */ @@ -803,7 +798,6 @@ jQuery.extend( jQuery.easing, }; })(this)); $("#inner-iframe").focus(); - this; } Wrapper.prototype.onMessageWebsocket = function(e) { diff --git a/src/Ui/media/lib/jquery.cssanim.js b/src/Ui/media/lib/jquery.cssanim.js index be93a386..04879b62 100644 --- a/src/Ui/media/lib/jquery.cssanim.js +++ b/src/Ui/media/lib/jquery.cssanim.js @@ -1,5 +1,5 @@ jQuery.cssHooks['scale'] = { - get: function(elem, computed, extra) { + get: function(elem, computed) { var match = window.getComputedStyle(elem)[transform_property].match("[0-9\.]+") if (match) { var scale = parseFloat(match[0]) diff --git a/src/User/User.py b/src/User/User.py index 6e13c793..1822345e 100644 --- a/src/User/User.py +++ b/src/User/User.py @@ -5,7 +5,7 @@ import time from Crypt import CryptBitcoin from Plugin import PluginManager from Config import config -from util import utils +from util import helper @PluginManager.acceptPlugins class User(object): @@ -35,7 +35,7 @@ class User(object): user_data["master_seed"] = self.master_seed user_data["sites"] = self.sites user_data["certs"] = self.certs - utils.atomicWrite("%s/users.json" % config.data_dir, json.dumps(users, indent=2, sort_keys=True)) + helper.atomicWrite("%s/users.json" % config.data_dir, json.dumps(users, indent=2, sort_keys=True)) self.log.debug("Saved") def getAddressAuthIndex(self, address): diff --git a/src/Worker/WorkerManager.py b/src/Worker/WorkerManager.py index ba4b9f1a..06d438e6 100644 --- a/src/Worker/WorkerManager.py +++ b/src/Worker/WorkerManager.py @@ -72,16 +72,23 @@ class WorkerManager: # Tasks sorted by this def taskSorter(self, task): - if task["inner_path"] == "content.json": + inner_path = task["inner_path"] + if inner_path == "content.json": return 9999 # Content.json always prority - if task["inner_path"] == "index.html": + if inner_path == "index.html": return 9998 # index.html also important priority = task["priority"] - if task["inner_path"].endswith(".js") or task["inner_path"].endswith(".css"): - priority += 2 # boost js and css files priority - elif task["inner_path"].endswith(".json"): - priority += 1 # boost json files priority - return priority - task["workers_num"] # Prefer more priority and less workers + if "-default" in inner_path: + priority -= 4 # Default files are cloning not important + elif inner_path.endswith(".css"): + priority += 5 # boost css files priority + elif inner_path.endswith(".js"): + priority += 3 # boost js files priority + elif inner_path.endswith("content.json"): + priority += 1 # boost included content.json files priority a bit + elif inner_path.endswith(".json"): + priority += 2 # boost data json files priority more + return priority - task["workers_num"]*5 # Prefer more priority and less workers # Returns the next free or less worked task def getTask(self, peer): diff --git a/src/util/GeventSslPatch.py b/src/util/GeventSslPatch.py deleted file mode 100644 index 8eb8be80..00000000 --- a/src/util/GeventSslPatch.py +++ /dev/null @@ -1,52 +0,0 @@ -# Re-add sslwrap to Python 2.7.9 -# https://github.com/gevent/gevent/issues/477 - -import inspect -__ssl__ = __import__('ssl') - -try: - _ssl = __ssl__._ssl -except AttributeError: - _ssl = __ssl__._ssl2 - - -OldSSLSocket = __ssl__.SSLSocket - - -class NewSSLSocket(OldSSLSocket): - - """Fix SSLSocket constructor.""" - - def __init__( - self, sock, keyfile=None, certfile=None, server_side=False, cert_reqs=0, - ssl_version=2, ca_certs=None, do_handshake_on_connect=True, - suppress_ragged_eofs=True, ciphers=None, - server_hostname=None, _context=None - ): - OldSSLSocket.__init__( - self, sock, keyfile=None, certfile=None, server_side=False, cert_reqs=0, - ssl_version=2, ca_certs=None, do_handshake_on_connect=True, - suppress_ragged_eofs=True, ciphers=None - ) - - -def new_sslwrap( - sock, server_side=False, keyfile=None, certfile=None, - cert_reqs=__ssl__.CERT_NONE, ssl_version=__ssl__.PROTOCOL_SSLv23, - ca_certs=None, ciphers=None -): - context = __ssl__.SSLContext(ssl_version) - context.verify_mode = cert_reqs or __ssl__.CERT_NONE - if ca_certs: - context.load_verify_locations(ca_certs) - if certfile: - context.load_cert_chain(certfile, keyfile) - if ciphers: - context.set_ciphers(ciphers) - - caller_self = inspect.currentframe().f_back.f_locals['self'] - return context._wrap_socket(sock, server_side=server_side, ssl_sock=caller_self) - -if not hasattr(_ssl, 'sslwrap'): - _ssl.sslwrap = new_sslwrap - __ssl__.SSLSocket = NewSSLSocket diff --git a/src/util/Http.py b/src/util/Http.py index f8c62c72..05f6446e 100644 --- a/src/util/Http.py +++ b/src/util/Http.py @@ -1,13 +1,12 @@ import urllib2 import logging -import GeventSslPatch from Config import config -def get(url): +def get(url, accept="application/json"): logging.debug("Get %s" % url) req = urllib2.Request(url) req.add_header('User-Agent', "ZeroNet %s (https://github.com/HelloZeroNet/ZeroNet)" % config.version) - req.add_header('Accept', 'application/json') + req.add_header('Accept', accept) return urllib2.urlopen(req) diff --git a/src/util/utils.py b/src/util/helper.py similarity index 56% rename from src/util/utils.py rename to src/util/helper.py index 3381d9e6..2d8c4f33 100644 --- a/src/util/utils.py +++ b/src/util/helper.py @@ -1,4 +1,6 @@ import os +import socket +import struct def atomicWrite(dest, content, mode="w"): @@ -13,3 +15,11 @@ def shellquote(*args): return '"%s"' % args[0].replace('"', "") else: return tuple(['"%s"' % arg.replace('"', "") for arg in args]) + +# ip, port to packed 6byte format +def packAddress(ip, port): + return socket.inet_aton(ip) + struct.pack("H", port) + +# From 6byte format to ip, port +def unpackAddress(packed): + return socket.inet_ntoa(packed[0:4]), struct.unpack_from("H", packed, 4)[0] \ No newline at end of file