Merge pull request #215 from caryoscelus/no-local-zeroname

No local zeroname

refs #23
This commit is contained in:
caryoscelus 2023-07-23 09:50:42 +00:00 committed by GitHub
commit 62f14371bd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 0 additions and 411 deletions

View file

@ -1,153 +0,0 @@
import logging, json, os, re, sys, time
import gevent
from Plugin import PluginManager
from Config import config
from util import Http
from Debug import Debug
allow_reload = False # No reload supported
log = logging.getLogger("DnschainPlugin")
@PluginManager.registerTo("SiteManager")
class SiteManagerPlugin(object):
dns_cache_path = "%s/dns_cache.json" % config.data_dir
dns_cache = None
# Checks if its a valid address
def isAddress(self, address):
if self.isDomain(address):
return True
else:
return super(SiteManagerPlugin, self).isAddress(address)
# Return: True if the address is domain
def isDomain(self, address):
return re.match(r"(.*?)([A-Za-z0-9_-]+\.[A-Za-z0-9]+)$", address)
# Load dns entries from data/dns_cache.json
def loadDnsCache(self):
if os.path.isfile(self.dns_cache_path):
self.dns_cache = json.load(open(self.dns_cache_path))
else:
self.dns_cache = {}
log.debug("Loaded dns cache, entries: %s" % len(self.dns_cache))
# Save dns entries to data/dns_cache.json
def saveDnsCache(self):
json.dump(self.dns_cache, open(self.dns_cache_path, "wb"), indent=2)
# Resolve domain using dnschain.net
# Return: The address or None
def resolveDomainDnschainNet(self, domain):
try:
match = self.isDomain(domain)
sub_domain = match.group(1).strip(".")
top_domain = match.group(2)
if not sub_domain: sub_domain = "@"
address = None
with gevent.Timeout(5, Exception("Timeout: 5s")):
res = Http.get("https://api.dnschain.net/v1/namecoin/key/%s" % top_domain).read()
data = json.loads(res)["data"]["value"]
if "zeronet" in data:
for key, val in data["zeronet"].items():
self.dns_cache[key+"."+top_domain] = [val, time.time()+60*60*5] # Cache for 5 hours
self.saveDnsCache()
return data["zeronet"].get(sub_domain)
# Not found
return address
except Exception as err:
log.debug("Dnschain.net %s resolve error: %s" % (domain, Debug.formatException(err)))
# Resolve domain using dnschain.info
# Return: The address or None
def resolveDomainDnschainInfo(self, domain):
try:
match = self.isDomain(domain)
sub_domain = match.group(1).strip(".")
top_domain = match.group(2)
if not sub_domain: sub_domain = "@"
address = None
with gevent.Timeout(5, Exception("Timeout: 5s")):
res = Http.get("https://dnschain.info/bit/d/%s" % re.sub(r"\.bit$", "", top_domain)).read()
data = json.loads(res)["value"]
for key, val in data["zeronet"].items():
self.dns_cache[key+"."+top_domain] = [val, time.time()+60*60*5] # Cache for 5 hours
self.saveDnsCache()
return data["zeronet"].get(sub_domain)
# Not found
return address
except Exception as err:
log.debug("Dnschain.info %s resolve error: %s" % (domain, Debug.formatException(err)))
# Resolve domain
# Return: The address or None
def resolveDomain(self, domain):
domain = domain.lower()
if self.dns_cache == None:
self.loadDnsCache()
if domain.count(".") < 2: # Its a topleved request, prepend @. to it
domain = "@."+domain
domain_details = self.dns_cache.get(domain)
if domain_details and time.time() < domain_details[1]: # Found in cache and its not expired
return domain_details[0]
else:
# Resovle dns using dnschain
thread_dnschain_info = gevent.spawn(self.resolveDomainDnschainInfo, domain)
thread_dnschain_net = gevent.spawn(self.resolveDomainDnschainNet, domain)
gevent.joinall([thread_dnschain_net, thread_dnschain_info]) # Wait for finish
if thread_dnschain_info.value and thread_dnschain_net.value: # Booth successfull
if thread_dnschain_info.value == thread_dnschain_net.value: # Same returned value
return thread_dnschain_info.value
else:
log.error("Dns %s missmatch: %s != %s" % (domain, thread_dnschain_info.value, thread_dnschain_net.value))
# Problem during resolve
if domain_details: # Resolve failed, but we have it in the cache
domain_details[1] = time.time()+60*60 # Dont try again for 1 hour
return domain_details[0]
else: # Not found in cache
self.dns_cache[domain] = [None, time.time()+60] # Don't check again for 1 min
return None
# Return or create site and start download site files
# Return: Site or None if dns resolve failed
def need(self, address, all_file=True):
if self.isDomain(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, all_file)
# Return: Site object or None if not found
def get(self, address):
if self.sites == None: # Not loaded yet
self.load()
if self.isDomain(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 = self.sites.get(address)
return site

View file

@ -1,34 +0,0 @@
import re
from Plugin import PluginManager
@PluginManager.registerTo("UiRequest")
class UiRequestPlugin(object):
def __init__(self, server = None):
from Site import SiteManager
self.site_manager = SiteManager.site_manager
super(UiRequestPlugin, self).__init__(server)
# Media request
def actionSiteMedia(self, path):
match = re.match(r"/media/(?P<address>[A-Za-z0-9-]+\.[A-Za-z0-9\.-]+)(?P<inner_path>/.*|$)", path)
if match: # Its a valid domain, resolve first
domain = match.group("address")
address = self.site_manager.resolveDomain(domain)
if address:
path = "/media/"+address+match.group("inner_path")
return super(UiRequestPlugin, self).actionSiteMedia(path) # Get the wrapper frame output
# Is mediarequest allowed from that referer
def isMediaRequestAllowed(self, site_address, referer):
referer_path = re.sub("http[s]{0,1}://.*?/", "/", referer).replace("/media", "") # Remove site address
referer_site_address = re.match(r"/(?P<address>[A-Za-z0-9\.-]+)(?P<inner_path>/.*|$)", referer_path).group("address")
if referer_site_address == site_address: # Referer site address as simple address
return True
elif self.site_manager.resolveDomain(referer_site_address) == site_address: # Referer site address as dns
return True
else: # Invalid referer
return False

View file

@ -1,3 +0,0 @@
# This plugin is experimental, if you really want to enable uncomment the following lines:
# import DnschainPlugin
# import SiteManagerPlugin

View file

@ -1,180 +0,0 @@
import logging, json, os, re, sys, time, socket
from Plugin import PluginManager
from Config import config
from Debug import Debug
from http.client import HTTPSConnection, HTTPConnection, HTTPException
from base64 import b64encode
allow_reload = False # No reload supported
@PluginManager.registerTo("SiteManager")
class SiteManagerPlugin(object):
def load(self, *args, **kwargs):
super(SiteManagerPlugin, self).load(*args, **kwargs)
self.log = logging.getLogger("ZeronetLocal Plugin")
self.error_message = None
if not config.namecoin_host or not config.namecoin_rpcport or not config.namecoin_rpcuser or not config.namecoin_rpcpassword:
self.error_message = "Missing parameters"
self.log.error("Missing parameters to connect to namecoin node. Please check all the arguments needed with '--help'. Zeronet will continue working without it.")
return
url = "%(host)s:%(port)s" % {"host": config.namecoin_host, "port": config.namecoin_rpcport}
self.c = HTTPConnection(url, timeout=3)
user_pass = "%(user)s:%(password)s" % {"user": config.namecoin_rpcuser, "password": config.namecoin_rpcpassword}
userAndPass = b64encode(bytes(user_pass, "utf-8")).decode("ascii")
self.headers = {"Authorization" : "Basic %s" % userAndPass, "Content-Type": " application/json " }
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
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(".")
if self.error_message:
self.log.error("Not able to connect to Namecoin node : {!s}".format(self.error_message))
return None
if len(domain_array) > 2:
self.log.error("Too many subdomains! Can only handle one level (eg. staging.mixtape.bit)")
return None
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:
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"]
except Exception as err:
#domain doesn't exist
return None
if "zeronet" in domain_object["value"]:
zeronet_domains = json.loads(domain_object["value"])["zeronet"]
if isinstance(zeronet_domains, str):
# {
# "zeronet":"19rXKeKptSdQ9qt7omwN82smehzTuuq6S9"
# } is valid
zeronet_domains = {"": zeronet_domains}
self.cache[domain] = {"addresses_resolved": zeronet_domains, "time": time.time()}
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"]
self.cache[domain] = {"addresses_resolved": zeronet_domains, "time": time.time()}
else:
# No Zeronet address registered
return None
return self.cache[domain]["addresses_resolved"][subdomain]
@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")
return super(ConfigPlugin, self).createArguments()

View file

@ -1,39 +0,0 @@
import re
from Plugin import PluginManager
@PluginManager.registerTo("UiRequest")
class UiRequestPlugin(object):
def __init__(self, *args, **kwargs):
from Site import SiteManager
self.site_manager = SiteManager.site_manager
super(UiRequestPlugin, self).__init__(*args, **kwargs)
# Media request
def actionSiteMedia(self, path):
match = re.match(r"/media/(?P<address>[A-Za-z0-9-]+\.[A-Za-z0-9\.-]+)(?P<inner_path>/.*|$)", path)
if match: # Its a valid domain, resolve first
domain = match.group("address")
address = self.site_manager.resolveDomain(domain)
if address:
path = "/media/"+address+match.group("inner_path")
return super(UiRequestPlugin, self).actionSiteMedia(path) # Get the wrapper frame output
# Is mediarequest allowed from that referer
def isMediaRequestAllowed(self, site_address, referer):
referer_path = re.sub("http[s]{0,1}://.*?/", "/", referer).replace("/media", "") # Remove site address
referer_path = re.sub(r"\?.*", "", referer_path) # Remove http params
if self.isProxyRequest(): # Match to site domain
referer = re.sub("^http://zero[/]+", "http://", referer) # Allow /zero access
referer_site_address = re.match("http[s]{0,1}://(.*?)(/|$)", referer).group(1)
else: # Match to request path
referer_site_address = re.match(r"/(?P<address>[A-Za-z0-9\.-]+)(?P<inner_path>/.*|$)", referer_path).group("address")
if referer_site_address == site_address: # Referer site address as simple address
return True
elif self.site_manager.resolveDomain(referer_site_address) == site_address: # Referer site address as dns
return True
else: # Invalid referer
return False

View file

@ -1,2 +0,0 @@
from . import UiRequestPlugin
from . import SiteManagerPlugin