Exemplo n.º 1
0
    def setUp(self):
        """
        Setup everything needed for the test
        """

        PyFunceble.load_config(generate_directory_structure=False,
                               custom={"db_type": "json"})

        self.file_to_test = "this_file_is_a_ghost"

        self.file = (PyFunceble.CONFIG_DIRECTORY +
                     PyFunceble.OUTPUTS["default_files"]["inactive_db"])

        self.expected_content = {
            self.file_to_test: {
                "0": {
                    "mÿethèrwallét.com":
                    PyFunceble.STATUS["official"]["invalid"],
                    "||google.com^": PyFunceble.STATUS["official"]["invalid"],
                }
            }
        }

        self.time_past = str(int(PyFunceble.time()) - (365 * 24 * 3600))
        self.time_future = str(int(PyFunceble.time()) + (365 * 24 * 3600))

        self.inactive_db = InactiveDB(self.file_to_test)
Exemplo n.º 2
0
    def __init__(self, subject, complete=False, configuration=None):
        # We share the subject.
        self.subject = subject

        # We share the complete option.
        self.complete = complete
        # We share the configuration.
        self.configuration = configuration

        # We load the global configuration
        # if it was not alreay done.
        PyFunceble.load_config(generate_directory_structure=False,
                               custom=self.configuration)

        if ("api_file_generation" in PyFunceble.CONFIGURATION
                and PyFunceble.CONFIGURATION["api_file_generation"]):
            PyFunceble.load_config(generate_directory_structure=True)

        # We update the configuration with the given
        # configuration.
        PyFunceble.Preset().api()

        # We get an instance of the DB connection.
        self.sqlite_db = SQLite()
        self.mysql_db = MySQL()

        # We create an instance of the whois database.
        self.whois_db = WhoisDB(sqlite_db=self.sqlite_db,
                                mysql_db=self.mysql_db)

        # We create an instance of the inactive database.
        self.inactive_db = InactiveDB("api_call",
                                      sqlite_db=self.sqlite_db,
                                      mysql_db=self.mysql_db)
Exemplo n.º 3
0
    def __init__(self, file, file_type="domain"):
        # We share the file we are working with.
        self.file = file
        # We share the file/test type.
        self.file_type = file_type

        # We construct the list of UP statuses.
        self.list_of_up_statuses = PyFunceble.STATUS["list"]["up"]
        self.list_of_up_statuses.extend(PyFunceble.STATUS["list"]["valid"])

        # We get/initiate the db.
        self.sqlite_db = SQLite()
        self.mysql_db = MySQL()

        # We get/initiate the preset class.
        self.preset = PyFunceble.Preset()
        # We get/initiate the autosave database/subsyste..
        self.autosave = AutoSave(start_time=PyFunceble.INTERN["start"])
        # We get/initiate the inactive database.
        self.inactive_db = InactiveDB(self.file,
                                      sqlite_db=self.sqlite_db,
                                      mysql_db=self.mysql_db)
        # We get/initiate the whois database.
        self.whois_db = WhoisDB(sqlite_db=self.sqlite_db,
                                mysql_db=self.mysql_db)
        # We get/initiate the mining subsystem.
        self.mining = Mining(self.file,
                             sqlite_db=self.sqlite_db,
                             mysql_db=self.mysql_db)
        # We get/initiate the autocontinue subsystem.
        self.autocontinue = AutoContinue(
            self.file,
            parent_process=True,
            sqlite_db=self.sqlite_db,
            mysql_db=self.mysql_db,
        )

        # We initiate a variable which will tell us when
        # we start testing for complements.
        self.complements_test_started = False

        # We download the file if it is a list.
        self.download_link()
