From: Nils Gillmann Date: Thu, 17 May 2018 12:30:37 +0000 (+0000) Subject: Opportunisticly rename gnunet-chk.py to let its python invokation line be generated... X-Git-Tag: v0.11.0pre66~37^2~3 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=42399e29836ef338bd6452391f3fc62348e6e4fa;p=oweals%2Fgnunet.git Opportunisticly rename gnunet-chk.py to let its python invokation line be generated (py.in), and assume that it is not supposed to be installed Signed-off-by: Nils Gillmann --- diff --git a/contrib/Makefile.am b/contrib/Makefile.am index 577924fab..1db5b3091 100644 --- a/contrib/Makefile.am +++ b/contrib/Makefile.am @@ -20,7 +20,8 @@ noinst_SCRIPTS = \ terminate.py \ pydiffer.py \ gnunet_pyexpect.py \ - gnunet_janitor.py + gnunet_janitor.py \ + gnunet-chk.py dist_pkgdata_DATA = \ gns-bcd.html \ @@ -50,6 +51,7 @@ EXTRA_DIST = \ terminate.py.in \ gnunet_pyexpect.py.in \ gnunet_janitor.py.in \ + gnunet-chk.py.in \ pydiffer.py.in \ gnunet-gns-import.sh \ openvpn-tap32/tapw32/tap0901.sys \ diff --git a/contrib/gnunet-chk.py b/contrib/gnunet-chk.py deleted file mode 100755 index dba694c34..000000000 --- a/contrib/gnunet-chk.py +++ /dev/null @@ -1,382 +0,0 @@ -#!/usr/bin/python -# This file is part of GNUnet. -# (C) 2013 Christian Grothoff (and other contributing authors) -# -# GNUnet is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published -# by the Free Software Foundation; either version 3, or (at your -# option) any later version. -# -# GNUnet is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNUnet; see the file COPYING. If not, write to the -# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -# Boston, MA 02110-1301, USA. -# -# File: gnunet-chk.py -# Brief: Computes GNUNET style Content Hash Key for a given file -# Author: Sree Harsha Totakura - -from hashlib import sha512 -import logging -import os -import getopt -import sys -from Crypto.Cipher import AES - - -# Defaults -DBLOCK_SIZE = (32 * 1024) # Data block size - -# Pick a multiple of 2 here to achive 8-byte alignment! We also -# probably want DBlocks to have (roughly) the same size as IBlocks. -# With SHA-512, the optimal value is 32768 byte / 128 byte = 256 (128 -# byte = 2 * 512 bits). DO NOT CHANGE! -CHK_PER_INODE = 256 - -CHK_HASH_SIZE = 64 # SHA-512 hash = 512 bits = 64 bytes - -CHK_QUERY_SIZE = CHK_HASH_SIZE # Again a SHA-512 hash - -GNUNET_FS_URI_PREFIX = "gnunet://fs/" # FS CHK URI prefix - -GNUNET_FS_URI_CHK_INFIX = "chk/" # FS CHK URI infix - - -def encode_data_to_string(data): - """Returns an ASCII encoding of the given data block like - GNUNET_STRINGS_data_to_string() function. - - data: A bytearray representing the block of data which has to be encoded - """ - echart = "0123456789ABCDEFGHIJKLMNOPQRSTUV" - assert (None != data) - assert (bytearray == type(data)) - size = len(data) - assert (0 != size) - vbit = 0 - wpos = 0 - rpos = 0 - bits = 0 - out = "" - while (rpos < size) or (vbit > 0): - if (rpos < size) and (vbit < 5): - bits = (bits << 8) | data[rpos] # eat 8 more bits - rpos += 1 - vbit += 8 - if (vbit < 5): - bits <<= (5 - vbit) # zero-padding - assert (vbit == ((size * 8) % 5)) - vbit = 5 - out += echart[(bits >> (vbit - 5)) & 31] - wpos += 1 - vbit -= 5 - assert (0 == vbit) - return out; - - -def sha512_hash(data): - """ Returns the sha512 hash of the given data. - - data: string to hash - """ - hash_obj = sha512() - hash_obj.update(data) - return hash_obj.digest() - - -class AESKey: - """Class for AES Keys. Contains the main key and the initialization - vector. """ - - key = None # The actual AES key - iv = None # The initialization vector - cipher = None # The cipher object - KEY_SIZE = 32 # AES 256-bit key = 32 bytes - IV_SIZE = AES.block_size # Initialization vector size (= AES block size) - - def __init__(self, passphrase): - """Creates a new AES key. - - passphrase: string containing the passphrase to get the AES key and - initialization vector - """ - passphrase = bytearray(passphrase); - self.key = bytearray(self.KEY_SIZE) - self.iv = bytearray(self.IV_SIZE) - if (len(passphrase) > self.KEY_SIZE): - self.key = passphrase[:self.KEY_SIZE] - passphrase = passphrase[self.KEY_SIZE:] - if (len(passphrase) > self.IV_SIZE): - self.iv = passphrase[:self.IV_SIZE] - else: - self.iv[0:len(passphrase)] = passphrase - else: - self.key[0:len(passphrase)] = passphrase - self.key = str(self.key) - self.iv = str(self.iv) - assert (len(self.key) == self.KEY_SIZE) - assert (len(self.iv) == self.IV_SIZE) - - -def setup_aes_cipher_(aes_key): - """Initializes the AES object with settings similar to those in GNUnet. - - aes_key: the AESKey object - Returns the newly initialized AES object - """ - return AES.new(aes_key.key, AES.MODE_CFB, aes_key.iv, segment_size=128) - - -def aes_pad_(data): - """Adds padding to the data such that the size of the data is a multiple of - 16 bytes - - data: the data string - Returns a tuple:(pad_len, data). pad_len denotes the number of bytes added - as padding; data is the new data string with padded bytes at the end - """ - pad_len = len(data) % 16 - if (0 != pad_len): - pad_len = 16 - pad_len - pad_bytes = bytearray(15) - data += str(pad_bytes[:pad_len]) - return (pad_len, data) - - -def aes_encrypt(aes_key, data): - """Encrypts the given data using AES. - - aes_key: the AESKey object to use for AES encryption - data: the data string to encrypt - """ - (pad_len, data) = aes_pad_(data) - cipher = setup_aes_cipher_(aes_key) - enc_data = cipher.encrypt(data) - if (0 != pad_len): - enc_data = enc_data[:-pad_len] - return enc_data - - -def aes_decrypt(aes_key, data): - """Decrypts the given data using AES - - aes_key: the AESKey object to use for AES decryption - data: the data string to decrypt - """ - (pad_len, data) = aes_pad_(data) - cipher = setup_aes_cipher_(aes_key) - ptext = cipher.decrypt(data) - if (0 != pad_len): - ptext = ptext[:-pad_len] - return ptext - - -class Chk: - """Class for the content hash key.""" - key = None - query = None - fsize = None - - def __init__(self, key, query): - assert (len(key) == CHK_HASH_SIZE) - assert (len(query) == CHK_QUERY_SIZE) - self.key = key - self.query = query - - def setSize(self, size): - self.fsize = size - - def uri(self): - sizestr = repr(self.fsize) - if isinstance(self.fsize, long): - sizestr = sizestr[:-1] - return GNUNET_FS_URI_PREFIX + GNUNET_FS_URI_CHK_INFIX + \ - encode_data_to_string(bytearray(self.key)) + "." + \ - encode_data_to_string(bytearray(self.query)) + "." + \ - sizestr - - -def compute_depth_(size): - """Computes the depth of the hash tree. - - size: the size of the file whose tree's depth has to be computed - Returns the depth of the tree. Always > 0. - """ - depth = 1 - fl = DBLOCK_SIZE - while (fl < size): - depth += 1 - if ((fl * CHK_PER_INODE) < fl): - return depth - fl = fl * CHK_PER_INODE - return depth - - -def compute_tree_size_(depth): - """Calculate how many bytes of payload a block tree of the given depth MAY - correspond to at most (this function ignores the fact that some blocks will - only be present partially due to the total file size cutting some blocks - off at the end). - - depth: depth of the block. depth==0 is a DBLOCK. - Returns the number of bytes of payload a subtree of this depth may - correspond to. - """ - rsize = DBLOCK_SIZE - for cnt in range(0, depth): - rsize *= CHK_PER_INODE - return rsize - - -def compute_chk_offset_(depth, end_offset): - """Compute the offset of the CHK for the current block in the IBlock - above - - depth: depth of the IBlock in the tree (aka overall number of tree levels - minus depth); 0 == DBLOCK - end_offset: current offset in the overall file, at the *beginning* of the - block for DBLOCK (depth == 0), otherwise at the *end* of the - block (exclusive) - Returns the offset in the list of CHKs in the above IBlock - """ - bds = compute_tree_size_(depth) - if (depth > 0): - end_offset -= 1 - ret = end_offset / bds - return ret % CHK_PER_INODE - - -def compute_iblock_size_(depth, offset): - """Compute the size of the current IBLOCK. The encoder is triggering the - calculation of the size of an IBLOCK at the *end* (hence end_offset) of its - construction. The IBLOCK maybe a full or a partial IBLOCK, and this - function is to calculate how long it should be. - - depth: depth of the IBlock in the tree, 0 would be a DBLOCK, must be > 0 - (this function is for IBLOCKs only!) - offset: current offset in the payload (!) of the overall file, must be > 0 - (since this function is called at the end of a block). - Returns the number of elements to be in the corresponding IBlock - """ - assert (depth > 0) - assert (offset > 0) - bds = compute_tree_size_(depth) - mod = offset % bds - if mod is 0: - ret = CHK_PER_INODE - else: - bds /= CHK_PER_INODE - ret = mod / bds - if (mod % bds) is not 0: - ret += 1 - return ret - - -def compute_rootchk(readin, size): - """Returns the content hash key after generating the hash tree for the given - input stream. - - readin: the stream where to read data from - size: the size of data to be read - """ - depth = compute_depth_(size); - current_depth = 0 - chks = [None] * (depth * CHK_PER_INODE) # list buffer - read_offset = 0 - logging.debug("Begining to calculate tree hash with depth: " + repr(depth)) - while True: - if (depth == current_depth): - off = CHK_PER_INODE * (depth - 1) - assert (chks[off] is not None) - logging.debug("Encoding done, reading CHK `" + chks[off].query + \ - "' from " + repr(off) + "\n") - uri_chk = chks[off] - assert (size == read_offset) - uri_chk.setSize(size) - return uri_chk - if (0 == current_depth): - pt_size = min(DBLOCK_SIZE, size - read_offset); - try: - pt_block = readin.read(pt_size) - except IOError: - logging.warning("Error reading input file stream") - return None - else: - pt_elements = compute_iblock_size_(current_depth, read_offset) - pt_block = "" - pt_block = \ - reduce((lambda ba, chk: - ba + (chk.key + chk.query)), - chks[(current_depth - 1) * CHK_PER_INODE:][:pt_elements], - pt_block) - pt_size = pt_elements * (CHK_HASH_SIZE + CHK_QUERY_SIZE) - assert (len(pt_block) == pt_size) - assert (pt_size <= DBLOCK_SIZE) - off = compute_chk_offset_(current_depth, read_offset) - logging.debug("Encoding data at offset " + repr(read_offset) + \ - " and depth " + repr(current_depth) + " with block " \ - "size " + repr(pt_size) + " and target CHK offset " + \ - repr(current_depth * CHK_PER_INODE)) - pt_hash = sha512_hash(pt_block) - pt_aes_key = AESKey(pt_hash) - pt_enc = aes_encrypt(pt_aes_key, pt_block) - pt_enc_hash = sha512_hash(pt_enc) - chk = Chk(pt_hash, pt_enc_hash) - chks[(current_depth * CHK_PER_INODE) + off] = chk - if (0 == current_depth): - read_offset += pt_size - if (read_offset == size) or \ - (0 == (read_offset % (CHK_PER_INODE * DBLOCK_SIZE))): - current_depth += 1 - else: - if (CHK_PER_INODE == off) or (read_offset == size): - current_depth += 1 - else: - current_depth = 0 - - -def chkuri_from_path(path): - """Returns the CHK URI of the file at the given path. - - path: the path of the file whose CHK has to be calculated - """ - size = os.path.getsize(path) - readin = open(path, "rb") - chk = compute_rootchk(readin, size) - readin.close() - return chk.uri() - - -def usage(): - """Prints help about using this script.""" - print(""" -Usage: gnunet-chk.py [options] file -Prints the Content Hash Key of given file in GNUNET-style URI. - -Options: - -h, --help : prints this message -""") - - -if '__main__' == __name__: - try: - opts, args = getopt.getopt(sys.argv[1:], "h", ["help"]) - except getopt.GetoptError, err: - print(err) - print("Exception occured") - usage() - sys.exit(2) - for option, value in opts: - if option in("-h", "--help"): - usage() - sys.exit(0) - if len(args) != 1: - print("Incorrect number of arguments passed") - usage() - sys.exit(1) - print chkuri_from_path(args[0]) diff --git a/contrib/gnunet-chk.py.in b/contrib/gnunet-chk.py.in new file mode 100755 index 000000000..83e26f244 --- /dev/null +++ b/contrib/gnunet-chk.py.in @@ -0,0 +1,382 @@ +#!@PYTHON@ +# This file is part of GNUnet. +# (C) 2013, 2018 Christian Grothoff (and other contributing authors) +# +# GNUnet is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published +# by the Free Software Foundation; either version 3, or (at your +# option) any later version. +# +# GNUnet is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNUnet; see the file COPYING. If not, write to the +# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# File: gnunet-chk.py +# Brief: Computes GNUNET style Content Hash Key for a given file +# Author: Sree Harsha Totakura + +from hashlib import sha512 +import logging +import os +import getopt +import sys +from Crypto.Cipher import AES + + +# Defaults +DBLOCK_SIZE = (32 * 1024) # Data block size + +# Pick a multiple of 2 here to achive 8-byte alignment! We also +# probably want DBlocks to have (roughly) the same size as IBlocks. +# With SHA-512, the optimal value is 32768 byte / 128 byte = 256 (128 +# byte = 2 * 512 bits). DO NOT CHANGE! +CHK_PER_INODE = 256 + +CHK_HASH_SIZE = 64 # SHA-512 hash = 512 bits = 64 bytes + +CHK_QUERY_SIZE = CHK_HASH_SIZE # Again a SHA-512 hash + +GNUNET_FS_URI_PREFIX = "gnunet://fs/" # FS CHK URI prefix + +GNUNET_FS_URI_CHK_INFIX = "chk/" # FS CHK URI infix + + +def encode_data_to_string(data): + """Returns an ASCII encoding of the given data block like + GNUNET_STRINGS_data_to_string() function. + + data: A bytearray representing the block of data which has to be encoded + """ + echart = "0123456789ABCDEFGHIJKLMNOPQRSTUV" + assert (None != data) + assert (bytearray == type(data)) + size = len(data) + assert (0 != size) + vbit = 0 + wpos = 0 + rpos = 0 + bits = 0 + out = "" + while (rpos < size) or (vbit > 0): + if (rpos < size) and (vbit < 5): + bits = (bits << 8) | data[rpos] # eat 8 more bits + rpos += 1 + vbit += 8 + if (vbit < 5): + bits <<= (5 - vbit) # zero-padding + assert (vbit == ((size * 8) % 5)) + vbit = 5 + out += echart[(bits >> (vbit - 5)) & 31] + wpos += 1 + vbit -= 5 + assert (0 == vbit) + return out; + + +def sha512_hash(data): + """ Returns the sha512 hash of the given data. + + data: string to hash + """ + hash_obj = sha512() + hash_obj.update(data) + return hash_obj.digest() + + +class AESKey: + """Class for AES Keys. Contains the main key and the initialization + vector. """ + + key = None # The actual AES key + iv = None # The initialization vector + cipher = None # The cipher object + KEY_SIZE = 32 # AES 256-bit key = 32 bytes + IV_SIZE = AES.block_size # Initialization vector size (= AES block size) + + def __init__(self, passphrase): + """Creates a new AES key. + + passphrase: string containing the passphrase to get the AES key and + initialization vector + """ + passphrase = bytearray(passphrase); + self.key = bytearray(self.KEY_SIZE) + self.iv = bytearray(self.IV_SIZE) + if (len(passphrase) > self.KEY_SIZE): + self.key = passphrase[:self.KEY_SIZE] + passphrase = passphrase[self.KEY_SIZE:] + if (len(passphrase) > self.IV_SIZE): + self.iv = passphrase[:self.IV_SIZE] + else: + self.iv[0:len(passphrase)] = passphrase + else: + self.key[0:len(passphrase)] = passphrase + self.key = str(self.key) + self.iv = str(self.iv) + assert (len(self.key) == self.KEY_SIZE) + assert (len(self.iv) == self.IV_SIZE) + + +def setup_aes_cipher_(aes_key): + """Initializes the AES object with settings similar to those in GNUnet. + + aes_key: the AESKey object + Returns the newly initialized AES object + """ + return AES.new(aes_key.key, AES.MODE_CFB, aes_key.iv, segment_size=128) + + +def aes_pad_(data): + """Adds padding to the data such that the size of the data is a multiple of + 16 bytes + + data: the data string + Returns a tuple:(pad_len, data). pad_len denotes the number of bytes added + as padding; data is the new data string with padded bytes at the end + """ + pad_len = len(data) % 16 + if (0 != pad_len): + pad_len = 16 - pad_len + pad_bytes = bytearray(15) + data += str(pad_bytes[:pad_len]) + return (pad_len, data) + + +def aes_encrypt(aes_key, data): + """Encrypts the given data using AES. + + aes_key: the AESKey object to use for AES encryption + data: the data string to encrypt + """ + (pad_len, data) = aes_pad_(data) + cipher = setup_aes_cipher_(aes_key) + enc_data = cipher.encrypt(data) + if (0 != pad_len): + enc_data = enc_data[:-pad_len] + return enc_data + + +def aes_decrypt(aes_key, data): + """Decrypts the given data using AES + + aes_key: the AESKey object to use for AES decryption + data: the data string to decrypt + """ + (pad_len, data) = aes_pad_(data) + cipher = setup_aes_cipher_(aes_key) + ptext = cipher.decrypt(data) + if (0 != pad_len): + ptext = ptext[:-pad_len] + return ptext + + +class Chk: + """Class for the content hash key.""" + key = None + query = None + fsize = None + + def __init__(self, key, query): + assert (len(key) == CHK_HASH_SIZE) + assert (len(query) == CHK_QUERY_SIZE) + self.key = key + self.query = query + + def setSize(self, size): + self.fsize = size + + def uri(self): + sizestr = repr(self.fsize) + if isinstance(self.fsize, long): + sizestr = sizestr[:-1] + return GNUNET_FS_URI_PREFIX + GNUNET_FS_URI_CHK_INFIX + \ + encode_data_to_string(bytearray(self.key)) + "." + \ + encode_data_to_string(bytearray(self.query)) + "." + \ + sizestr + + +def compute_depth_(size): + """Computes the depth of the hash tree. + + size: the size of the file whose tree's depth has to be computed + Returns the depth of the tree. Always > 0. + """ + depth = 1 + fl = DBLOCK_SIZE + while (fl < size): + depth += 1 + if ((fl * CHK_PER_INODE) < fl): + return depth + fl = fl * CHK_PER_INODE + return depth + + +def compute_tree_size_(depth): + """Calculate how many bytes of payload a block tree of the given depth MAY + correspond to at most (this function ignores the fact that some blocks will + only be present partially due to the total file size cutting some blocks + off at the end). + + depth: depth of the block. depth==0 is a DBLOCK. + Returns the number of bytes of payload a subtree of this depth may + correspond to. + """ + rsize = DBLOCK_SIZE + for cnt in range(0, depth): + rsize *= CHK_PER_INODE + return rsize + + +def compute_chk_offset_(depth, end_offset): + """Compute the offset of the CHK for the current block in the IBlock + above + + depth: depth of the IBlock in the tree (aka overall number of tree levels + minus depth); 0 == DBLOCK + end_offset: current offset in the overall file, at the *beginning* of the + block for DBLOCK (depth == 0), otherwise at the *end* of the + block (exclusive) + Returns the offset in the list of CHKs in the above IBlock + """ + bds = compute_tree_size_(depth) + if (depth > 0): + end_offset -= 1 + ret = end_offset / bds + return ret % CHK_PER_INODE + + +def compute_iblock_size_(depth, offset): + """Compute the size of the current IBLOCK. The encoder is triggering the + calculation of the size of an IBLOCK at the *end* (hence end_offset) of its + construction. The IBLOCK maybe a full or a partial IBLOCK, and this + function is to calculate how long it should be. + + depth: depth of the IBlock in the tree, 0 would be a DBLOCK, must be > 0 + (this function is for IBLOCKs only!) + offset: current offset in the payload (!) of the overall file, must be > 0 + (since this function is called at the end of a block). + Returns the number of elements to be in the corresponding IBlock + """ + assert (depth > 0) + assert (offset > 0) + bds = compute_tree_size_(depth) + mod = offset % bds + if mod is 0: + ret = CHK_PER_INODE + else: + bds /= CHK_PER_INODE + ret = mod / bds + if (mod % bds) is not 0: + ret += 1 + return ret + + +def compute_rootchk(readin, size): + """Returns the content hash key after generating the hash tree for the given + input stream. + + readin: the stream where to read data from + size: the size of data to be read + """ + depth = compute_depth_(size); + current_depth = 0 + chks = [None] * (depth * CHK_PER_INODE) # list buffer + read_offset = 0 + logging.debug("Begining to calculate tree hash with depth: " + repr(depth)) + while True: + if (depth == current_depth): + off = CHK_PER_INODE * (depth - 1) + assert (chks[off] is not None) + logging.debug("Encoding done, reading CHK `" + chks[off].query + \ + "' from " + repr(off) + "\n") + uri_chk = chks[off] + assert (size == read_offset) + uri_chk.setSize(size) + return uri_chk + if (0 == current_depth): + pt_size = min(DBLOCK_SIZE, size - read_offset); + try: + pt_block = readin.read(pt_size) + except IOError: + logging.warning("Error reading input file stream") + return None + else: + pt_elements = compute_iblock_size_(current_depth, read_offset) + pt_block = "" + pt_block = \ + reduce((lambda ba, chk: + ba + (chk.key + chk.query)), + chks[(current_depth - 1) * CHK_PER_INODE:][:pt_elements], + pt_block) + pt_size = pt_elements * (CHK_HASH_SIZE + CHK_QUERY_SIZE) + assert (len(pt_block) == pt_size) + assert (pt_size <= DBLOCK_SIZE) + off = compute_chk_offset_(current_depth, read_offset) + logging.debug("Encoding data at offset " + repr(read_offset) + \ + " and depth " + repr(current_depth) + " with block " \ + "size " + repr(pt_size) + " and target CHK offset " + \ + repr(current_depth * CHK_PER_INODE)) + pt_hash = sha512_hash(pt_block) + pt_aes_key = AESKey(pt_hash) + pt_enc = aes_encrypt(pt_aes_key, pt_block) + pt_enc_hash = sha512_hash(pt_enc) + chk = Chk(pt_hash, pt_enc_hash) + chks[(current_depth * CHK_PER_INODE) + off] = chk + if (0 == current_depth): + read_offset += pt_size + if (read_offset == size) or \ + (0 == (read_offset % (CHK_PER_INODE * DBLOCK_SIZE))): + current_depth += 1 + else: + if (CHK_PER_INODE == off) or (read_offset == size): + current_depth += 1 + else: + current_depth = 0 + + +def chkuri_from_path(path): + """Returns the CHK URI of the file at the given path. + + path: the path of the file whose CHK has to be calculated + """ + size = os.path.getsize(path) + readin = open(path, "rb") + chk = compute_rootchk(readin, size) + readin.close() + return chk.uri() + + +def usage(): + """Prints help about using this script.""" + print(""" +Usage: gnunet-chk.py [options] file +Prints the Content Hash Key of given file in GNUNET-style URI. + +Options: + -h, --help : prints this message +""") + + +if '__main__' == __name__: + try: + opts, args = getopt.getopt(sys.argv[1:], "h", ["help"]) + except getopt.GetoptError, err: + print(err) + print("Exception occured") + usage() + sys.exit(2) + for option, value in opts: + if option in("-h", "--help"): + usage() + sys.exit(0) + if len(args) != 1: + print("Incorrect number of arguments passed") + usage() + sys.exit(1) + print chkuri_from_path(args[0])