2015-01-12 02:03:45 +01:00
|
|
|
import os, sys
|
2015-02-20 01:37:12 +01:00
|
|
|
update_after_shutdown = False
|
2015-01-13 21:19:40 +01:00
|
|
|
sys.path.insert(0, os.path.dirname(__file__)) # Imports relative to main.py
|
2015-01-12 02:03:45 +01:00
|
|
|
|
2015-01-12 19:11:35 +01:00
|
|
|
# Create necessary files and dirs
|
|
|
|
if not os.path.isdir("log"): os.mkdir("log")
|
|
|
|
if not os.path.isdir("data"): os.mkdir("data")
|
|
|
|
if not os.path.isfile("data/sites.json"): open("data/sites.json", "w").write("{}")
|
version 0.2.0, new lib for bitcoin ecc, dont display or track notify errors, dont reload again within 1 sec, null peer ip fix, signingmoved to ContentManager, content.json include support, content.json multisig ready, content.json proper bitcoincore compatible signing, content.json include permissions, multithreaded publish, publish timeout 60s, no exception on invalid bitcoin address, testcase for new lib, bip32 based persite privatekey generation, multiuser ready, simple json database query command, websocket api fileGet, wrapper loading title stuck bugfix
2015-02-09 02:09:02 +01:00
|
|
|
if not os.path.isfile("data/users.json"): open("data/users.json", "w").write("{}")
|
2015-01-12 19:11:35 +01:00
|
|
|
|
2015-01-12 02:03:45 +01:00
|
|
|
# Load config
|
|
|
|
from Config import config
|
|
|
|
|
|
|
|
# Init logging
|
|
|
|
import logging
|
|
|
|
if config.action == "main":
|
|
|
|
if os.path.isfile("log/debug.log"): # Simple logrotate
|
|
|
|
if os.path.isfile("log/debug-last.log"): os.unlink("log/debug-last.log")
|
|
|
|
os.rename("log/debug.log", "log/debug-last.log")
|
|
|
|
logging.basicConfig(format='[%(asctime)s] %(levelname)-8s %(name)s %(message)s', level=logging.DEBUG, filename="log/debug.log")
|
|
|
|
else:
|
|
|
|
logging.basicConfig(level=logging.DEBUG, stream=open(os.devnull,"w")) # No file logging if action is not main
|
|
|
|
|
2015-01-17 18:50:56 +01:00
|
|
|
# Console logger
|
2015-01-12 02:03:45 +01:00
|
|
|
console_log = logging.StreamHandler()
|
2015-01-17 18:50:56 +01:00
|
|
|
if config.action == "main": # Add time if main action
|
|
|
|
console_log.setFormatter(logging.Formatter('[%(asctime)s] %(name)s %(message)s', "%H:%M:%S"))
|
|
|
|
else:
|
|
|
|
console_log.setFormatter(logging.Formatter('%(name)s %(message)s', "%H:%M:%S"))
|
|
|
|
|
|
|
|
|
2015-01-12 02:03:45 +01:00
|
|
|
logging.getLogger('').addHandler(console_log) # Add console logger
|
|
|
|
logging.getLogger('').name = "-" # Remove root prefix
|
|
|
|
|
|
|
|
# Debug dependent configuration
|
version 0.2.0, new lib for bitcoin ecc, dont display or track notify errors, dont reload again within 1 sec, null peer ip fix, signingmoved to ContentManager, content.json include support, content.json multisig ready, content.json proper bitcoincore compatible signing, content.json include permissions, multithreaded publish, publish timeout 60s, no exception on invalid bitcoin address, testcase for new lib, bip32 based persite privatekey generation, multiuser ready, simple json database query command, websocket api fileGet, wrapper loading title stuck bugfix
2015-02-09 02:09:02 +01:00
|
|
|
from Debug import DebugHook
|
2015-01-12 02:03:45 +01:00
|
|
|
if config.debug:
|
|
|
|
console_log.setLevel(logging.DEBUG)
|
|
|
|
from gevent import monkey; monkey.patch_all(thread=False) # thread=False because of pyfilesystem
|
|
|
|
else:
|
|
|
|
console_log.setLevel(logging.INFO)
|
|
|
|
from gevent import monkey; monkey.patch_all()
|
|
|
|
|
|
|
|
import gevent
|
|
|
|
import time
|
|
|
|
|
|
|
|
logging.debug("Starting... %s" % config)
|
|
|
|
|
2015-01-12 19:11:35 +01:00
|
|
|
# Starts here when running zeronet.py
|
|
|
|
def start():
|
|
|
|
action_func = globals()[config.action] # Function reference
|
|
|
|
action_kwargs = config.getActionArguments() # non-config arguments when calling zeronet.py
|
|
|
|
|
|
|
|
action_func(**action_kwargs)
|
|
|
|
|
2015-01-12 02:03:45 +01:00
|
|
|
|
|
|
|
# Start serving UiServer and PeerServer
|
|
|
|
def main():
|
2015-02-20 01:37:12 +01:00
|
|
|
global ui_server, file_server
|
2015-01-12 02:03:45 +01:00
|
|
|
from File import FileServer
|
|
|
|
from Ui import UiServer
|
|
|
|
logging.info("Creating UiServer....")
|
|
|
|
ui_server = UiServer()
|
|
|
|
|
|
|
|
logging.info("Creating FileServer....")
|
|
|
|
file_server = FileServer()
|
|
|
|
|
|
|
|
logging.info("Starting servers....")
|
|
|
|
gevent.joinall([gevent.spawn(ui_server.start), gevent.spawn(file_server.start)])
|
|
|
|
|
|
|
|
|
|
|
|
# Site commands
|
|
|
|
|
|
|
|
def siteCreate():
|
|
|
|
logging.info("Generating new privatekey...")
|
|
|
|
from src.Crypt import CryptBitcoin
|
|
|
|
privatekey = CryptBitcoin.newPrivatekey()
|
2015-01-20 02:47:00 +01:00
|
|
|
logging.info("----------------------------------------------------------------------")
|
|
|
|
logging.info("Site private key: %s" % privatekey)
|
|
|
|
logging.info(" !!! ^ Save it now, required to modify the site ^ !!!")
|
2015-01-12 02:03:45 +01:00
|
|
|
address = CryptBitcoin.privatekeyToAddress(privatekey)
|
2015-01-20 02:47:00 +01:00
|
|
|
logging.info("Site address: %s" % address)
|
|
|
|
logging.info("----------------------------------------------------------------------")
|
|
|
|
|
|
|
|
while True:
|
|
|
|
if raw_input("? Have you secured your private key? (yes, no) > ").lower() == "yes": break
|
|
|
|
else: logging.info("Please, secure it now, you going to need it to modify your site!")
|
2015-01-12 02:03:45 +01:00
|
|
|
|
|
|
|
logging.info("Creating directory structure...")
|
|
|
|
from Site import Site
|
|
|
|
os.mkdir("data/%s" % address)
|
|
|
|
open("data/%s/index.html" % address, "w").write("Hello %s!" % address)
|
|
|
|
|
|
|
|
logging.info("Creating content.json...")
|
|
|
|
site = Site(address)
|
version 0.2.0, new lib for bitcoin ecc, dont display or track notify errors, dont reload again within 1 sec, null peer ip fix, signingmoved to ContentManager, content.json include support, content.json multisig ready, content.json proper bitcoincore compatible signing, content.json include permissions, multithreaded publish, publish timeout 60s, no exception on invalid bitcoin address, testcase for new lib, bip32 based persite privatekey generation, multiuser ready, simple json database query command, websocket api fileGet, wrapper loading title stuck bugfix
2015-02-09 02:09:02 +01:00
|
|
|
site.content_manager.sign(privatekey=privatekey)
|
2015-01-14 02:41:13 +01:00
|
|
|
site.settings["own"] = True
|
|
|
|
site.saveSettings()
|
2015-01-12 02:03:45 +01:00
|
|
|
|
|
|
|
logging.info("Site created!")
|
|
|
|
|
|
|
|
|
version 0.2.0, new lib for bitcoin ecc, dont display or track notify errors, dont reload again within 1 sec, null peer ip fix, signingmoved to ContentManager, content.json include support, content.json multisig ready, content.json proper bitcoincore compatible signing, content.json include permissions, multithreaded publish, publish timeout 60s, no exception on invalid bitcoin address, testcase for new lib, bip32 based persite privatekey generation, multiuser ready, simple json database query command, websocket api fileGet, wrapper loading title stuck bugfix
2015-02-09 02:09:02 +01:00
|
|
|
def siteSign(address, privatekey=None, inner_path="content.json"):
|
2015-01-12 02:03:45 +01:00
|
|
|
from Site import Site
|
|
|
|
logging.info("Signing site: %s..." % address)
|
|
|
|
site = Site(address, allow_create = False)
|
|
|
|
|
|
|
|
if not privatekey: # If no privatekey in args then ask it now
|
|
|
|
import getpass
|
|
|
|
privatekey = getpass.getpass("Private key (input hidden):")
|
version 0.2.0, new lib for bitcoin ecc, dont display or track notify errors, dont reload again within 1 sec, null peer ip fix, signingmoved to ContentManager, content.json include support, content.json multisig ready, content.json proper bitcoincore compatible signing, content.json include permissions, multithreaded publish, publish timeout 60s, no exception on invalid bitcoin address, testcase for new lib, bip32 based persite privatekey generation, multiuser ready, simple json database query command, websocket api fileGet, wrapper loading title stuck bugfix
2015-02-09 02:09:02 +01:00
|
|
|
site.content_manager.sign(inner_path=inner_path, privatekey=privatekey)
|
2015-01-12 02:03:45 +01:00
|
|
|
|
|
|
|
|
|
|
|
def siteVerify(address):
|
|
|
|
from Site import Site
|
|
|
|
logging.info("Verifing site: %s..." % address)
|
|
|
|
site = Site(address)
|
|
|
|
|
version 0.2.0, new lib for bitcoin ecc, dont display or track notify errors, dont reload again within 1 sec, null peer ip fix, signingmoved to ContentManager, content.json include support, content.json multisig ready, content.json proper bitcoincore compatible signing, content.json include permissions, multithreaded publish, publish timeout 60s, no exception on invalid bitcoin address, testcase for new lib, bip32 based persite privatekey generation, multiuser ready, simple json database query command, websocket api fileGet, wrapper loading title stuck bugfix
2015-02-09 02:09:02 +01:00
|
|
|
for content_inner_path in site.content_manager.contents:
|
|
|
|
logging.info("Verifing %s signature..." % content_inner_path)
|
|
|
|
if site.content_manager.verifyFile(content_inner_path, open(site.getPath(content_inner_path), "rb"), ignore_same=False) == True:
|
|
|
|
logging.info("[OK] %s signed by address %s!" % (content_inner_path, address))
|
|
|
|
else:
|
|
|
|
logging.error("[ERROR] %s not signed by address %s!" % (content_inner_path, address))
|
2015-01-12 02:03:45 +01:00
|
|
|
|
|
|
|
logging.info("Verifying site files...")
|
|
|
|
bad_files = site.verifyFiles()
|
|
|
|
if not bad_files:
|
2015-01-18 22:52:19 +01:00
|
|
|
logging.info("[OK] All file sha512sum matches!")
|
2015-01-12 02:03:45 +01:00
|
|
|
else:
|
|
|
|
logging.error("[ERROR] Error during verifying site files!")
|
|
|
|
|
|
|
|
|
|
|
|
def siteAnnounce(address):
|
|
|
|
from Site.Site import Site
|
|
|
|
logging.info("Announcing site %s to tracker..." % address)
|
|
|
|
site = Site(address)
|
|
|
|
|
|
|
|
s = time.time()
|
|
|
|
site.announce()
|
|
|
|
print "Response time: %.3fs" % (time.time()-s)
|
|
|
|
print site.peers
|
|
|
|
|
|
|
|
|
|
|
|
def siteNeedFile(address, inner_path):
|
|
|
|
from Site import Site
|
|
|
|
site = Site(address)
|
|
|
|
site.announce()
|
|
|
|
print site.needFile(inner_path, update=True)
|
|
|
|
|
|
|
|
|
version 0.2.0, new lib for bitcoin ecc, dont display or track notify errors, dont reload again within 1 sec, null peer ip fix, signingmoved to ContentManager, content.json include support, content.json multisig ready, content.json proper bitcoincore compatible signing, content.json include permissions, multithreaded publish, publish timeout 60s, no exception on invalid bitcoin address, testcase for new lib, bip32 based persite privatekey generation, multiuser ready, simple json database query command, websocket api fileGet, wrapper loading title stuck bugfix
2015-02-09 02:09:02 +01:00
|
|
|
def sitePublish(address, peer_ip=None, peer_port=15441, inner_path="content.json"):
|
version 0.2.4, peerPing and peerGetFile commands, old content update bugfix, new network code and protocol, connection share between sites, connection reuse, dont retry bad file more than 3 times in 20 min, multi threaded include file download, shuffle peers before publish, simple internal stats page, dont retry on failed peers, more than 10 peers publish bugfix
2015-02-23 23:33:31 +01:00
|
|
|
global file_server
|
2015-01-12 02:03:45 +01:00
|
|
|
from Site import Site
|
|
|
|
from File import FileServer # We need fileserver to handle incoming file requests
|
version 0.2.4, peerPing and peerGetFile commands, old content update bugfix, new network code and protocol, connection share between sites, connection reuse, dont retry bad file more than 3 times in 20 min, multi threaded include file download, shuffle peers before publish, simple internal stats page, dont retry on failed peers, more than 10 peers publish bugfix
2015-02-23 23:33:31 +01:00
|
|
|
|
2015-01-12 02:03:45 +01:00
|
|
|
logging.info("Creating FileServer....")
|
|
|
|
file_server = FileServer()
|
|
|
|
file_server_thread = gevent.spawn(file_server.start, check_sites=False) # Dont check every site integrity
|
|
|
|
file_server.openport()
|
|
|
|
if file_server.port_opened == False:
|
|
|
|
logging.info("Port not opened, passive publishing not supported yet :(")
|
|
|
|
return
|
|
|
|
site = file_server.sites[address]
|
|
|
|
site.settings["serving"] = True # Serving the site even if its disabled
|
2015-01-16 11:52:42 +01:00
|
|
|
if peer_ip: # Announce ip specificed
|
|
|
|
site.addPeer(peer_ip, peer_port)
|
|
|
|
else: # Just ask the tracker
|
|
|
|
logging.info("Gathering peers from tracker")
|
|
|
|
site.announce() # Gather peers
|
version 0.2.0, new lib for bitcoin ecc, dont display or track notify errors, dont reload again within 1 sec, null peer ip fix, signingmoved to ContentManager, content.json include support, content.json multisig ready, content.json proper bitcoincore compatible signing, content.json include permissions, multithreaded publish, publish timeout 60s, no exception on invalid bitcoin address, testcase for new lib, bip32 based persite privatekey generation, multiuser ready, simple json database query command, websocket api fileGet, wrapper loading title stuck bugfix
2015-02-09 02:09:02 +01:00
|
|
|
site.publish(20, inner_path) # Push to 20 peers
|
2015-01-12 02:03:45 +01:00
|
|
|
logging.info("Serving files....")
|
|
|
|
gevent.joinall([file_server_thread])
|
|
|
|
|
|
|
|
|
|
|
|
# Crypto commands
|
|
|
|
|
|
|
|
def cryptoPrivatekeyToAddress(privatekey=None):
|
|
|
|
from src.Crypt import CryptBitcoin
|
|
|
|
if not privatekey: # If no privatekey in args then ask it now
|
|
|
|
import getpass
|
|
|
|
privatekey = getpass.getpass("Private key (input hidden):")
|
|
|
|
|
|
|
|
print CryptBitcoin.privatekeyToAddress(privatekey)
|
|
|
|
|
|
|
|
|
|
|
|
# Peer
|
|
|
|
|
version 0.2.4, peerPing and peerGetFile commands, old content update bugfix, new network code and protocol, connection share between sites, connection reuse, dont retry bad file more than 3 times in 20 min, multi threaded include file download, shuffle peers before publish, simple internal stats page, dont retry on failed peers, more than 10 peers publish bugfix
2015-02-23 23:33:31 +01:00
|
|
|
def peerPing(peer_ip, peer_port):
|
|
|
|
logging.info("Opening a simple connection server")
|
|
|
|
global file_server
|
|
|
|
from Connection import ConnectionServer
|
|
|
|
file_server = ConnectionServer("127.0.0.1", 1234)
|
|
|
|
|
2015-01-12 02:03:45 +01:00
|
|
|
from Peer import Peer
|
version 0.2.4, peerPing and peerGetFile commands, old content update bugfix, new network code and protocol, connection share between sites, connection reuse, dont retry bad file more than 3 times in 20 min, multi threaded include file download, shuffle peers before publish, simple internal stats page, dont retry on failed peers, more than 10 peers publish bugfix
2015-02-23 23:33:31 +01:00
|
|
|
logging.info("Pinging 5 times peer: %s:%s..." % (peer_ip, peer_port))
|
|
|
|
peer = Peer(peer_ip, peer_port)
|
2015-01-12 02:03:45 +01:00
|
|
|
for i in range(5):
|
|
|
|
s = time.time()
|
|
|
|
print peer.ping(),
|
|
|
|
print "Response time: %.3fs" % (time.time()-s)
|
|
|
|
time.sleep(1)
|
|
|
|
|
|
|
|
|
version 0.2.4, peerPing and peerGetFile commands, old content update bugfix, new network code and protocol, connection share between sites, connection reuse, dont retry bad file more than 3 times in 20 min, multi threaded include file download, shuffle peers before publish, simple internal stats page, dont retry on failed peers, more than 10 peers publish bugfix
2015-02-23 23:33:31 +01:00
|
|
|
def peerGetFile(peer_ip, peer_port, site, filename):
|
|
|
|
logging.info("Opening a simple connection server")
|
|
|
|
global file_server
|
|
|
|
from Connection import ConnectionServer
|
|
|
|
file_server = ConnectionServer()
|
|
|
|
|
2015-01-12 02:03:45 +01:00
|
|
|
from Peer import Peer
|
version 0.2.4, peerPing and peerGetFile commands, old content update bugfix, new network code and protocol, connection share between sites, connection reuse, dont retry bad file more than 3 times in 20 min, multi threaded include file download, shuffle peers before publish, simple internal stats page, dont retry on failed peers, more than 10 peers publish bugfix
2015-02-23 23:33:31 +01:00
|
|
|
logging.info("Getting %s/%s from peer: %s:%s..." % (site, filename, peer_ip, peer_port))
|
|
|
|
peer = Peer(peer_ip, peer_port)
|
2015-01-12 02:03:45 +01:00
|
|
|
s = time.time()
|
|
|
|
print peer.getFile(site, filename).read()
|
|
|
|
print "Response time: %.3fs" % (time.time()-s)
|
|
|
|
|