Exemplo n.º 4
0
class FileCore:  # pylint: disable=too-many-instance-attributes
    """
    Brain of PyFunceble for file testing.

    :param str file: The file we are testing.

    :param str file_type:
        The file type.
        Should be one of the following.

            - :code:`domain`

            - :code:`url`
    """

    # We set a regex of element to delete.
    # Understand with this variable that we don't want to test those.
    regex_ignore = r"localhost$|localdomain$|local$|broadcasthost$|0\.0\.0\.0$|allhosts$|allnodes$|allrouters$|localnet$|loopback$|mcastprefix$|ip6-mcastprefix$|ip6-localhost$|ip6-loopback$|ip6-allnodes$|ip6-allrouters$|ip6-localnet$"  # pylint: disable=line-too-long

    def __init__(self, file, file_type="domain"):
        # We share the file we are working with.
        self.file = file
        # We share the file/test type.
        self.file_type = file_type

        # We construct the list of UP statuses.
        self.list_of_up_statuses = PyFunceble.STATUS["list"]["up"]
        self.list_of_up_statuses.extend(PyFunceble.STATUS["list"]["valid"])

        # We get/initiate the db.
        self.sqlite_db = SQLite()
        self.mysql_db = MySQL()

        # We get/initiate the preset class.
        self.preset = PyFunceble.Preset()
        # We get/initiate the autosave database/subsyste..
        self.autosave = AutoSave(start_time=PyFunceble.INTERN["start"])
        # We get/initiate the inactive database.
        self.inactive_db = InactiveDB(self.file,
                                      sqlite_db=self.sqlite_db,
                                      mysql_db=self.mysql_db)
        # We get/initiate the whois database.
        self.whois_db = WhoisDB(sqlite_db=self.sqlite_db,
                                mysql_db=self.mysql_db)
        # We get/initiate the mining subsystem.
        self.mining = Mining(self.file,
                             sqlite_db=self.sqlite_db,
                             mysql_db=self.mysql_db)
        # We get/initiate the autocontinue subsystem.
        self.autocontinue = AutoContinue(
            self.file,
            parent_process=True,
            sqlite_db=self.sqlite_db,
            mysql_db=self.mysql_db,
        )

        # We initiate a variable which will tell us when
        # we start testing for complements.
        self.complements_test_started = False

        # We download the file if it is a list.
        self.download_link()

    @classmethod
    def get_simple_coloration(cls, status):
        """
        Given a status we give the coloration for the simple mode.

        :param str status: An official status output.
        """

        if status in [
                PyFunceble.STATUS["official"]["up"],
                PyFunceble.STATUS["official"]["valid"],
        ]:
            # The status is in the list of UP status.

            # We return the green coloration.
            return PyFunceble.Fore.GREEN + PyFunceble.Style.BRIGHT

        if status == PyFunceble.STATUS["official"]["down"]:
            # The status is in the list of DOWN status.

            # We return the red coloration.
            return PyFunceble.Fore.RED + PyFunceble.Style.BRIGHT

        # The status is not in the list of UP nor DOWN status.

        # We return the cyam coloration.
        return PyFunceble.Fore.CYAN + PyFunceble.Style.BRIGHT

    def download_link(self):  # pragma: no cover
        """
        Download the file if it is an URL.
        """

        if PyFunceble.Check(self.file).is_url():
            # We get the destination.
            destination = self.file.split("/")[-1]

            if self.file and self.autocontinue.is_empty():
                # The given file is an URL.

                if (not PyFunceble.path.isfile(destination) or
                        PyFunceble.INTERN["counter"]["number"]["tested"] == 0):
                    # The filename does not exist in the current directory
                    # or the currently number of tested is equal to 0.

                    # We download the content of the link.
                    Download(self.file, destination).text()

            # We update the global file with the destination.
            self.file = destination

    def domain(self, subject):  # pragma: no cover
        """
        Handle the test of a single domain.

        :param str subject: The subject we are testing.
        """

        if subject:
            # The given subject is not empty nor None.

            if PyFunceble.CONFIGURATION["syntax"]:
                # The syntax mode is activated.

                # We get the status from SyntaxStatus.
                status = SyntaxStatus(subject,
                                      subject_type="file_domain",
                                      filename=self.file).get()["status"]
            else:
                # We test and get the status of the domain.
                status = Status(
                    subject,
                    subject_type="file_domain",
                    filename=self.file,
                    whois_db=self.whois_db,
                    inactive_db=self.inactive_db,
                ).get()["status"]

            if PyFunceble.CONFIGURATION["simple"]:
                # The simple mode is activated.

                # We print the domain and the status.
                print("{0} {1}".format(
                    self.get_simple_coloration(status) + subject, status))

            if self.complements_test_started:
                # We started to test the complements.

                # We generate the complement file(s).
                Generate(subject, "file_domain", status).complements_file()

            # We return the status.
            return status

        # We return None, there is nothing to test.
        return None

    def url(self, subject):  # pragma: no cover
        """
        Handle the simple URL testing.

        :param str subject: The subject we are testing.
        """

        if subject:
            # The given subject is not empty nor None.

            if PyFunceble.CONFIGURATION["syntax"]:
                # The syntax mode is activated.

                # We get the status from SyntaxStatus.
                status = SyntaxStatus(subject,
                                      subject_type="file_url",
                                      filename=self.file).get()["status"]
            else:
                # We test and get the status of the domain.
                status = URLStatus(
                    subject,
                    subject_type="file_url",
                    filename=self.file,
                    inactive_db=self.inactive_db,
                ).get()["status"]

            if PyFunceble.CONFIGURATION["simple"]:
                # The simple mode is activated.

                # We print the domain and the status.
                print("{0} {1}".format(
                    self.get_simple_coloration(status) + subject, status))

            if self.complements_test_started:
                # We started to test the complements.

                # We generate the complement file(s).
                Generate(subject, "file_url", status).complements_file()

            # We retunr the status.
            return status

        # We return None, there is nothing to test.
        return None

    @classmethod
    def _format_line(cls, line):
        """
        Format the extracted line before passing it to the system.

        :param str line: The extracted line.

        :return: The formatted line with only the element to test.
        :rtype: str

        .. note:
            Understand by formating the fact that we get rid
            of all the noises around the element we want to test.
        """

        line = line.strip()

        if line and not line.startswith("#"):
            # The line is not a commented line.

            if "#" in line:
                # There is a comment at the end of the line.

                # We delete the comment from the line.
                line = line[:line.find("#")].strip()

            if " " in line or "\t" in line:
                # A space or a tabs is in the line.

                # We remove all whitestring from the extracted line.
                splited_line = line.split()

                # As there was a space or a tab in the string, we consider
                # that we are working with the hosts file format which means
                # that the domain we have to test is after the first string.
                # So we set the index to 1.
                index = 1

                while index < len(splited_line):
                    # We loop until the index is greater than the length of
                    #  the splited line.

                    if splited_line[index]:
                        # The element at the current index is not an empty string.

                        # We break the loop.
                        break

                    # The element at the current index is an empty string.

                    # We increase the index number.
                    index += 1  # pragma: no cover

                # We return the last read element.
                return splited_line[index]

            # We return the extracted line.
            return line

        # The extracted line is a comment line.

        # We return an empty string as we do not want to work with commented line.
        return ""

    def __process_test(self, subject):  # pragma: no cover
        """
        Given a subject, we perform its test.

        :param str subject: The subjet we have to test.
        """

        if self.file_type == "domain":
            # We are testing for domains.

            if PyFunceble.CONFIGURATION["idna_conversion"]:
                # We have to convert to IDNA:

                # We get and return the status of the IDNA
                # domain.
                return self.domain(domain2idna(subject))

            # We get and return the status of the domain.
            return self.domain(subject)

        if self.file_type == "url":
            # We are testing for urls.

            # We get and return the status of the URL.
            return self.url(subject)

        # We raise an exception, we could not understand the
        # given file type.
        raise Exception("Unknown file type.")

    def get_complements(self):  # pragma: no cover
        """
        Generate a list of complements to test.
        """

        # We initiate an empty list of complements.
        complements = []

        if (PyFunceble.CONFIGURATION["generate_complements"]
                and self.autocontinue.authorized):
            # * The user want us to generate and test the list
            # of all complements.
            # and
            # * The autocontinue subsystem is activated.

            # We inform all subsystem that we are testing for complements.
            self.complements_test_started = True

            # We get/generate the complements.
            complements = self.autocontinue.get_or_generate_complements()

        return complements

    def _test_line(self, line, manager_data=None):  # pylint: disable=too-many-branches  # pragma: no cover
        """
        Given a line, we test it.

        :param str line: A line to work with.
        :param multiprocessing.Manager.list manager_data: A Server process.
        """

        if PyFunceble.CONFIGURATION[
                "db_type"] == "json" and manager_data is not None:
            autocontinue = AutoContinue(self.file, parent_process=False)
            inactive_db = InactiveDB(self.file)
            mining = Mining(self.file)
        else:
            # We use the previously initiated autocontinue instance.
            autocontinue = self.autocontinue

            # We use the previously initiated inactive database instance.
            inactive_db = self.inactive_db

            # We use the previously initiated mining instance.
            mining = self.mining

        # We remove cariage from the given line.
        line = line.strip()

        if not line or line[0] == "#":
            # We line is a comment line.

            # We return None, there is nothing to test.
            return None

        if Regex(line, self.regex_ignore, escape=False,
                 return_data=False).match():
            # The line match our list of elemenet
            # to ignore.

            # We return None, there is nothing to test.
            return None

        # We format the line, it's the last
        # rush before starting to filter and test.
        subject = self._format_line(line)

        if (not PyFunceble.CONFIGURATION["local"]
                and PyFunceble.Check(subject).is_reserved_ipv4()):
            # * We are not testing for local components.
            # and
            # * The subject is a reserved IPv4.

            # We return None, there is nothing to test.
            return None

        if PyFunceble.CONFIGURATION["filter"]:
            # We have to filter.

            if Regex(subject,
                     PyFunceble.CONFIGURATION["filter"],
                     return_data=False).match():
                # The line match the given filter.

                # We get the status of the current line.
                status = self.__process_test(subject)
            else:
                # The line does not match the given filter.

                # We return None.
                return None
        else:
            # We do not have to filter.

            # We get the status of the current line.
            status = self.__process_test(subject)

        # We add the line into the auto continue database.
        autocontinue.add(subject, status)

        if status.lower() in self.list_of_up_statuses:
            # The status is in the list of UP status.

            # We mine if necessary.
            mining.mine(subject, self.file_type)

            if subject in inactive_db:
                # The subject is in the inactive database.

                # We generate the suspicous file.
                Generate(subject, "file_domain", PyFunceble.STATUS["official"]
                         ["up"]).analytic_file("suspicious")

                # And we remove the current subject from
                # the inactive database.
                inactive_db.remove(subject)
        else:
            # The status is not in the list of UP status.

            # We add the current subject into the
            # inactive database.
            inactive_db.add(subject, status)

        if (self.complements_test_started
                and PyFunceble.CONFIGURATION["db_type"] == "json"):
            # We started the test of the complements.

            if "complements" in autocontinue.database:
                # The complement index is present.

                while subject in autocontinue.database["complements"]:
                    # We loop untill the line is not present into the
                    # database.

                    # We remove the currently tested element.
                    autocontinue.database["complements"].remove(subject)

                    # We save the current state.
                    autocontinue.save()

        if manager_data is None:
            # We are not in a multiprocess environment.

            # We update the counters
            autocontinue.update_counters()

            # We process the autosaving if it is necessary.
            self.autosave.process(test_completed=False)
        elif PyFunceble.CONFIGURATION["db_type"] == "json":
            # We are in a multiprocess environment.

            # We save everything we initiated into the server process
            manager_data.append({
                "autocontinue": autocontinue.database,
                "inactive_db": inactive_db.database,
                "mining": mining.database,
            })

        # We return None.
        return None

    def _get_list_to_of_subjects_to_test_from_file(
            self, file_object):  # pragma: no cover
        """
        Give a file object, we construct/get the list of subject to test.
        """

        to_retest_inactive_db = self.inactive_db.get_to_retest()

        if PyFunceble.CONFIGURATION["multiprocess"]:
            with Pool(PyFunceble.CONFIGURATION["maximal_processes"]) as pool:
                if not PyFunceble.CONFIGURATION["adblock"]:
                    formatted_subjects = set(
                        pool.map(self._format_line, file_object))
                else:
                    formatted_subjects = {
                        x
                        for x in AdBlock(file_object).decode()
                    }
        else:
            if not PyFunceble.CONFIGURATION["adblock"]:
                formatted_subjects = {
                    self._format_line(x)
                    for x in file_object
                }
            else:
                formatted_subjects = {x for x in AdBlock(file_object).decode()}

        subjects_to_test = (formatted_subjects -
                            self.autocontinue.get_already_tested() -
                            self.inactive_db.get_already_tested() -
                            to_retest_inactive_db)

        if not subjects_to_test:
            subjects_to_test = list(formatted_subjects)
        else:
            subjects_to_test = list(subjects_to_test)

        if not PyFunceble.CONFIGURATION["multiprocess"]:
            if not PyFunceble.CONFIGURATION["hierarchical_sorting"]:
                subjects_to_test = List(subjects_to_test).custom_format(
                    Sort.standard)
            else:
                subjects_to_test = List(subjects_to_test).custom_format(
                    Sort.hierarchical)

        return chain(subjects_to_test, to_retest_inactive_db)

    def read_and_test_file_content(self):  # pragma: no cover
        """
        Read a file block by block and test its content.
        """

        # We print the CLI header.
        PyFunceble.CLICore.print_header()

        with open(self.file, "r", encoding="utf-8") as file:
            # We open the file we have to test.

            for line in self._get_list_to_of_subjects_to_test_from_file(file):
                # We loop through the file decoded file
                # content.

                # We test the line.
                self._test_line(line)

        for index, line in self.mining.list_of_mined():
            # We loop through the list of mined domains
            # (if the mining subystem is activated.)

            # We test the line.
            self._test_line(line)
            # and remove the currently tested line
            # from the mining database.
            self.mining.remove(index, line)

        for subject in self.get_complements():
            # We loop through the list of complements.

            # We test the complement.
            self._test_line(subject)

        # We inform all subsystem that we are not testing for complements anymore.
        self.complements_test_started = False

        # We update the counters
        self.autocontinue.update_counters()
        # We clean the autocontinue subsystem, we finished
        # the test.
        self.autocontinue.clean()
        # We process the autosaving if necessary.
        self.autosave.process(test_completed=True)
        # We close the database connection
        if self.sqlite_db.authorized:
            self.sqlite_db.connection.close()
        if self.mysql_db.authorized:
            self.mysql_db.get_connection().close()
