Merge commit '70a020f9b24f01a52603b0a4e66666ff60650177' as 'utils_v2'

This commit is contained in:
2025-02-28 13:35:55 +05:30
207 changed files with 148037 additions and 0 deletions
+228
View File
@@ -0,0 +1,228 @@
"""
AUTHOR:
Khushal P Soonderji
DATE:
Friday, 12th Jul., 2024
OBJECTIVE:
To provide an easy way to get geolocation information of an IP address.
REFERENCES:
1) https://medium.com/@tubelwj/how-to-retrieve-ip-geolocation-information-in-python-929e15041e3e
DOWNLOADS:
N/A
"""
# *****************************************************************************************************************
# ***** ****
# *** IMPORT ***
# ***** ****
# *****************************************************************************************************************
# To make sibling directories accessible for imports:
import sys
sys.path.append(".")
sys.path.append("..")
# For working with IP Addresses:
import ipaddress
# *****************************************************************************************************************
# ***** ****
# *** MACROS / ONE-TIME INIT ***
# ***** ****
# *****************************************************************************************************************
# --- Nothing Yet
# *****************************************************************************************************************
# ***** ****
# *** VARIABLES ***
# ***** ****
# *****************************************************************************************************************
# --- Nothing Yet
# *****************************************************************************************************************
# ***** ****
# *** FUNCTIONS ***
# ***** ****
# *****************************************************************************************************************
def ipv4_to_int(ip_string):
"""
Converts an IP (v4) string to an integer value.
:param ip_string: The IP address (v4) that you want to convert to integer format.
:return: An integer representation of the IP (v4) address.
"""
ip_numerical = int(ipaddress.IPv4Address(ip_string))
return ip_numerical
# ---------------------------------------------------------------------------------------------------------------------
def int_to_ipv4(ip_numerical):
"""
Interprets the IP (v4) value from the given integer value.
:param ip_numerical: The integer value that represents an IP (v4) address.
:return:
"""
ip_string = str(ipaddress.IPv4Address(ip_numerical))
return ip_string
# ---------------------------------------------------------------------------------------------------------------------
def ipv4_to_bin(ip_string):
"""
Converts an input IP (v4) address to the binary string that represents the 32 bits.
:param ip_string: The IP (v4) string in a format like "192.168.0.1"
:return: The binary representation (as a string) of the input IP address.
"""
ip_binary = bin(int(ipaddress.IPv4Address(ip_string)))[2:].zfill(32)
return ip_binary
# ---------------------------------------------------------------------------------------------------------------------
def bin_to_ipv4(ip_binary):
"""
Interprets the IP (v4) value from the given binary string.
:param ip_binary: The string of 1s and 0s that represents the IP (v4) address.
:return: The IP (v4) address as a string.
"""
ip_string = str(ipaddress.IPv4Address(int(ip_binary, 2)))
return ip_string
# ---------------------------------------------------------------------------------------------------------------------
def get_ipv4_range(ip_string, as_string = True):
"""
Given a network description in the format "88.95.100.128/25", this function tells you the first and last IP
addresses of that network. Useful for determining if an IP address lies in a network.
:param ip_string: The input network description in the format "88.95.100.128/25"
:param as_string: To select between integer and string formats for the IP range output.
:return: The first and last IP addresses of the input network, and the count.
"""
# Extract the components of the string:
ip_components = ip_string.split("/")
ip_addr = ipv4_to_int(ip_components[0])
ip_bits = int(ip_components[1])
# Convert the mask number to binary representation:
ip_mask = (1 << ip_bits) - 1
ip_mask = ip_mask << (32 - ip_bits)
inv_ip_mask = (~ip_mask) & 0xFFFF
# Figure out the start and end IP addresses:
start_ip = ip_addr & ip_mask
end_ip = ip_addr | inv_ip_mask
count = end_ip - start_ip + 1
# If the IPs are needed as strings, we perform the conversion:
if as_string:
start_ip = int_to_ipv4(start_ip)
end_ip = int_to_ipv4(end_ip)
# Done here:
return start_ip, end_ip, count
# ---------------------------------------------------------------------------------------------------------------------
def to_hyphen_notation(value: str) -> str | None:
"""
Takes in an IP pool (range) in either CIDR notation or already in hyphen-separated notation and parses it into the
hyphen-separated notation.
:param value: The IP-range in either of the accepted formats.
:return: The IP range in hyphen-separated notation.
"""
# Let's start by assuming failure:
success = False
start_ip = None
end_ip = None
# Ensure that the input is treated as a string:
value = str(value)
# First we check if the IP has been given in the CIDR notation:
if not success:
try:
# Try to extract the first and last IP addressed from the input:
ip_net = ipaddress.IPv4Network(value, strict = False)
start_ip = ip_net.network_address
end_ip = ip_net.broadcast_address
success = True
# In case the CIDR interpretation doesn't work:
except:
success = False
# Now we try to parse the input string as a hyphen-separated input:
if not success:
try:
# Split at the hyphen and take the parts:
parts = value.split("-")
start_ip = parts[0]
end_ip = parts[1]
success = True
# In case the hyphen-separated interpretation doesn't work:
except:
success = False
# Done here:
value = f"{start_ip}-{end_ip}" if success else None
return value
# *****************************************************************************************************************
# ***** ****
# *** MAIN PROGRAM ***
# ***** ****
# *****************************************************************************************************************
if __name__ == "__main__":
print(ipv4_to_int("255.255.255.255"))
print(ipv4_to_int("x.x.x.x"))