Esempio n. 1
0
    def __init__(
        self,
        subject: Optional[str] = None,
        do_syntax_check_first: Optional[bool] = None,
        db_session: Optional[Session] = None,
        use_collection: Optional[bool] = None,
    ) -> None:
        self.dns_query_tool = DNSQueryTool()
        self.ipv4_reputation_query_tool = IPV4ReputationDataset()
        self.domain_syntax_checker = DomainSyntaxChecker()
        self.ip_syntax_checker = IPSyntaxChecker()
        self.url_syntax_checker = URLSyntaxChecker()

        self.params = ReputationCheckerParams()

        self.status = ReputationCheckerStatus()
        self.status.params = self.params
        self.status.dns_lookup_record = self.dns_query_tool.lookup_record

        super().__init__(
            subject,
            do_syntax_check_first=do_syntax_check_first,
            db_session=db_session,
            use_collection=use_collection,
        )
Esempio n. 2
0
    def test_is_not_valid_not_rfc_compliant(self) -> None:
        """
        Tests the method which let us check if the given subject is valid for
        the case that the given subject is not RFC compliant.
        """

        expected = False

        given = "http://example.hello_world.org"
        actual = URLSyntaxChecker(given).is_valid()

        self.assertEqual(expected, actual)
Esempio n. 3
0
    def test_is_not_valid_not_extension(self) -> None:
        """
        Tests the method which let us check if the given subject is valid for
        the case that the given subject has no valid extension.
        """

        expected = False

        given = "http://example"
        actual = URLSyntaxChecker(given).is_valid()

        self.assertEqual(expected, actual)
Esempio n. 4
0
    def test_is_not_valid(self) -> None:
        """
        Tests the method which let us check if the given subject is valid for
        the case that the given subject is not valid.
        """

        url_checker = URLSyntaxChecker()

        expected = False

        for subject in pyf_test_dataset.NOT_VALID_DOMAINS:
            url_checker.subject = f"{subject}/?is_admin=true"
            actual = url_checker.is_valid()

            self.assertEqual(expected, actual, subject)
Esempio n. 5
0
    def test_is_valid_subdomain(self) -> None:
        """
        Tests the method which let us check if the given subject is valid for
        the case that a subdomain is given.
        """

        url_checker = URLSyntaxChecker()

        expected = True

        for subject in pyf_test_dataset.VALID_SUBDOMAINS:
            url_checker.subject = f"https://{subject}/?is_admin=true"
            actual = url_checker.is_valid()

            self.assertEqual(expected, actual, subject)
Esempio n. 6
0
        def download_file(file: str, destination: str) -> bool:
            """
            Downloads the given file (if it's an URL).

            :param file:
                The file to download.
            :param destination.
                The file to write.

            :return:
                A boolean which represent the action state.
            """

            if URLSyntaxChecker(file).is_valid():
                DownloadHelper(file).download_text(destination=destination)
                return True
            return False
Esempio n. 7
0
def is_url(subject: str, **kwargs) -> bool:
    """
    Checks if the given subject is syntactically a valid URL.

    .. warning::
        This method may be removed in the future.
        It is still available for convenience.

        Please consider the following alternative example:

        ::

            from PyFunceble import DomainReputationChecker

            my_subject = "https://example.org"
            the_status = URLSyntaxChecker(
                my_subject
            ).get_status()

            # Get the status in dict format.
            print(the_status.to_dict())

            # Get the status in json format.
            print(the_status.to_json())

            # Check if it is a URL.
            print(f"{my_subject} is URL ? {the_status.is_valid()}")

    :parma subject:
        The subject to check.
    """

    warnings.warn(
        "PyFunceble.is_url may be removed in the future."
        "Please consider using PyFunceble.URLSyntaxChecker explicitly.",
        DeprecationWarning,
    )

    # pylint: disable=no-member
    return URLSyntaxChecker(subject, **kwargs).get_status().is_valid()