Exemplo n.º 5
0
    def _test_line(self, line, manager_data=None):  # pylint: disable=too-many-branches  # pragma: no cover
        """
        Given a line, we test it.

        :param str line: A line to work with.
        :param multiprocessing.Manager.list manager_data: A Server process.
        """

        if PyFunceble.CONFIGURATION[
                "db_type"] == "json" and manager_data is not None:
            autocontinue = AutoContinue(self.file, parent_process=False)
            inactive_db = InactiveDB(self.file)
            mining = Mining(self.file)
        else:
            # We use the previously initiated autocontinue instance.
            autocontinue = self.autocontinue

            # We use the previously initiated inactive database instance.
            inactive_db = self.inactive_db

            # We use the previously initiated mining instance.
            mining = self.mining

        # We remove cariage from the given line.
        line = line.strip()

        if not line or line[0] == "#":
            # We line is a comment line.

            # We return None, there is nothing to test.
            return None

        if Regex(line, self.regex_ignore, escape=False,
                 return_data=False).match():
            # The line match our list of elemenet
            # to ignore.

            # We return None, there is nothing to test.
            return None

        # We format the line, it's the last
        # rush before starting to filter and test.
        subject = self._format_line(line)

        if (not PyFunceble.CONFIGURATION["local"]
                and PyFunceble.Check(subject).is_reserved_ipv4()):
            # * We are not testing for local components.
            # and
            # * The subject is a reserved IPv4.

            # We return None, there is nothing to test.
            return None

        if PyFunceble.CONFIGURATION["filter"]:
            # We have to filter.

            if Regex(subject,
                     PyFunceble.CONFIGURATION["filter"],
                     return_data=False).match():
                # The line match the given filter.

                # We get the status of the current line.
                status = self.__process_test(subject)
            else:
                # The line does not match the given filter.

                # We return None.
                return None
        else:
            # We do not have to filter.

            # We get the status of the current line.
            status = self.__process_test(subject)

        # We add the line into the auto continue database.
        autocontinue.add(subject, status)

        if status.lower() in self.list_of_up_statuses:
            # The status is in the list of UP status.

            # We mine if necessary.
            mining.mine(subject, self.file_type)

            if subject in inactive_db:
                # The subject is in the inactive database.

                # We generate the suspicous file.
                Generate(subject, "file_domain", PyFunceble.STATUS["official"]
                         ["up"]).analytic_file("suspicious")

                # And we remove the current subject from
                # the inactive database.
                inactive_db.remove(subject)
        else:
            # The status is not in the list of UP status.

            # We add the current subject into the
            # inactive database.
            inactive_db.add(subject, status)

        if (self.complements_test_started
                and PyFunceble.CONFIGURATION["db_type"] == "json"):
            # We started the test of the complements.

            if "complements" in autocontinue.database:
                # The complement index is present.

                while subject in autocontinue.database["complements"]:
                    # We loop untill the line is not present into the
                    # database.

                    # We remove the currently tested element.
                    autocontinue.database["complements"].remove(subject)

                    # We save the current state.
                    autocontinue.save()

        if manager_data is None:
            # We are not in a multiprocess environment.

            # We update the counters
            autocontinue.update_counters()

            # We process the autosaving if it is necessary.
            self.autosave.process(test_completed=False)
        elif PyFunceble.CONFIGURATION["db_type"] == "json":
            # We are in a multiprocess environment.

            # We save everything we initiated into the server process
            manager_data.append({
                "autocontinue": autocontinue.database,
                "inactive_db": inactive_db.database,
                "mining": mining.database,
            })

        # We return None.
        return None
