# Path: hashdd/algorithms/algorithm.py
# class algorithm(object):
#     name = None
#     validation_regex = None
#     sample = None # The result of hashing sample.exe
#     implements_readfile = False
# 
#     def __init__(self, arg):
#         self.setup(arg)
#         self.update(arg)
# 
#     @staticmethod
#     def prefilter(arg):
#         """
#         Override, use to inspect the input buffer
#         to determine if it meets algorithm requirements
#         (e.g. length). Return True to continue processing 
#         otherwise return False to abort
#         """
#         return True 
#     
#     def setup(self, arg):
#         # Override
#         pass
# 
#     def hexdigest(self):
#         # Override
#         pass
# 
#     def update(self, arg):
#         # Override
#         pass
# 
#     def digest(self):
#         # Override
#         pass
# 
#     def copy(self):
#         copy = super(self.__class__, self).__new__(self.__class__)
#         return copy
# 
#     def readfile(self, filename, filesize):
#         raise NotImplemented
# 
#     @classmethod
#     def validate(self, string):
#         """Checks an input string to determine if it matches the characteristics
#         of the hash
#         """
#         if self.validation_regex is None:
#             raise Exception("Cannot validate string for \
#                     algorithm {}, no alphabet and/or digest_size \
#                     defined".format(self.name))
# 
#         return bool(self.validation_regex.match(string))
# 
# Path: hashdd/features/feature.py
# class feature(object):
#     def __init__(self, buffer, filename):
#         self.buffer = buffer
#         self.filename = filename
#         
#         self.setup()
#         self.result = self.process()
# 
#     
#     def setup(self):
#         # Override
#         pass
# 
#     def process(self):
#         # Override
#         pass
# 
# Path: hashdd/constants.py
# MAX_SIZE = 16 * 1024 * 1024


import hashlib
import os
import logging
from os.path import join
from functools import partial
from hashdd.algorithms.algorithm import algorithm
from hashdd.features.feature import feature
from hashdd.constants import MAX_SIZE
    def _runmod_algo(self, algorithmname):
        if not self._buffer and self._filename_size == 0:
            return None

        module = getattr(hashlib, algorithmname)

        hexdigest = None
        if self._buffer:
            # For buffers we use prefilter, for chunked files, we don't
            if module.prefilter(self._buffer):
                hexdigest = module(self._buffer).hexdigest()
        elif self._filename:
            m = module(b'')

            if m.implements_readfile:
                m.readfile(self._filename, self._filename_size)
            else:
                with open(self._filename, 'rb') as f:
                    for chunk in iter(partial(f.read, self.CHUNK_SIZE), b''):
                        m.update(chunk)

            hexdigest = m.hexdigest()

        return hexdigest

    def _runmod_feature(self, modfeature):
        return modfeature(buffer=self._buffer, filename=self._filename).result

    def _generate_hashes(self):
        algos = list(hashlib.algorithms_available)

# Path: hashdd/algorithms/algorithm.py
# class algorithm(object):
#     name = None
#     validation_regex = None
#     sample = None # The result of hashing sample.exe
#     implements_readfile = False
# 
#     def __init__(self, arg):
#         self.setup(arg)
#         self.update(arg)
# 
#     @staticmethod
#     def prefilter(arg):
#         """
#         Override, use to inspect the input buffer
#         to determine if it meets algorithm requirements
#         (e.g. length). Return True to continue processing 
#         otherwise return False to abort
#         """
#         return True 
#     
#     def setup(self, arg):
#         # Override
#         pass
# 
#     def hexdigest(self):
#         # Override
#         pass
# 
#     def update(self, arg):
#         # Override
#         pass
# 
#     def digest(self):
#         # Override
#         pass
# 
#     def copy(self):
#         copy = super(self.__class__, self).__new__(self.__class__)
#         return copy
# 
#     def readfile(self, filename, filesize):
#         raise NotImplemented
# 
#     @classmethod
#     def validate(self, string):
#         """Checks an input string to determine if it matches the characteristics
#         of the hash
#         """
#         if self.validation_regex is None:
#             raise Exception("Cannot validate string for \
#                     algorithm {}, no alphabet and/or digest_size \
#                     defined".format(self.name))
# 
#         return bool(self.validation_regex.match(string))
# 
# Path: hashdd/features/feature.py
# class feature(object):
#     def __init__(self, buffer, filename):
#         self.buffer = buffer
#         self.filename = filename
#         
#         self.setup()
#         self.result = self.process()
# 
#     
#     def setup(self):
#         # Override
#         pass
# 
#     def process(self):
#         # Override
#         pass
# 
# Path: hashdd/constants.py
# MAX_SIZE = 16 * 1024 * 1024


# Path: hashdd/hashdd.py
import hashlib
import os
import logging
from os.path import join
from functools import partial
from hashdd.algorithms.algorithm import algorithm
from hashdd.features.feature import feature
from hashdd.constants import MAX_SIZE

    def _runmod_algo(self, algorithmname):
        if not self._buffer and self._filename_size == 0:
            return None

        module = getattr(hashlib, algorithmname)

        hexdigest = None
        if self._buffer:
            # For buffers we use prefilter, for chunked files, we don't
            if module.prefilter(self._buffer):
                hexdigest = module(self._buffer).hexdigest()
        elif self._filename:
            m = module(b'')

            if m.implements_readfile:
                m.readfile(self._filename, self._filename_size)
            else:
                with open(self._filename, 'rb') as f:
                    for chunk in iter(partial(f.read, self.CHUNK_SIZE), b''):
                        m.update(chunk)

            hexdigest = m.hexdigest()

        return hexdigest

    def _runmod_feature(self, modfeature):
        return modfeature(buffer=self._buffer, filename=self._filename).result

    def _generate_hashes(self):
        algos = list(hashlib.algorithms_available)

        for a in algorithm.__subclasses__():