| #!/usr/bin/env python3 | |
| 
 | |
| class Colours: | |
|     HEADER = '\033[95m' | |
|     OKBLUE = '\033[94m' | |
|     OKGREEN = '\033[92m' | |
|     WARNING = '\033[93m' | |
|     FAIL = '\033[91m' | |
|     ENDC = '\033[0m' | |
|     BOLD = '\033[1m' | |
|     UNDERLINE = '\033[4m' | |
| 
 | |
| try: | |
|     import os | |
|     import re | |
|     import sys | |
|     import getopt | |
|     import requests | |
|     from clint.textui import progress | |
|     from bs4 import BeautifulSoup | |
| except Exception as err: | |
|     print(Colours.FAIL + "Error: {}".format(err) + Colours.ENDC) | |
| 
 | |
| def Usage(): | |
|     use_msg = ''' | |
| ---------- Usage ----------  | |
| leak-lookup [options] [search term] | |
| ---------------------------  | |
| Options: | |
|     -h: Prints this help message | |
|     -p: Searches haveibeenpwned.com  | |
|     -d: Searches for leaked database | |
| ---------------------------  | |
| ''' | |
|     print(use_msg) | |
| 
 | |
| def DownloadDatabase(url, name): | |
|     try: | |
|         r = requests.get(url, stream=True) | |
|         with open(name, 'wb') as f: | |
|             total_length = int(r.headers.get('content-length')) | |
|             for chunk in progress.bar(r.iter_content(chunk_size=1024), expected_size=(total_length/1024) + 1):  | |
|                 if chunk: | |
|                     f.write(chunk) | |
|                     f.flush() | |
|     except (KeyboardInterrupt, SystemExit, EOFError): | |
|         print(Colours.FAIL + "An error occurred, cleaning up" + Colours.ENDC) | |
|         os.remove(name) | |
| 
 | |
| def DatabaseQuery(database): | |
|     r = requests.get("https://www.databases.today/search-nojs.php?for=" + database) | |
|     if r.reason != "OK": | |
|         print(Colours.FAIL + "Error code: {}".format(r.status_code) + Colours.ENDC) | |
|         sys.exit(1) | |
|     soup = BeautifulSoup(r.text, "html.parser") | |
|     dbs = soup.find(id="myTable").find_all("tr") | |
|     entries = [] | |
|     for table in dbs: | |
|         entry = table.find_all("td") | |
|         if len(entry) != 0: | |
|             entries.append([entry[0].text, entry[4].a.get("href")]) | |
|     print("Which file would you like to download?") | |
|     for index, dllink in enumerate(entries): | |
|         print("{}) {}".format(index + 1, dllink[0])) | |
|     print("a) All") | |
|     print("q) Quit") | |
|     download_choice = input(">> ") | |
|     if download_choice == "q": | |
|         sys.exit(0) | |
|     elif download_choice == "a": | |
|         for x in dllink: | |
|             DownloadDatabase(x[1], x[0]) | |
|     else: | |
|         try: | |
|             download_choice = int(download_choice) - 1 | |
|             DownloadDatabase(dllink[1], dllink[0].split(" (")[0]) | |
|         except: | |
|             print(Colours.FAIL + "Error: Invalid selection" + Colours.ENDC) | |
|             sys.exit(1) | |
| 
 | |
| 
 | |
| def QueryHaveIBeenPwned(email): | |
|     r = requests.post("https://haveibeenpwned.com/", data={"Account": email}) | |
|     if r.reason != "OK": | |
|         print(Colours.FAIL + "Error code: {}".format(r.status_code) + Colours.ENDC) | |
|         sys.exit(1) | |
|     soup = BeautifulSoup(r.text, "html.parser") | |
|     pwnCount = re.match("Pwned on \d+", soup.find(id="pwnCount").text) | |
|     if pwnCount == None: | |
|         print(Colours.OKGREEN + "{} has no public leaks".format(email) + Colours.ENDC) | |
|         return | |
|     print(Colours.FAIL + "{} has {} public leaks avalible".format(email, pwnCount.group().split(" ")[-1]) + Colours.ENDC) | |
|     leaks = [] | |
|     for leak in soup.find_all(class_="pwnedWebsite"): | |
|         leak_name = None | |
|         leak_status = None | |
|         compromised_data = None | |
|         leak_name_html = leak.find(class_="pwnedCompanyTitle") | |
|         if leak_name_html: | |
|             if "(" in leak_name_html.text: | |
|                 leak_name = leak_name_html.text.split("  (")[0] | |
|                 leak_status = leak_name_html.text.split("  (")[1][:-2] | |
|             else: | |
|                 leak_name = leak_name_html.text[:-1] | |
|                 leak_status = None | |
|         compromised_data_html = leak.find(class_="dataClasses") | |
|         if compromised_data_html: | |
|             compromised_data = compromised_data_html.text | |
|         if leak_name: | |
|             leaks.append([leak_name, leak_status, compromised_data]) | |
|     print("\nDownload databases:") | |
|     for index, leak in enumerate(leaks): | |
|         if leak[1] == None: | |
|             print("{}) {}: {}".format(index + 1, leak[0], leak[2])) | |
|         else: | |
|             print("{}) {} ({}): {}".format(index + 1, leak[0], leak[1], leak[2])) | |
|     print("a) Download all") | |
|     print("q) Quit") | |
|     download_choice = input(">> ") | |
|     if download_choice == "q": | |
|         sys.exit(0) | |
|     elif download_choice == "a": | |
|         for leak in leaks: | |
|             DatabaseQuery(leak[0]) | |
|     try: | |
|         download_choice = int(download_choice) - 1 | |
|         DatabaseQuery(leaks[download_choice][0]) | |
|     except: | |
|         print(Colours.FAIL + "Error: Invalid selection" + Colours.ENDC) | |
|         sys.exit(1) | |
| 
 | |
| 
 | |
| def main(): | |
|     if len(sys.argv[1:]) == 0: | |
|         Usage() | |
|         sys.exit(1) | |
|     try: | |
|         options, remainder = getopt.getopt(sys.argv[1:],'hpd',['h', 'p','d',]) | |
|     except getopt.GetoptError as err: | |
|         print(Colours.FAIL + "Error: {}".format(err) + Colours.ENDC) | |
|         sys.exit(1) | |
| 
 | |
|     for opt, arg in options: | |
|         if opt == "-h": | |
|             Usage() | |
|             sys.exit(0) | |
|         elif opt == "-p": | |
|             if len(remainder) == 0: | |
|                 Usage() | |
|                 sys.exit(1) | |
|             QueryHaveIBeenPwned(" ".join(remainder)) | |
|         elif opt == "-d": | |
|             if len(remainder) == 0: | |
|                 Usage() | |
|                 sys.exit(1) | |
|             DatabaseQuery(" ".join(remainder)) | |
| 
 | |
| 
 | |
| if __name__ == "__main__": | |
|     try: | |
|         main() | |
|     except (KeyboardInterrupt, SystemExit, EOFError): | |
|         sys.exit(0)
 |