Exemplo n.º 6
0
class TestInactiveDB(TestCase):
    """
    Test PyFunceble.database.Inactive
    """
    def setUp(self):
        """
        Setup everything needed for the test
        """

        PyFunceble.load_config(generate_directory_structure=False,
                               custom={"db_type": "json"})

        self.file_to_test = "this_file_is_a_ghost"

        self.file = (PyFunceble.CONFIG_DIRECTORY +
                     PyFunceble.OUTPUTS["default_files"]["inactive_db"])

        self.expected_content = {
            self.file_to_test: {
                "0": {
                    "mÿethèrwallét.com":
                    PyFunceble.STATUS["official"]["invalid"],
                    "||google.com^": PyFunceble.STATUS["official"]["invalid"],
                }
            }
        }

        self.time_past = str(int(PyFunceble.time()) - (365 * 24 * 3600))
        self.time_future = str(int(PyFunceble.time()) + (365 * 24 * 3600))

        self.inactive_db = InactiveDB(self.file_to_test)

    def test_file_not_exist(self):
        """
        Test if everything is right with the generated
        file.
        """

        File(self.file).delete()

        expected = False
        actual = PyFunceble.path.isfile(self.file)

        self.assertEqual(expected, actual)

    def test_load_file_not_exist(self):
        """
        Test the case that we want to load the database file that does not exist.
        """

        self.test_file_not_exist()

        self.inactive_db.load()

        expected = {self.file_to_test: {}}

        self.assertEqual(expected, self.inactive_db.database)

        self.test_file_not_exist()

    def test_load_file_exist(self):
        """
        Test the case that we want to load a file that exist.
        """

        self.test_file_not_exist()

        Dict(self.expected_content).to_json(self.file)
        self.inactive_db.database = {}
        self.inactive_db.load()

        self.assertEqual(self.expected_content, self.inactive_db.database)

        self.test_file_not_exist()

    def test_save(self):
        """
        Test the saving of the inactive database.
        """

        self.test_file_not_exist()
        self.inactive_db.database = self.expected_content

        self.inactive_db.save()

        self.assertEqual(self.expected_content,
                         Dict().from_json(File(self.file).read()))

        self.test_file_not_exist()

    def test_initiate__path_not_exist(self):  # pylint: disable=invalid-name
        """
        Test Inactive.initiate() for the case that the path does not exist.
        """

        self.test_file_not_exist()

        self.inactive_db.database = {}

        expected = {self.file_to_test: {}}

        self.inactive_db.initiate()

        self.assertEqual(expected, self.inactive_db.database)

        self.test_file_not_exist()

    def test_initiate__path_exist_time_past(self):  # pylint: disable=invalid-name
        """
        Test Inactive.initiate() for the case that the path exist but
        the timestamp is in the past.
        """

        self.test_file_not_exist()

        new_time = str(
            int(PyFunceble.time()) - self.inactive_db.one_day_in_seconds - 100)

        self.inactive_db.database = {
            self.file_to_test: {
                self.time_past: {
                    "hello.world": PyFunceble.STATUS["official"]["down"],
                    "world.hello": PyFunceble.STATUS["official"]["down"],
                },
                "to_test": {
                    "github.com": ""
                },
            }
        }

        expected = {
            self.file_to_test: {
                self.time_past: {
                    "hello.world": PyFunceble.STATUS["official"]["down"],
                    "world.hello": PyFunceble.STATUS["official"]["down"],
                },
                new_time: {
                    "github.com": ""
                },
            }
        }

        self.inactive_db.save()
        self.inactive_db.initiate()

        self.assertEqual(expected, self.inactive_db.database)
        self.test_file_not_exist()

    def test_initiate__path_exist_time_future(self):  # pylint: disable=invalid-name
        """
        Test Inactive.initiate() for the case that the path exist but
        the timestamp is in the future.
        """

        self.test_file_not_exist()

        self.inactive_db.database = {
            self.file_to_test: {
                self.time_future: {
                    "hello.world": PyFunceble.STATUS["official"]["down"],
                    "world.hello": PyFunceble.STATUS["official"]["down"],
                }
            }
        }

        expected = {
            self.file_to_test: {
                self.time_future: {
                    "hello.world": PyFunceble.STATUS["official"]["down"],
                    "world.hello": PyFunceble.STATUS["official"]["down"],
                }
            }
        }

        self.inactive_db.save()
        self.inactive_db.initiate()

        self.assertEqual(expected, self.inactive_db.database)

        self.test_file_not_exist()

    def test_timestamp_path_does_not_exit(self):  # pylint: disable=invalid-name
        """
        Test Inactive._timestamp() for the case that the path does
        not exist but the time is in the past.
        """

        self.test_file_not_exist()

        self.inactive_db.database = {}

        expected = int(PyFunceble.time())
        actual = self.inactive_db._timestamp()

        self.assertGreaterEqual(expected, actual)

        self.test_file_not_exist()

    def test_timestamp_path_exist_time_past(self):  # pylint: disable=invalid-name
        """
        Test Inactive._timestamp() for the case that the path exist but
        the time is in the past.
        """

        self.test_file_not_exist()

        self.inactive_db.database = {
            self.file_to_test: {
                self.time_past: ["hello.world", "world.hello"]
            }
        }

        expected = int(PyFunceble.time())
        actual = self.inactive_db._timestamp()

        self.assertGreaterEqual(expected, actual)

        self.test_file_not_exist()

    def test_timestamp_path_exist_time_future(self):  # pylint: disable=invalid-name
        """
        Test Inactive._timestamp() for the case that the path exist but
        the time is in the future.
        """

        self.test_file_not_exist()

        self.inactive_db.database = {
            self.file_to_test: {
                self.time_future: ["hello.world", "world.hello"]
            }
        }

        expected = int(self.time_future)
        actual = self.inactive_db._timestamp()

        self.assertEqual(expected, actual)

        self.test_file_not_exist()

    def test_add_path_does_not_exist(self):  # pylint: disable=invalid-name
        """
        Test Inactive.add() for the case that the path does not exist.
        """

        self.test_file_not_exist()

        self.inactive_db.database = {}
        subject = "hello.world"

        expected = {
            self.file_to_test: {
                str(self.inactive_db._timestamp()): {
                    "hello.world": PyFunceble.STATUS["official"]["down"]
                }
            }
        }

        self.inactive_db.add(subject, PyFunceble.STATUS["official"]["down"])
        self.assertEqual(expected, self.inactive_db.database)

        self.inactive_db.database = {}
        subject = "http://hello.world"

        expected = {
            self.file_to_test: {
                str(self.inactive_db._timestamp()): {
                    "http://hello.world": PyFunceble.STATUS["official"]["down"]
                }
            }
        }

        self.inactive_db.add(subject, PyFunceble.STATUS["official"]["down"])
        self.assertEqual(expected, self.inactive_db.database)

        self.test_file_not_exist()

    def test_add_file_path_not_present(self):  # pylint: disable=invalid-name
        """
        Test Inactive.add() for the case that the path is not
        present into the Inactive.
        """

        self.test_file_not_exist()

        timestamp = str(self.inactive_db._timestamp())
        subject = "hello.world"
        expected = {
            self.file_to_test: {
                timestamp: {
                    "hello.world": PyFunceble.STATUS["official"]["down"]
                }
            }
        }

        self.inactive_db.add(subject, PyFunceble.STATUS["official"]["down"])

        self.assertEqual(expected, self.inactive_db.database)

        self.test_file_not_exist()

    def test_add_file_path_present(self):  # pylint: disable=invalid-name
        """
        Test Inactive.add() for the case that the path is present
        into the Inactive.
        """

        self.test_file_not_exist()

        timestamp = str(self.inactive_db._timestamp())
        subject = "hello.world"

        expected = {
            self.file_to_test: {
                timestamp: {
                    "hello.world": PyFunceble.STATUS["official"]["down"],
                    "world.hello": PyFunceble.STATUS["official"]["down"],
                }
            }
        }

        self.inactive_db.database = {
            self.file_to_test: {
                timestamp: {
                    "world.hello": PyFunceble.STATUS["official"]["down"]
                }
            }
        }

        self.inactive_db.add(subject, PyFunceble.STATUS["official"]["down"])

        self.assertEqual(expected, self.inactive_db.database)

        self.test_file_not_exist()

    def test_remove(self):
        """
        Test Inactive.remove().
        """

        timestamp = str(self.inactive_db._timestamp())

        self.test_file_not_exist()

        self.inactive_db.database = {
            self.file_to_test: {
                timestamp: {
                    "hello.world": PyFunceble.STATUS["official"]["down"]
                }
            }
        }
        subject = "hello.world"

        expected = {self.file_to_test: {timestamp: {}}}

        self.inactive_db.remove(subject)

        self.assertEqual(expected, self.inactive_db.database)

        self.test_file_not_exist()

    def test_is_present(self):
        """
        Test the presence of element in the databse.
        """

        self.test_file_not_exist()

        # Test of the case that everything goes right !
        timestamp = str(self.inactive_db._timestamp())

        self.inactive_db.database = {
            self.file_to_test: {
                timestamp: ["hello.world", "world.hello", "hello-world.com"]
            }
        }
        subject = "hello.world"

        expected = True
        actual = subject in self.inactive_db

        self.assertEqual(expected, actual)

        del self.inactive_db.database[self.file_to_test][timestamp]
        subject = "world.hello.world"
        expected = False
        actual = subject in self.inactive_db

        self.assertEqual(expected, actual)

        self.assertEqual(expected, actual)

        self.test_file_not_exist()
