2015-01-12 02:03:45 +01:00
import os , sys
version 0.2.7, plugin system, multiuser plugin for zeroproxies, reworked imports, cookie parse, stats moved to plugin, usermanager class, dont generate site auth on listing, multiline notifications, allow server side prompt from user, update script keep plugins disabled status
2015-03-24 01:33:09 +01:00
update_after_shutdown = False # If set True then update and restart zeronet after main loop ended
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
version 0.2.7, plugin system, multiuser plugin for zeroproxies, reworked imports, cookie parse, stats moved to plugin, usermanager class, dont generate site auth on listing, multiline notifications, allow server side prompt from user, update script keep plugins disabled status
2015-03-24 01:33:09 +01:00
# Setup logging
2015-01-12 02:03:45 +01:00
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
version 0.2.7, plugin system, multiuser plugin for zeroproxies, reworked imports, cookie parse, stats moved to plugin, usermanager class, dont generate site auth on listing, multiline notifications, allow server side prompt from user, update script keep plugins disabled status
2015-03-24 01:33:09 +01:00
2015-01-12 02:03:45 +01:00
# 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 :
version 0.2.7, plugin system, multiuser plugin for zeroproxies, reworked imports, cookie parse, stats moved to plugin, usermanager class, dont generate site auth on listing, multiline notifications, allow server side prompt from user, update script keep plugins disabled status
2015-03-24 01:33:09 +01:00
console_log . setLevel ( logging . DEBUG ) # Display everything to console
2015-01-12 02:03:45 +01:00
else :
version 0.2.7, plugin system, multiuser plugin for zeroproxies, reworked imports, cookie parse, stats moved to plugin, usermanager class, dont generate site auth on listing, multiline notifications, allow server side prompt from user, update script keep plugins disabled status
2015-03-24 01:33:09 +01:00
console_log . setLevel ( logging . INFO ) # Display only important info to console
2015-04-18 11:18:37 +02:00
from gevent import monkey ; monkey . patch_all ( thread = False , ssl = False ) # Make time, socket gevent compatible. Not thread: pyfilesystem and system tray icon not compatible, Not ssl: broken in 2.7.9
2015-01-12 02:03:45 +01:00
import gevent
import time
version 0.2.7, plugin system, multiuser plugin for zeroproxies, reworked imports, cookie parse, stats moved to plugin, usermanager class, dont generate site auth on listing, multiline notifications, allow server side prompt from user, update script keep plugins disabled status
2015-03-24 01:33:09 +01:00
# Log current config
2015-03-19 21:19:14 +01:00
logging . debug ( " Config: %s " % config )
2015-01-12 02:03:45 +01:00
version 0.2.7, plugin system, multiuser plugin for zeroproxies, reworked imports, cookie parse, stats moved to plugin, usermanager class, dont generate site auth on listing, multiline notifications, allow server side prompt from user, update script keep plugins disabled status
2015-03-24 01:33:09 +01:00
2015-04-12 23:59:22 +02:00
# Socks Proxy monkey patch
if config . proxy :
from util import SocksProxy
import urllib2
logging . info ( " Patching sockets to socks proxy: %s " % config . proxy )
config . fileserver_ip = ' 127.0.0.1 ' # Do not accept connections anywhere but localhost
SocksProxy . monkeyPath ( * config . proxy . split ( " : " ) )
version 0.2.7, plugin system, multiuser plugin for zeroproxies, reworked imports, cookie parse, stats moved to plugin, usermanager class, dont generate site auth on listing, multiline notifications, allow server side prompt from user, update script keep plugins disabled status
2015-03-24 01:33:09 +01:00
# Load plugins
from Plugin import PluginManager
PluginManager . plugin_manager . loadPlugins ( )
# -- Actions --
2015-04-15 02:54:10 +02:00
@PluginManager.acceptPlugins
class Actions :
# Default action: Start serving UiServer and FileServer
def main ( self ) :
2015-04-17 23:12:22 +02:00
logging . info ( " Version: %s r %s , Python %s , Gevent: %s " % ( config . version , config . rev , sys . version , gevent . __version__ ) )
2015-04-15 02:54:10 +02:00
global ui_server , file_server
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 ( self ) :
logging . info ( " Generating new privatekey... " )
from Crypt import CryptBitcoin
privatekey = CryptBitcoin . newPrivatekey ( )
logging . info ( " ---------------------------------------------------------------------- " )
logging . info ( " Site private key: %s " % privatekey )
logging . info ( " !!! ^ Save it now, required to modify the site ^ !!! " )
address = CryptBitcoin . privatekeyToAddress ( privatekey )
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! " )
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 )
site . content_manager . sign ( privatekey = privatekey )
site . settings [ " own " ] = True
site . saveSettings ( )
logging . info ( " Site created! " )
version 0.3.0, rev187, Trusted authorization sites support, --publish option on signing, cryptSign command line option, OpenSSL enabled on OSX, Crypto verify allows list of valid addresses, Option for version 2 json DB tables, DbCursor SELECT parameters bugfix, Add peer to site on ListModified, Download blind includes when new site added, Publish command better messages, Multi-threaded announce, New http Torrent trackers, Wait for dbschema.json on query, Handle json import errors, More compact writeJson storage command, Testcase for signing and verifying, Workaround to make non target=_top links work, More clean UiWebsocket command route, Send cert_user_id on siteinfo, Notify other local clients on local file modify, Option to wait for file download before sql query, File rules websocket API command, Cert add and select, set websocket API command, Put focus on innerframe, innerloaded wrapper api command to add hashtag, Allow more file error on big sites, Keep worker running after stuked on done task, New more stable openSSL layer that works on OSX, Noparallel parameter bugfix, RateLimit allowed again interval bugfix, Updater skips non-writeable files, Try to close openssl dll before update
2015-05-25 01:26:33 +02:00
def siteSign ( self , address , privatekey = None , inner_path = " content.json " , publish = False ) :
2015-04-15 02:54:10 +02: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.3.0, rev187, Trusted authorization sites support, --publish option on signing, cryptSign command line option, OpenSSL enabled on OSX, Crypto verify allows list of valid addresses, Option for version 2 json DB tables, DbCursor SELECT parameters bugfix, Add peer to site on ListModified, Download blind includes when new site added, Publish command better messages, Multi-threaded announce, New http Torrent trackers, Wait for dbschema.json on query, Handle json import errors, More compact writeJson storage command, Testcase for signing and verifying, Workaround to make non target=_top links work, More clean UiWebsocket command route, Send cert_user_id on siteinfo, Notify other local clients on local file modify, Option to wait for file download before sql query, File rules websocket API command, Cert add and select, set websocket API command, Put focus on innerframe, innerloaded wrapper api command to add hashtag, Allow more file error on big sites, Keep worker running after stuked on done task, New more stable openSSL layer that works on OSX, Noparallel parameter bugfix, RateLimit allowed again interval bugfix, Updater skips non-writeable files, Try to close openssl dll before update
2015-05-25 01:26:33 +02:00
succ = site . content_manager . sign ( inner_path = inner_path , privatekey = privatekey , update_changed_files = True )
if succ and publish :
self . sitePublish ( address , inner_path = inner_path )
2015-04-15 02:54:10 +02:00
def siteVerify ( self , address ) :
2015-04-28 00:43:17 +02:00
import time
2015-04-15 02:54:10 +02:00
from Site import Site
2015-04-28 00:43:17 +02:00
s = time . time ( )
2015-04-15 02:54:10 +02:00
logging . info ( " Verifing site: %s ... " % address )
site = Site ( address )
version 0.3.0, rev187, Trusted authorization sites support, --publish option on signing, cryptSign command line option, OpenSSL enabled on OSX, Crypto verify allows list of valid addresses, Option for version 2 json DB tables, DbCursor SELECT parameters bugfix, Add peer to site on ListModified, Download blind includes when new site added, Publish command better messages, Multi-threaded announce, New http Torrent trackers, Wait for dbschema.json on query, Handle json import errors, More compact writeJson storage command, Testcase for signing and verifying, Workaround to make non target=_top links work, More clean UiWebsocket command route, Send cert_user_id on siteinfo, Notify other local clients on local file modify, Option to wait for file download before sql query, File rules websocket API command, Cert add and select, set websocket API command, Put focus on innerframe, innerloaded wrapper api command to add hashtag, Allow more file error on big sites, Keep worker running after stuked on done task, New more stable openSSL layer that works on OSX, Noparallel parameter bugfix, RateLimit allowed again interval bugfix, Updater skips non-writeable files, Try to close openssl dll before update
2015-05-25 01:26:33 +02:00
bad_files = [ ]
2015-04-15 02:54:10 +02: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 , site . storage . open ( content_inner_path , " rb " ) , ignore_same = False ) == True :
logging . info ( " [OK] %s signed by address %s ! " % ( content_inner_path , address ) )
else :
version 0.3.0, rev187, Trusted authorization sites support, --publish option on signing, cryptSign command line option, OpenSSL enabled on OSX, Crypto verify allows list of valid addresses, Option for version 2 json DB tables, DbCursor SELECT parameters bugfix, Add peer to site on ListModified, Download blind includes when new site added, Publish command better messages, Multi-threaded announce, New http Torrent trackers, Wait for dbschema.json on query, Handle json import errors, More compact writeJson storage command, Testcase for signing and verifying, Workaround to make non target=_top links work, More clean UiWebsocket command route, Send cert_user_id on siteinfo, Notify other local clients on local file modify, Option to wait for file download before sql query, File rules websocket API command, Cert add and select, set websocket API command, Put focus on innerframe, innerloaded wrapper api command to add hashtag, Allow more file error on big sites, Keep worker running after stuked on done task, New more stable openSSL layer that works on OSX, Noparallel parameter bugfix, RateLimit allowed again interval bugfix, Updater skips non-writeable files, Try to close openssl dll before update
2015-05-25 01:26:33 +02:00
logging . error ( " [ERROR] %s : invalid file! " % content_inner_path )
bad_files + = content_inner_path
2015-04-15 02:54:10 +02:00
logging . info ( " Verifying site files... " )
version 0.3.0, rev187, Trusted authorization sites support, --publish option on signing, cryptSign command line option, OpenSSL enabled on OSX, Crypto verify allows list of valid addresses, Option for version 2 json DB tables, DbCursor SELECT parameters bugfix, Add peer to site on ListModified, Download blind includes when new site added, Publish command better messages, Multi-threaded announce, New http Torrent trackers, Wait for dbschema.json on query, Handle json import errors, More compact writeJson storage command, Testcase for signing and verifying, Workaround to make non target=_top links work, More clean UiWebsocket command route, Send cert_user_id on siteinfo, Notify other local clients on local file modify, Option to wait for file download before sql query, File rules websocket API command, Cert add and select, set websocket API command, Put focus on innerframe, innerloaded wrapper api command to add hashtag, Allow more file error on big sites, Keep worker running after stuked on done task, New more stable openSSL layer that works on OSX, Noparallel parameter bugfix, RateLimit allowed again interval bugfix, Updater skips non-writeable files, Try to close openssl dll before update
2015-05-25 01:26:33 +02:00
bad_files + = site . storage . verifyFiles ( )
2015-04-15 02:54:10 +02:00
if not bad_files :
2015-04-28 00:43:17 +02:00
logging . info ( " [OK] All file sha512sum matches! ( %.3f s) " % ( time . time ( ) - s ) )
2015-04-15 02:54:10 +02:00
else :
logging . error ( " [ERROR] Error during verifying site files! " )
2015-01-12 02:03:45 +01:00
2015-04-15 02:54:10 +02:00
def dbRebuild ( self , address ) :
from Site import Site
logging . info ( " Rebuilding site sql cache: %s ... " % address )
site = Site ( address )
s = time . time ( )
site . storage . rebuildDb ( )
logging . info ( " Done in %.3f s " % ( time . time ( ) - s ) )
2015-01-12 02:03:45 +01:00
2015-04-15 02:54:10 +02:00
def dbQuery ( self , address , query ) :
from Site import Site
import json
site = Site ( address )
result = [ ]
for row in site . storage . query ( query ) :
result . append ( dict ( row ) )
print json . dumps ( result , indent = 4 )
2015-01-12 02:03:45 +01:00
2015-04-15 02:54:10 +02:00
def siteAnnounce ( self , address ) :
from Site . Site import Site
logging . info ( " Announcing site %s to tracker... " % address )
site = Site ( address )
2015-01-12 02:03:45 +01:00
s = time . time ( )
2015-04-15 02:54:10 +02:00
site . announce ( )
print " Response time: %.3f s " % ( time . time ( ) - s )
print site . peers
def siteNeedFile ( self , address , inner_path ) :
from Site import Site
site = Site ( address )
site . announce ( )
print site . needFile ( inner_path , update = True )
def sitePublish ( self , address , peer_ip = None , peer_port = 15441 , inner_path = " content.json " ) :
global file_server
from Site import Site
from File import FileServer # We need fileserver to handle incoming file requests
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 ( )
site = file_server . sites [ address ]
site . settings [ " serving " ] = True # Serving the site even if its disabled
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.3.0, rev187, Trusted authorization sites support, --publish option on signing, cryptSign command line option, OpenSSL enabled on OSX, Crypto verify allows list of valid addresses, Option for version 2 json DB tables, DbCursor SELECT parameters bugfix, Add peer to site on ListModified, Download blind includes when new site added, Publish command better messages, Multi-threaded announce, New http Torrent trackers, Wait for dbschema.json on query, Handle json import errors, More compact writeJson storage command, Testcase for signing and verifying, Workaround to make non target=_top links work, More clean UiWebsocket command route, Send cert_user_id on siteinfo, Notify other local clients on local file modify, Option to wait for file download before sql query, File rules websocket API command, Cert add and select, set websocket API command, Put focus on innerframe, innerloaded wrapper api command to add hashtag, Allow more file error on big sites, Keep worker running after stuked on done task, New more stable openSSL layer that works on OSX, Noparallel parameter bugfix, RateLimit allowed again interval bugfix, Updater skips non-writeable files, Try to close openssl dll before update
2015-05-25 01:26:33 +02:00
published = site . publish ( 20 , inner_path ) # Push to 20 peers
if published > 0 :
time . sleep ( 3 )
logging . info ( " Serving files (max 60s)... " )
gevent . joinall ( [ file_server_thread ] , timeout = 60 )
logging . info ( " Done. " )
else :
logging . info ( " No peers found for this site, sitePublish command only works if you already have peers serving your site " )
2015-04-15 02:54:10 +02:00
# Crypto commands
version 0.3.0, rev187, Trusted authorization sites support, --publish option on signing, cryptSign command line option, OpenSSL enabled on OSX, Crypto verify allows list of valid addresses, Option for version 2 json DB tables, DbCursor SELECT parameters bugfix, Add peer to site on ListModified, Download blind includes when new site added, Publish command better messages, Multi-threaded announce, New http Torrent trackers, Wait for dbschema.json on query, Handle json import errors, More compact writeJson storage command, Testcase for signing and verifying, Workaround to make non target=_top links work, More clean UiWebsocket command route, Send cert_user_id on siteinfo, Notify other local clients on local file modify, Option to wait for file download before sql query, File rules websocket API command, Cert add and select, set websocket API command, Put focus on innerframe, innerloaded wrapper api command to add hashtag, Allow more file error on big sites, Keep worker running after stuked on done task, New more stable openSSL layer that works on OSX, Noparallel parameter bugfix, RateLimit allowed again interval bugfix, Updater skips non-writeable files, Try to close openssl dll before update
2015-05-25 01:26:33 +02:00
def cryptPrivatekeyToAddress ( self , privatekey = None ) :
2015-04-15 02:54:10 +02:00
from 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 )
version 0.3.0, rev187, Trusted authorization sites support, --publish option on signing, cryptSign command line option, OpenSSL enabled on OSX, Crypto verify allows list of valid addresses, Option for version 2 json DB tables, DbCursor SELECT parameters bugfix, Add peer to site on ListModified, Download blind includes when new site added, Publish command better messages, Multi-threaded announce, New http Torrent trackers, Wait for dbschema.json on query, Handle json import errors, More compact writeJson storage command, Testcase for signing and verifying, Workaround to make non target=_top links work, More clean UiWebsocket command route, Send cert_user_id on siteinfo, Notify other local clients on local file modify, Option to wait for file download before sql query, File rules websocket API command, Cert add and select, set websocket API command, Put focus on innerframe, innerloaded wrapper api command to add hashtag, Allow more file error on big sites, Keep worker running after stuked on done task, New more stable openSSL layer that works on OSX, Noparallel parameter bugfix, RateLimit allowed again interval bugfix, Updater skips non-writeable files, Try to close openssl dll before update
2015-05-25 01:26:33 +02:00
def cryptSign ( self , message , privatekey ) :
from Crypt import CryptBitcoin
print CryptBitcoin . sign ( message , privatekey )
2015-04-15 02:54:10 +02:00
# Peer
def peerPing ( self , 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 )
from Peer import Peer
logging . info ( " Pinging 5 times peer: %s : %s ... " % ( peer_ip , int ( peer_port ) ) )
peer = Peer ( peer_ip , peer_port )
for i in range ( 5 ) :
s = time . time ( )
print peer . ping ( ) ,
print " Response time: %.3f s " % ( time . time ( ) - s )
time . sleep ( 1 )
def peerGetFile ( self , peer_ip , peer_port , site , filename ) :
logging . info ( " Opening a simple connection server " )
global file_server
from Connection import ConnectionServer
file_server = ConnectionServer ( )
from Peer import Peer
logging . info ( " Getting %s / %s from peer: %s : %s ... " % ( site , filename , peer_ip , peer_port ) )
peer = Peer ( peer_ip , peer_port )
s = time . time ( )
print peer . getFile ( site , filename ) . read ( )
2015-01-12 02:03:45 +01:00
print " Response time: %.3f s " % ( time . time ( ) - s )
rev125, Class statistics, OpenSSL disabled on OSX by default because of possible segfault, --disable_openssl command line parameter, Save memory on Connection, Peer and FileRequest objects using slots, Dont store modification time from the far future, Able to query modified files from peer, Allow reannounce in 30secs, Use with command in SiteStorage, Always create dir before write file, PeerCmd shell command to query specific command from peer
2015-04-29 23:12:45 +02:00
def peerCmd ( self , peer_ip , peer_port , cmd , parameters ) :
logging . info ( " Opening a simple connection server " )
global file_server
from Connection import ConnectionServer
file_server = ConnectionServer ( )
from Peer import Peer
peer = Peer ( peer_ip , peer_port )
import json
if parameters :
parameters = json . loads ( parameters . replace ( " ' " , ' " ' ) )
else :
parameters = { }
logging . info ( " Response: %s " % peer . request ( cmd , parameters ) )
2015-04-15 02:54:10 +02:00
actions = Actions ( )
# Starts here when running zeronet.py
def start ( ) :
# Call function
func = getattr ( actions , config . action , None )
action_kwargs = config . getActionArguments ( )
func ( * * action_kwargs )