Esempio n. 8
0
class Nameservers:
    """
    Provides an interface to get the right nameserver to communicate with.
    """

    nameservers: Optional[List[str]] = None
    nameserver_ports: Optional[dict] = None

    protocol: Optional[str] = None

    domain_syntax_checker: DomainSyntaxChecker = DomainSyntaxChecker()
    url_syntax_checker: URLSyntaxChecker = URLSyntaxChecker()
    url2netloc: Url2Netloc = Url2Netloc()

    def __init__(self,
                 nameserver: Optional[List[str]] = None,
                 protocol: str = "TCP") -> None:
        self.protocol = protocol

        if nameserver is not None:
            self.set_nameservers(nameserver)

    @staticmethod
    def split_nameserver_from_port(
        nameserver: str,
        *,
        default_port: int = 53,
    ) -> Tuple[str, int]:
        """
        Splits the nameserver from its port.re

        :param nameserver:
            The nameserver to work with.
        :param default_port:
            The default port to apply, if none is found.
        """

        if ":" in nameserver:
            splitted = nameserver.rsplit(":")

            if splitted[-1].isdigit():
                return ":".join(splitted[:-1]), int(splitted[-1])

            return ":".join(splitted), default_port
        return nameserver, default_port

    @classmethod
    def get_ip_from_nameserver(cls, nameserver: str) -> List[str]:
        """
        Given a nameserver, this method resolve it in order to get the
        IP to contact.

        :param nameserver:
            The name to resolve.
        """

        PyFunceble.facility.Logger.info(
            "Started to get ip from nameserver (%r)", nameserver)

        result = []

        if cls.domain_syntax_checker.set_subject(nameserver).is_valid():
            try:
                result.extend([
                    x.address
                    for x in dns.resolver.Resolver().resolve(nameserver, "A")
                ])
            except dns.exception.DNSException:
                pass

            try:
                result.extend([
                    x.address for x in dns.resolver.Resolver().resolve(
                        nameserver, "AAAA")
                ])
            except dns.exception.DNSException:
                pass
        else:
            result.append(nameserver)

        PyFunceble.facility.Logger.debug("IP from nameserver (%r):\n%r",
                                         nameserver, result)

        PyFunceble.facility.Logger.info(
            "Finished to get ip from nameserver (%r)", nameserver)

        return result

    def set_nameservers(self, value: List[str]) -> "Nameservers":
        """
        Sets the nameserver to use.

        Side Effect:
            Also updates the :code:`nameserver_ports` variable.

        :raise TypeError:
            When the given :code:`value` is not a :py:class:`list`.
        :raise ValueError:
            When the given :code:`value` is emtpy.
        """

        if not isinstance(value, list):
            raise TypeError(f"<value> should be {list}, {type(value)} given.")

        if not value:
            raise ValueError("<value> should not be empty.")

        self.nameserver_ports = {}
        self.nameservers = []

        for nameserver in value:
            if self.protocol.lower() == "https":
                if not nameserver.startswith("https://"):
                    netloc = self.url2netloc.set_data_to_convert(
                        nameserver).get_converted()

                    if "/" in nameserver:
                        path = nameserver[nameserver.find("/"):]
                    else:
                        path = ""

                    self.nameservers.append("https://"
                                            # pylint: disable=line-too-long
                                            f"{netloc}{path}")
                else:
                    self.nameservers.append(nameserver)

                # 443 is because it's more likely to be for DOH.
                self.nameserver_ports.update({self.nameservers[-1]: 443})
                continue

            server, port = self.split_nameserver_from_port(nameserver)

            for dns_ip in self.get_ip_from_nameserver(server):
                self.nameservers.append(dns_ip)
                self.nameserver_ports.update({dns_ip: port})

        return self

    def get_nameservers(self) -> Optional[List[str]]:
        """
        Provides the currently set nameservers.
        """

        return self.nameservers

    def get_nameserver_ports(self) -> Optional[dict]:
        """
        Provides the currently set nameserver_ports.
        """

        return self.nameserver_ports

    def guess_and_set_nameservers(self) -> "Nameservers":
        """
        Try to guess and set the nameserver to use.
        """

        if PyFunceble.facility.ConfigLoader.is_already_loaded():
            if PyFunceble.storage.CONFIGURATION.dns.server:
                if isinstance(PyFunceble.storage.CONFIGURATION.dns.server,
                              list):
                    self.set_nameservers(
                        PyFunceble.storage.CONFIGURATION.dns.server)
                else:
                    self.set_nameservers(
                        [PyFunceble.storage.CONFIGURATION.dns.server])
            else:  # pragma: no cover
                ## Well, I don't like playing with the default resolver.
                self.set_nameservers(
                    dns.resolver.get_default_resolver().nameservers)
        else:  # pragma: no cover
            ## Well, I don't like playing with the default resolver.
            self.set_nameservers(
                dns.resolver.get_default_resolver().nameservers)

        return self

    def guess_all_settings(
        self,
    ) -> "Nameservers":  # pragma: no cover ## Method themselves are more important
        """
        Try to guess all settings.
        """

        to_ignore = ["guess_all_settings"]

        for method in dir(self):
            if method in to_ignore or not method.startswith("guess_"):
                continue

            getattr(self, method)()

        return self
