From 0cce0f4318fe165185b7e870b0e001961d765f4f Mon Sep 17 00:00:00 2001 From: Kevin Froman Date: Mon, 11 Nov 2019 23:32:18 -0600 Subject: [PATCH] sites now support multi pages --- onionr/__init__.py | 2 +- onionr/httpapi/onionrsitesapi/__init__.py | 32 +++++++++++++++++++++- onionr/httpapi/onionrsitesapi/sitefiles.py | 15 ++++++---- onionr/httpapi/security/client.py | 2 +- onionr/onionrblocks/insert.py | 2 +- onionr/onionrcommands/parser/recommend.py | 2 +- 6 files changed, 45 insertions(+), 10 deletions(-) diff --git a/onionr/__init__.py b/onionr/__init__.py index b33ded55..a48d6fd2 100755 --- a/onionr/__init__.py +++ b/onionr/__init__.py @@ -59,8 +59,8 @@ setup.setup_config() setup.setup_default_plugins() def onionr_main(): + """Onionr entrypoint, start command processor""" parser.register() - return if ran_as_script: onionr_main() diff --git a/onionr/httpapi/onionrsitesapi/__init__.py b/onionr/httpapi/onionrsitesapi/__init__.py index d40db153..3db799fb 100644 --- a/onionr/httpapi/onionrsitesapi/__init__.py +++ b/onionr/httpapi/onionrsitesapi/__init__.py @@ -34,7 +34,7 @@ from . import sitefiles site_api = Blueprint('siteapi', __name__) -@site_api.route('/site/', endpoint='site') +@site_api.route('/site//', endpoint='site') def site(name: str)->Response: """Accept a site 'name', if pubkey then show multi-page site, if hash show single page site""" resp: str = 'Not Found' @@ -63,3 +63,33 @@ def site(name: str)->Response: if resp == 'Not Found' or not resp: abort(404) return Response(resp) + +@site_api.route('/site//', endpoint='siteFile') +def site_file(name: str, file: str)->Response: + """Accept a site 'name', if pubkey then show multi-page site, if hash show single page site""" + resp: str = 'Not Found' + mime_type = 'text/html' + + # If necessary convert the name to base32 from mnemonic + if mnemonickeys.DELIMITER in name: + name = mnemonickeys.get_base32(name) + + # Now make sure the key is regardless a valid base32 format ed25519 key (readding padding if necessary) + if stringvalidators.validate_pub_key(name): + name = unpaddedbase32.repad(name) + resp = sitefiles.get_file(name, file) + + elif stringvalidators.validate_hash(name): + try: + resp = onionrblockapi.Block(name).bcontent + except onionrexceptions.NoDataAvailable: + abort(404) + except TypeError: + pass + try: + resp = base64.b64decode(resp) + except binascii.Error: + pass + if resp == 'Not Found' or not resp: + abort(404) + return Response(resp) diff --git a/onionr/httpapi/onionrsitesapi/sitefiles.py b/onionr/httpapi/onionrsitesapi/sitefiles.py index 742a3ee5..948662d3 100644 --- a/onionr/httpapi/onionrsitesapi/sitefiles.py +++ b/onionr/httpapi/onionrsitesapi/sitefiles.py @@ -3,6 +3,8 @@ import tarfile import io import os +import unpaddedbase32 + from coredb import blockmetadb from onionrblocks import onionrblockapi from onionrblocks import insert @@ -12,9 +14,11 @@ from onionrtypes import UserID, DeterministicKeyPassphrase, BlockHash from onionrcrypto import generate_deterministic -def find_site_gzip(user_id: str)->str: +def find_site_gzip(user_id: str)->tarfile.TarFile: + """Return verified site tar object""" sites = blockmetadb.get_blocks_by_type('osite') user_site = None + user_id = unpaddedbase32.repad(user_id) for site in sites: block = onionrblockapi.Block(site) if block.isSigner(user_id): @@ -24,12 +28,13 @@ def find_site_gzip(user_id: str)->str: return None def get_file(user_id, file)->Union[bytes, None]: + """Get a site file content""" ret_data = "" site = find_site_gzip(user_id) if site is None: return None - for file in site.getmembers(): - if file.name == file: - return site.extractfile(file) + for t_file in site.getmembers(): + if t_file.name.replace('./', '') == file: + return site.extractfile(t_file) return None def create_site(admin_pass: DeterministicKeyPassphrase, directory:str='.')->Tuple[UserID, BlockHash]: @@ -43,6 +48,6 @@ def create_site(admin_pass: DeterministicKeyPassphrase, directory:str='.')->Tupl raw_tar.seek(0) - block_hash = insert(raw_tar.read(), signing_key=private_key) + block_hash = insert(raw_tar.read(), header='osite', signing_key=private_key, sign=True) return (public_key, block_hash) diff --git a/onionr/httpapi/security/client.py b/onionr/httpapi/security/client.py index d462c1cf..bf4fdd5b 100644 --- a/onionr/httpapi/security/client.py +++ b/onionr/httpapi/security/client.py @@ -24,7 +24,7 @@ from . import pluginwhitelist # Be extremely mindful of this. These are endpoints available without a password whitelist_endpoints = ['www', 'staticfiles.homedata', 'staticfiles.sharedContent', -'staticfiles.friends', 'staticfiles.friendsindex', 'siteapi.site', 'staticfiles.onionrhome', +'staticfiles.friends', 'staticfiles.friendsindex', 'siteapi.site', 'siteapi.siteFile', 'staticfiles.onionrhome', 'themes.getTheme', 'staticfiles.onboarding', 'staticfiles.onboardingIndex'] class ClientAPISecurity: diff --git a/onionr/onionrblocks/insert.py b/onionr/onionrblocks/insert.py index dbc9c272..301d5a49 100644 --- a/onionr/onionrblocks/insert.py +++ b/onionr/onionrblocks/insert.py @@ -29,7 +29,7 @@ def insert_block(data: Union[str, bytes], header: str ='txt', if signing_key != '': # if it was specified to use an alternative private key our_private_key = signing_key - our_pub_key = crypto.cryptoutils.get_pub_key_from_priv(our_private_key) + our_pub_key = bytesconverter.bytes_to_str(crypto.cryptoutils.get_pub_key_from_priv(our_private_key)) use_subprocess = powchoice.use_subprocess(config) storage_counter = storagecounter.StorageCounter() diff --git a/onionr/onionrcommands/parser/recommend.py b/onionr/onionrcommands/parser/recommend.py index 4e8dcc38..a7cf05b3 100644 --- a/onionr/onionrcommands/parser/recommend.py +++ b/onionr/onionrcommands/parser/recommend.py @@ -12,4 +12,4 @@ def recommend(print_default: bool = True): if SequenceMatcher(None, tried, word).ratio() >= 0.75: logger.warn('%s "%s", did you mean "%s"?' % (print_message, tried, word), terminal=True) return - if print_default: logger.error('%s "%s"' % (print_message, tried), terminal=True) \ No newline at end of file + if print_default: logger.error('%s "%s"' % (print_message, tried), terminal=True)