Exemplo n.º 7
0
class APICore:
    """
    Provide the logic and interface for the tests from the API.

    :param str subject: The element we are testing.
    :param bool complete:
        Activate the return of a dictionnary with signigicant - if not all -
        data about the test.

    :param dict configuration:
        The configuration to
    """

    # The subject we are working with.
    subject = None
    # Tell us if we have to return all possible data.
    complete = False
    # Saves the configuration.
    configuration = None

    def __init__(self, subject, complete=False, configuration=None):
        # We share the subject.
        self.subject = subject

        # We share the complete option.
        self.complete = complete
        # We share the configuration.
        self.configuration = configuration

        # We load the global configuration
        # if it was not alreay done.
        PyFunceble.load_config(generate_directory_structure=False,
                               custom=self.configuration)

        if ("api_file_generation" in PyFunceble.CONFIGURATION
                and PyFunceble.CONFIGURATION["api_file_generation"]):
            PyFunceble.load_config(generate_directory_structure=True)

        # We update the configuration with the given
        # configuration.
        PyFunceble.Preset().api()

        # We get an instance of the DB connection.
        self.sqlite_db = SQLite()
        self.mysql_db = MySQL()

        # We create an instance of the whois database.
        self.whois_db = WhoisDB(sqlite_db=self.sqlite_db,
                                mysql_db=self.mysql_db)

        # We create an instance of the inactive database.
        self.inactive_db = InactiveDB("api_call",
                                      sqlite_db=self.sqlite_db,
                                      mysql_db=self.mysql_db)

    def __inactive_database_management(self, subject, status):
        """
        Given the subject and status, we add or remove the subject
        from the inactive database.
        """

        if self.inactive_db.authorized:
            # We are authorized to operate with the
            # inactive database.s

            if status.lower() in PyFunceble.STATUS["list"]["up"]:
                # The status is in the list of UP status.

                # We remove it from the database.
                self.inactive_db.remove(subject)
            else:
                # The status is not in the list of UP status.

                # We add it into the database.
                self.inactive_db.add(subject, status)

    def domain_and_ip(self):
        """
        Run a domain/IP avaibility check over the given subject.
        """

        if isinstance(self.subject, list):
            # The given subject is a list of subjects.

            # We initiate a variable which save our result.
            result = {}

            for subject in self.subject:
                # We loop through the list of subject.

                # We get the complete data related to the status
                # of the subject.
                data = Status(subject,
                              subject_type="domain",
                              whois_db=self.whois_db).get()

                if self.complete:
                    # The user want a copy of the complete data.

                    # We set it.
                    result[subject] = data
                else:
                    # The user do not want a copy of the complete data.

                    # We only set the status.
                    result[subject] = data["status"]

                self.__inactive_database_management(subject, data["status"])

            # We return our local result.
            return result

        # We get the status of the given subject.
        data = Status(self.subject,
                      subject_type="domain",
                      whois_db=self.whois_db).get()

        self.__inactive_database_management(self.subject, data["status"])

        if self.complete:
            # The user want a copy of the compelte data.

            # We return them
            return data

        # We only return the status.
        return data["status"]

    def domain_syntax(self):
        """
        Run a domain syntax check over the given subject.
        """

        if isinstance(self.subject, list):
            # The given subject is a list of subject.

            # We return the validity of each subjects.
            return {
                subject: PyFunceble.Check(subject).is_domain()
                for subject in self.subject
            }

        # We return the validity of the the given subject.
        return PyFunceble.Check(self.subject).is_domain()

    def subdomain_syntax(self):
        """
        Run a subdomain syntax check over the given subject.
        """

        if isinstance(self.subject, list):
            # The given subjet is a list of subject.

            # We return the validity of each subjects.
            return {
                subject: PyFunceble.Check(subject).is_subdomain()
                for subject in self.subject
            }

        # We return the validity of the given subject.
        return PyFunceble.Check(self.subject).is_subdomain()

    def ipv4_syntax(self):
        """
        Run an IPv4 syntax check over the given subject.
        """

        if isinstance(self.subject, list):
            # The given subjet is a list of subject.

            # We return the validity of each subjects.
            return {
                subject: PyFunceble.Check(subject).is_ipv4()
                for subject in self.subject
            }

        # We return the validity of the given subject.
        return PyFunceble.Check(self.subject).is_ipv4()

    def ipv4_range_syntax(self):
        """
        Run an IPv4 range syntax check over the given subject.
        """

        if isinstance(self.subject, list):
            # The given subjet is a list of subject.

            # We return the validity of each subjects.
            return {
                subject: PyFunceble.Check(subject).is_ipv4_range()
                for subject in self.subject
            }

        # We return the validity of the given subject.
        return PyFunceble.Check(self.subject).is_ipv4_range()

    def url(self):
        """
        Run an URL avaibility check over the given subject.
        """

        if isinstance(self.subject, list):
            # The given subjet is a list of subject.

            # We initiate a local variable which will save
            # what we are going to return.
            result = {}

            for subject in self.subject:
                # We loop through the list of subjects.

                # We get the complete data about the status.
                data = URLStatus(subject, subject_type="url").get()

                if self.complete:
                    # The user want a complete copy of the data.

                    # We set it.
                    result[subject] = data
                else:
                    # The user does not want a complete copy of the data.

                    # We only set the status.
                    result[subject] = data["status"]

                self.__inactive_database_management(subject, data["status"])

            # We return the result of each subjects.
            return result

        # We get the complete data about the status of the subject.
        data = URLStatus(self.subject, subject_type="url").get()

        self.__inactive_database_management(self.subject, data["status"])

        if self.complete:
            # The user want a complete copy of the data.

            # We return them.
            return data

        # We return the result of each subjects.
        return data["status"]

    def url_syntax(self):
        """
        Run an IPv4 syntax check over the given subject.
        """

        if isinstance(self.subject, list):
            # The given subjet is a list of subject.

            # We return the validity of each subjects.
            return {
                subject: PyFunceble.Check(subject).is_url()
                for subject in self.subject
            }

        # We return the validity of the subject.
        return PyFunceble.Check(self.subject).is_url()