Esempio n. 9
0
    def __init__(
        self,
        subject: Optional[str] = None,
        *,
        use_extra_rules: Optional[bool] = None,
        use_whois_lookup: Optional[bool] = None,
        use_dns_lookup: Optional[bool] = None,
        use_netinfo_lookup: Optional[bool] = None,
        use_http_code_lookup: Optional[bool] = None,
        use_reputation_lookup: Optional[bool] = None,
        do_syntax_check_first: Optional[bool] = None,
        db_session: Optional[Session] = None,
        use_whois_db: Optional[bool] = None,
        use_collection: Optional[bool] = None,
    ) -> None:
        self.dns_query_tool = DNSQueryTool()
        self.whois_query_tool = WhoisQueryTool()
        self.addressinfo_query_tool = AddressInfo()
        self.hostbyaddr_query_tool = HostByAddrInfo()
        self.http_status_code_query_tool = HTTPStatusCode()
        self.domain_syntax_checker = DomainSyntaxChecker()
        self.ip_syntax_checker = IPSyntaxChecker()
        self.url_syntax_checker = URLSyntaxChecker()
        self.extra_rules_handler = ExtraRulesHandler()
        self.db_session = db_session

        self.params = AvailabilityCheckerParams()

        self.status = AvailabilityCheckerStatus()
        self.status.params = self.params
        self.status.dns_lookup_record = self.dns_query_tool.lookup_record
        self.status.whois_lookup_record = self.whois_query_tool.lookup_record

        if use_extra_rules is not None:
            self.use_extra_rules = use_extra_rules
        else:
            self.guess_and_set_use_extra_rules()

        if use_whois_lookup is not None:
            self.use_whois_lookup = use_whois_lookup
        else:
            self.guess_and_set_use_whois_lookup()

        if use_dns_lookup is not None:
            self.use_dns_lookup = use_dns_lookup
        else:
            self.guess_and_set_dns_lookup()

        if use_netinfo_lookup is not None:
            self.use_netinfo_lookup = use_netinfo_lookup
        else:
            self.guess_and_set_use_netinfo_lookup()

        if use_http_code_lookup is not None:
            self.use_http_code_lookup = use_http_code_lookup
        else:
            self.guess_and_set_use_http_code_lookup()

        if use_reputation_lookup is not None:
            self.use_reputation_lookup = use_reputation_lookup
        else:
            self.guess_and_set_use_reputation_lookup()

        if use_whois_db is not None:
            self.use_whois_db = use_whois_db
        else:
            self.guess_and_set_use_whois_db()

        super().__init__(
            subject,
            do_syntax_check_first=do_syntax_check_first,
            db_session=db_session,
            use_collection=use_collection,
        )