2019-04-20 20:23:59 +02:00
import logging , json , os , re , sys , time , socket
2019-04-14 16:57:37 +02:00
from Plugin import PluginManager
from Config import config
from Debug import Debug
2019-04-20 20:23:59 +02:00
from http . client import HTTPSConnection , HTTPConnection , HTTPException
2019-04-16 16:23:09 +02:00
from base64 import b64encode
2021-08-19 20:19:47 +02:00
from pathlib import Path
from . NamecoinUtils import is_namecoin_installed , is_namecoin_running , get_namecoin_conf , check_namecoin_rpc_conf , start_namecoin , kill_namecoin
2019-04-14 16:57:37 +02:00
allow_reload = False # No reload supported
@PluginManager.registerTo ( " SiteManager " )
class SiteManagerPlugin ( object ) :
2021-08-19 20:19:47 +02:00
def __del__ ( self ) :
if self . namecoin_pid :
kill_namecoin ( self . namecoin_pid )
self . log . debug ( " Kill namecoin pid : {} " . format ( self . namecoin_pid ) )
return
2019-04-14 16:57:37 +02:00
def load ( self , * args , * * kwargs ) :
super ( SiteManagerPlugin , self ) . load ( * args , * * kwargs )
2021-08-19 20:19:47 +02:00
self . log = logging . getLogger ( " ZeronameLocal Plugin " )
2019-04-20 20:23:59 +02:00
self . error_message = None
2021-08-19 20:19:47 +02:00
self . namecoin_pid = None
self . config = dict ( {
' rpcconnect ' : config . namecoin_host ,
' rpcport ' : config . namecoin_rpcport ,
' rpcuser ' : config . namecoin_rpcuser ,
' rpcpassword ' : config . namecoin_rpcpassword ,
' path ' : config . namecoin_path
} )
self . log . debug ( " Namecoin config through CLI ? {} " . format ( self . config ) )
self . log . debug ( " Namecoin installed ? {} " . format ( is_namecoin_installed ( ) ) )
2021-08-21 11:39:27 +02:00
if sys . platform . startswith ( ' linux ' ) and is_namecoin_installed ( ) :
2021-08-19 20:19:47 +02:00
self . log . debug ( " Namecoin running ? {} " . format ( is_namecoin_running ( ) ) )
if is_namecoin_running ( ) is not None :
if check_namecoin_rpc_conf ( self . config ) is not True :
self . config = get_namecoin_conf ( )
if check_namecoin_rpc_conf ( self . config ) is not True :
self . error_message = " Missing parameters "
self . log . error ( " Missing parameters to connect to namecoin node. Please check all the arguments needed with ' --help ' or provide them in the namecoin.conf. Zeronet will continue working without it. " )
return
else :
if config . namecoin_path is not None :
self . namecoin_pid = start_namecoin ( self . config [ ' path ' ] )
self . log . debug ( " Namecoin starting ? {} " . format ( str ( self . namecoin_pid ) ) )
else :
self . log . error ( " Please use --namecoin_path to specify namecoind binary path " )
if check_namecoin_rpc_conf ( self . config ) is not True :
2019-04-20 20:23:59 +02:00
self . error_message = " Missing parameters "
2021-08-19 20:19:47 +02:00
self . log . error ( " Namecoin is not installed or parameters are missing to connect to namecoin node. Please check all the arguments needed with ' --help ' . Zeronet will continue working without it. " )
2019-04-20 20:23:59 +02:00
return
2021-08-19 20:19:47 +02:00
url = " %(host)s : %(port)s " % { " host " : self . config [ ' rpcconnect ' ] , " port " : self . config [ ' rpcport ' ] }
2019-04-20 20:23:59 +02:00
self . c = HTTPConnection ( url , timeout = 3 )
2021-08-19 20:19:47 +02:00
user_pass = " %(user)s : %(password)s " % { " user " : self . config [ ' rpcuser ' ] , " password " : self . config [ ' rpcpassword ' ] }
2019-04-16 16:23:09 +02:00
userAndPass = b64encode ( bytes ( user_pass , " utf-8 " ) ) . decode ( " ascii " )
self . headers = { " Authorization " : " Basic %s " % userAndPass , " Content-Type " : " application/json " }
2019-04-20 20:23:59 +02:00
payload = json . dumps ( {
" jsonrpc " : " 2.0 " ,
" id " : " zeronet " ,
" method " : " ping " ,
" params " : [ ]
} )
try :
self . c . request ( " POST " , " / " , payload , headers = self . headers )
response = self . c . getresponse ( )
data = response . read ( )
self . c . close ( )
if response . status == 200 :
result = json . loads ( data . decode ( ) ) [ " result " ]
else :
raise Exception ( response . reason )
except Exception as err :
self . log . error ( " The Namecoin node is unreachable. Please check the configuration value are correct. Zeronet will continue working without it. " )
self . error_message = err
2019-04-14 16:57:37 +02:00
self . cache = dict ( )
# Checks if it's a valid address
def isAddress ( self , address ) :
return self . isBitDomain ( address ) or super ( SiteManagerPlugin , self ) . isAddress ( address )
# Return: True if the address is domain
def isDomain ( self , address ) :
return self . isBitDomain ( address ) or super ( SiteManagerPlugin , self ) . isDomain ( address )
# Return: True if the address is .bit domain
def isBitDomain ( self , address ) :
return re . match ( r " (.*?)([A-Za-z0-9_-]+ \ .bit)$ " , address )
# Return: Site object or None if not found
def get ( self , address ) :
if self . isBitDomain ( address ) : # Its looks like a domain
address_resolved = self . resolveDomain ( address )
if address_resolved : # Domain found
site = self . sites . get ( address_resolved )
if site :
site_domain = site . settings . get ( " domain " )
if site_domain != address :
site . settings [ " domain " ] = address
else : # Domain not found
site = self . sites . get ( address )
else : # Access by site address
site = super ( SiteManagerPlugin , self ) . get ( address )
return site
# Return or create site and start download site files
# Return: Site or None if dns resolve failed
def need ( self , address , * args , * * kwargs ) :
if self . isBitDomain ( address ) : # Its looks like a domain
address_resolved = self . resolveDomain ( address )
if address_resolved :
address = address_resolved
else :
return None
return super ( SiteManagerPlugin , self ) . need ( address , * args , * * kwargs )
# Resolve domain
# Return: The address or None
def resolveDomain ( self , domain ) :
domain = domain . lower ( )
#remove .bit on end
if domain [ - 4 : ] == " .bit " :
domain = domain [ 0 : - 4 ]
domain_array = domain . split ( " . " )
2019-04-20 20:23:59 +02:00
if self . error_message :
self . log . error ( " Not able to connect to Namecoin node : {!s} " . format ( self . error_message ) )
return None
2019-04-14 16:57:37 +02:00
if len ( domain_array ) > 2 :
2019-04-20 20:23:59 +02:00
self . log . error ( " Too many subdomains! Can only handle one level (eg. staging.mixtape.bit) " )
2019-04-18 15:27:49 +02:00
return None
2019-04-14 16:57:37 +02:00
subdomain = " "
if len ( domain_array ) == 1 :
domain = domain_array [ 0 ]
else :
subdomain = domain_array [ 0 ]
domain = domain_array [ 1 ]
if domain in self . cache :
delta = time . time ( ) - self . cache [ domain ] [ " time " ]
if delta < 3600 :
# Must have been less than 1hour
return self . cache [ domain ] [ " addresses_resolved " ] [ subdomain ]
payload = json . dumps ( {
" jsonrpc " : " 2.0 " ,
" id " : " zeronet " ,
" method " : " name_show " ,
" params " : [ " d/ " + domain ]
} )
try :
2019-04-16 16:23:09 +02:00
self . c . request ( " POST " , " / " , payload , headers = self . headers )
response = self . c . getresponse ( )
data = response . read ( )
self . c . close ( )
domain_object = json . loads ( data . decode ( ) ) [ " result " ]
2019-04-14 16:57:37 +02:00
except Exception as err :
#domain doesn't exist
return None
if " zeronet " in domain_object [ " value " ] :
zeronet_domains = json . loads ( domain_object [ " value " ] ) [ " zeronet " ]
2019-04-14 22:41:26 +02:00
if isinstance ( zeronet_domains , str ) :
# {
# "zeronet":"19rXKeKptSdQ9qt7omwN82smehzTuuq6S9"
# } is valid
zeronet_domains = { " " : zeronet_domains }
2019-04-14 16:57:37 +02:00
self . cache [ domain ] = { " addresses_resolved " : zeronet_domains , " time " : time . time ( ) }
2019-04-14 22:41:26 +02:00
elif " map " in domain_object [ " value " ] :
# Namecoin standard use {"map": { "blog": {"zeronet": "1D..."} }}
data_map = json . loads ( domain_object [ " value " ] ) [ " map " ]
zeronet_domains = dict ( )
for subdomain in data_map :
if " zeronet " in data_map [ subdomain ] :
zeronet_domains [ subdomain ] = data_map [ subdomain ] [ " zeronet " ]
if " zeronet " in data_map and isinstance ( data_map [ " zeronet " ] , str ) :
# {"map":{
# "zeronet":"19rXKeKptSdQ9qt7omwN82smehzTuuq6S9",
# }}
zeronet_domains [ " " ] = data_map [ " zeronet " ]
2019-04-17 18:34:53 +02:00
self . cache [ domain ] = { " addresses_resolved " : zeronet_domains , " time " : time . time ( ) }
2019-04-14 22:41:26 +02:00
else :
# No Zeronet address registered
return None
2019-04-14 16:57:37 +02:00
2019-04-14 22:41:26 +02:00
return self . cache [ domain ] [ " addresses_resolved " ] [ subdomain ]
2019-04-14 16:57:37 +02:00
@PluginManager.registerTo ( " ConfigPlugin " )
class ConfigPlugin ( object ) :
def createArguments ( self ) :
group = self . parser . add_argument_group ( " Zeroname Local plugin " )
group . add_argument ( ' --namecoin_host ' , help = " Host to namecoin node (eg. 127.0.0.1) " )
group . add_argument ( ' --namecoin_rpcport ' , help = " Port to connect (eg. 8336) " )
group . add_argument ( ' --namecoin_rpcuser ' , help = " RPC user to connect to the namecoin node (eg. nofish) " )
group . add_argument ( ' --namecoin_rpcpassword ' , help = " RPC password to connect to namecoin node " )
2021-08-19 20:19:47 +02:00
group . add_argument ( ' --namecoin_path ' , help = " Path to namecoind binary " )
2019-04-14 16:57:37 +02:00
return super ( ConfigPlugin , self ) . createArguments ( )