├── Import.sh ├── LICENSE.md ├── Logs ├── DELETE_ME.txt └── importedDBS.log ├── PutYourDataBasesHere └── example.txt ├── README.md ├── data └── DELETE_ME.txt ├── folderPrimer.py ├── pysort.py ├── query.sh ├── run.sh └── search.sh /Import.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #Author Github: https://github.com/g666gle 4 | #Author Twitter: https://twitter.com/g666gle1 5 | #Date: 1/29/2019 6 | #Usage: ./Import 7 | 8 | RED='\033[0;31m' 9 | YELLOW='\033[1;33m' 10 | NC='\033[0m' # No Color 11 | 12 | printf "${RED}[*]${NC} Starting at $(date)\n" 13 | #Checks to see if the user is working out of the BaseQuery directory 14 | if [ "${PWD##*/}" == "BaseQuery" ];then 15 | # Prime the data folder 16 | python3 folderPrimer.py 17 | # Checks to see if the Import directory is there 18 | if [ -d ./PutYourDataBasesHere ];then 19 | dataDir=$(pwd) 20 | # Read each file in the input directory, in sorted order 21 | ls ./PutYourDataBasesHere | sort | while read -r inputfile;do 22 | file_SHA_sum="$(sha256sum "$dataDir"/PutYourDataBasesHere/"$inputfile" | awk '{print$1}')" 23 | # check to see if the database has already been imported 24 | if [ "$(grep "$file_SHA_sum" -c < ./Logs/importedDBS.log)" == "0" ];then 25 | # Call a python script to iterate through the file and sort them 26 | python3 pysort.py "$inputfile" 27 | printf "${YELLOW}[!] Adding $inputfile to importedDBS.log${NC}\n" 28 | echo "$file_SHA_sum" "$(date)" "$inputfile" >> "$dataDir"/Logs/importedDBS.log 29 | echo 30 | else 31 | printf "${YELLOW}[!]${NC} $inputfile SHASUM found in importedDBS.log and is already stored in the data folder\n" 32 | fi 33 | done 34 | 35 | else # If the Import directory doesn't exist 36 | dataDir=$(pwd) 37 | printf "${RED}ERROR: Please make a directory called 'PutYourDataBasesHere' in $dataDir${NC}\n" 38 | fi 39 | else 40 | # If the users working directory is not BaseQuery while trying to run the script 41 | printf "${RED}ERROR: Please change directories to the BaseQuery root directory${NC}\n" 42 | fi 43 | 44 | echo 45 | printf "${RED}[*]${NC} Completed\n" 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright 2019 https://github.com/g666gle 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /Logs/DELETE_ME.txt: -------------------------------------------------------------------------------- 1 | This file is just here so github doesn't delete the directory from the repository -------------------------------------------------------------------------------- /Logs/importedDBS.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jayyogesh/BaseQuery/8a06dd00debf32e5d98d4f271a89cb2f6e8d8425/Logs/importedDBS.log -------------------------------------------------------------------------------- /PutYourDataBasesHere/example.txt: -------------------------------------------------------------------------------- 1 | test@example.com:Password1 2 | admin@example.com:SUperSeCreTPassswrd1 3 | Michael@dundermifflin.com:Sc0tt 4 | Password17:Mark@facebook.com 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BaseQuery 2 | 3 | Solving the problem of having thousands of different files from leaked databases and not an efficient way to store/query them. BaseQuery is an all in one program that 4 | takes the annoyance out of searching through data-breaches. You can find breaches in places such as [RaidForums.com](RAIDFORUMS.com) or [Databases.today](Databases.today). 5 | ### Features Included: 6 | * Calculating the time a file will take to import, before hand 7 | * A 4x nested storage structure 8 | * Average import speeds of 10,000+ entries per second 9 | * Instantaneous querying system 10 | * Email harvesting programs built in 11 | *** 12 | ### Installing 13 | 14 | To Install BaseQuery type the following commands 15 | 16 | ``` 17 | git clone https://github.com/g666gle/BaseQuery.git 18 | sudo chmod 777 -R BaseQuery/ 19 | cd BaseQuery 20 | ./run.sh 21 | ``` 22 | 23 | 24 | ## Getting Started 25 | 1. Place any databases that you have into the "PutYourDataBasesHere" folder 26 | - As of right now, BaseQuery can only accept files in the format where each line is either "test@example.com:password" or "password:test@example.com" 27 | - It doesn't matter if the line formats are mixed up within the same file. Ex) The first line may be "email:password" and the second can be "password:email" 28 | - One entry per line!! 29 | - MAKE SURE THAT YOUR FILES DO NOT HAVE SPACES IN THE NAMES OF THE DATABASE FILES! 30 | - If you need a better visual there is an example.txt file in the folder "PutYourDataBasesHere" 31 | - You should delete the example file before running the program. 32 | 1. Now that you have all of your files in the correct folder 33 | - Open up a terminal 34 | - type './run.sh' if that doesn't work type 'bash run.sh' 35 | 1. Follow the instructions on the screen 36 | - That's it, enjoy! 37 | 38 | *** 39 | ### Prerequisites 40 | 41 | ``` 42 | Python Version 3.6+ 43 | Bash 4.0+ 44 | mmap (sudo pip3 install mmap) 45 | ``` 46 | 47 | 48 | ## Built With 49 | 50 | * Ubuntu 18.04 bionic 51 | 52 | * Bash Version: 53 | GNU bash, version 4.4.19(1)-release (x86_64-pc-linux-gnu) 54 | 55 | * Python Version: 56 | 3.6.7 57 | 58 | ## Authors 59 | 60 | * **G666gle** - *All work* - [(Github)](https://github.com/G666gle) [(Twitter)](https://twitter.com/g666gle1) 61 | 62 | 63 | ## License 64 | 65 | This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details 66 | 67 | ### DISCLAIMER: 68 | 69 | * READ UP ON YOUR LOCAL LAWS FIRST BEFORE USING THIS PROGRAM. 70 | 71 | 72 | -------------------------------------------------------------------------------- /data/DELETE_ME.txt: -------------------------------------------------------------------------------- 1 | This file is just here so github doesn't delete the directory from the repository -------------------------------------------------------------------------------- /folderPrimer.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import os 3 | import time 4 | 5 | """ 6 | Author Github: https://github.com/g666gle 7 | Author Twitter: https://twitter.com/g666gle1 8 | Date: 1/29/2019 9 | Description: This file creates a triple nested [A-Z] and [0-9] directories so the data from the databases are easily 10 | accessible. The reason to do this before instead of while pysort.py is placing all the files is due to 11 | the fact that creating directories is slightly time consuming and by creating them all at once instead 12 | of on the fly. We can expect to see a small efficiency improvement. Also.... organization 13 | Usage: python3 folderPrimer.py 14 | Version: 1.0.0 15 | Python Version: 3.6.7 16 | """ 17 | 18 | path = os.getcwd() 19 | 20 | 21 | def folder_spam(): 22 | """ 23 | This function creates all the nested files needed to store the data. [A-Z][0-9] 24 | :return: N/A 25 | """ 26 | first_nest = ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't','u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9') 27 | second_nest = ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't','u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9') 28 | third_nest = ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't','u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9') 29 | # Creating the first nesting of the folders 30 | for char in first_nest: 31 | if not os.path.isdir(path + "/data/" + char.strip()): 32 | os.makedirs(path + "/data/" + char.strip()) 33 | # Creating the second nesting of the folders 34 | for char in first_nest: 35 | for char2 in second_nest: 36 | if not os.path.isdir(path + "/data/" + char.strip() + "/" + char2.strip()): 37 | os.makedirs(path + "/data/" + char.strip() + "/" + char2.strip()) 38 | # Creating the third nesting of the folders 39 | for char in first_nest: 40 | for char2 in second_nest: 41 | for char3 in third_nest: 42 | if not os.path.isdir(path + "/data/" + char.strip() + "/" + char2.strip() + "/" + char3.strip()): 43 | os.makedirs(path + "/data/" + char.strip() + "/" + char2.strip() + "/" + char3.strip()) 44 | 45 | 46 | def main(): 47 | GREEN = '\033[0;32m' 48 | YELLOW = '\033[1;33m' 49 | NC = '\033[0m' # No Color 50 | 51 | print() 52 | print(GREEN + "[+]" + NC + "Priming the data directory") 53 | start_time = time.time() 54 | folder_spam() 55 | end_time = time.time() 56 | print(GREEN + "[+]" + NC + " Data directory finished being primed!") 57 | print(YELLOW + "[!]" + NC + " Action took " + str(int(end_time - start_time)) + " seconds") 58 | print() 59 | 60 | main() 61 | -------------------------------------------------------------------------------- /pysort.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import os 3 | import sys 4 | import time 5 | import mmap 6 | 7 | """ 8 | Author Github: https://github.com/g666gle 9 | Author Twitter: https://twitter.com/g666gle1 10 | Date: 1/29/2019 11 | Description: Takes in one file at a time as command line input. processes each line in the file and places the 12 | information into the correct subdirectory of the data folder. 13 | Usage: python3 pysort.py file.txt 14 | Version: 1.0.0 15 | Python Version: 3.6.7 16 | """ 17 | 18 | args = sys.argv 19 | 20 | # TODO fix bug where spaces in import files 21 | # TODO make another log file for usage 22 | # TODO make an option for counting the number of files 23 | # TODO Add zstd to compress the files once all of the files are imported 24 | # TODO Add support for SQL vbull CSV Json 25 | 26 | 27 | # FIXED 28 | # - Bug where password:email files were being imputed as email:password 29 | # - in run.sh fixed and added SimplyEmail as an option for harvesting email addresses 30 | 31 | 32 | def check_duplicate(full_file_path, line): 33 | """ 34 | This function takes in a path to the file and the specific line we want to check for duplicates with. First the file 35 | is checked to make sure it isn't empty, then the file is opened as a binary so we can store the lines as a mmap obj. 36 | Next if the line is a duplicate then False is returned else True 37 | :param full_file_path: Path to the file 38 | :param line: The line being checked 39 | :return: True if the line should be written to the file; else False 40 | """ 41 | # Check to see if the file is not empty 42 | if not os.stat(full_file_path).st_size == 0: 43 | # Open the file as a binary file and store it in a mmap obj 44 | with open(full_file_path, 'rb', 0) as fp, mmap.mmap(fp.fileno(), 0, access=mmap.ACCESS_READ) as s: 45 | # Check to see if the line already exists in the file 46 | if s.find(str.encode(line.strip())) != -1: 47 | return False # string is in file so do not re-write it 48 | return True # string is not in file so write it to the file 49 | return True # Write to the file 50 | 51 | 52 | def place_data(line, path): 53 | """ 54 | This function takes in the line of the current file and the root path to the BaseQuery directory. Checks the format 55 | of the file to make sure each line is in the email:password format. Then determines the depth of the correct characters 56 | ex) ex|ample@gmail.com ---> would result in a depth of 2. Then checking each directory to see if it already exists 57 | the username:password combo is correctly placed into a easy to query file. If a invalid character is determined in the 58 | first 4 chars then it will be put in a '0UTLIERS.txt' file. 59 | :param line: email:password 60 | :param path: full path to file 61 | :return: Either a 1 or a 0 depending on if a line has been written or not 62 | """ 63 | if line[0] == ":": 64 | line = line[1:] 65 | emailPaswd = line.split(':', 2) 66 | 67 | # Checks to see if the users format is "Password:Username" instead of "Username:Password" 68 | if len(emailPaswd) >= 2 and '@' in emailPaswd[1] and '.' in emailPaswd[1]: 69 | # Switches the position of the username and password 70 | temp = emailPaswd[0] 71 | emailPaswd[0] = emailPaswd[1].lower() 72 | emailPaswd[1] = temp 73 | else: 74 | # Change all of the email usernames to be lowercase; to be uniform 75 | emailPaswd[0] = emailPaswd[0].lower() 76 | 77 | try: 78 | # check to see if you have a valid email address and the username is >= 4; also checks if there is a '@' in the username 79 | if '@' in emailPaswd[0].strip() and len(emailPaswd[0].strip().split('@')[0]) >= 4 and len(emailPaswd) >= 2 and emailPaswd[0].strip().count('@') == 1: 80 | first_letter = emailPaswd[0][0] 81 | second_letter = emailPaswd[0][1] 82 | third_letter = emailPaswd[0][2] 83 | fourth_letter = emailPaswd[0][3] 84 | 85 | # Check to see if the username has an invalid character and at what spot 86 | if str(first_letter).isalnum(): 87 | folder_depth = 1 88 | if str(second_letter).isalnum(): 89 | folder_depth = 2 90 | if str(third_letter).isalnum(): 91 | folder_depth = 3 92 | if str(fourth_letter).isalnum(): 93 | folder_depth = 4 94 | else: 95 | folder_depth = 0 96 | 97 | 98 | # Check to see if the first letter doesn't have a directory 99 | if not os.path.isdir(path + "/data/" + first_letter): 100 | # Check to see if we start with at least one valid char 101 | if folder_depth >= 1: 102 | # Make the directory 103 | os.makedirs(path + "/data/" + first_letter) 104 | else: 105 | # If the outlier dir doesn't exist; make it and start the file 106 | if not os.path.isdir(path + "/data/0UTLIERS"): 107 | os.makedirs(path + "/data/0UTLIERS") 108 | # Don't need to check for duplicates because its a new file 109 | with open(path + "/data/0UTLIERS/0utliers.txt", 'a') as fp: 110 | length = len(emailPaswd) 111 | # Iterate through each index of the list and write it to the file 112 | for index in range(length): 113 | if index != length - 1: 114 | fp.write(emailPaswd[index] + ":") 115 | else: # Don't add a ':' at the end of the line 116 | fp.write(emailPaswd[index]) 117 | fp.write("\n") 118 | return 1 119 | else: # If the outlier dir already exists append the line to the file 120 | if check_duplicate(path + "/data/0UTLIERS/0utliers.txt", line): 121 | # Checks to see if there are duplicates already in the file, returns true if there isn't 122 | with open(path + "/data/0UTLIERS/0utliers.txt", 'a') as fp: 123 | length = len(emailPaswd) 124 | # Iterate through each index of the list and write it to the file 125 | for index in range(length): 126 | if index != length - 1: 127 | fp.write(emailPaswd[index] + ":") 128 | else: # Don't add a ':' at the end of the line 129 | fp.write(emailPaswd[index]) 130 | fp.write("\n") 131 | return 1 132 | return 0 133 | else: # The directory already exists 134 | if folder_depth == 0: # There is not at least one consecutive valid char 135 | # If the outlier dir doesn't exist; make it and start the file 136 | if not os.path.isdir(path + "/data/0UTLIERS"): 137 | os.makedirs("mkdir " + path + "/data/0UTLIERS") 138 | with open(path + "/data/0UTLIERS/0utliers.txt", 'a') as fp: 139 | length = len(emailPaswd) 140 | # Iterate through each index of the list and write it to the file 141 | for index in range(length): 142 | if index != length - 1: 143 | fp.write(emailPaswd[index] + ":") 144 | else: # Don't add a ':' at the end of the line 145 | fp.write(emailPaswd[index]) 146 | fp.write("\n") 147 | return 1 148 | else: # If the outlier dir already exists append the line to the file 149 | if check_duplicate(path + "/data/0UTLIERS/0utliers.txt", line): 150 | with open(path + "/data/0UTLIERS/0utliers.txt", 'a') as fp: 151 | length = len(emailPaswd) 152 | # Iterate through each index of the list and write it to the file 153 | for index in range(length): 154 | if index != length - 1: 155 | fp.write(emailPaswd[index] + ":") 156 | else: # Don't add a ':' at the end of the line 157 | fp.write(emailPaswd[index]) 158 | fp.write("\n") 159 | return 1 160 | return 0 161 | 162 | # Check to see if the second letter doesn't have a directory 163 | if not os.path.isdir(path + "/data/" + first_letter + "/" + second_letter): 164 | # Check to see if we start with at least two valid char 165 | if folder_depth >= 2: 166 | # Make the directory 167 | os.makedirs(path + "/data/" + first_letter + "/" + second_letter) 168 | else: 169 | # If the outlier dir doesn't exist; make it and start the file 170 | if not os.path.isdir(path + "/data/" + first_letter + "/0UTLIERS"): 171 | os.makedirs(path + "/data/" + first_letter + "/0UTLIERS") 172 | with open(path + "/data/" + first_letter + "/0UTLIERS/0utliers.txt", 'a') as fp: 173 | length = len(emailPaswd) 174 | # Iterate through each index of the list and write it to the file 175 | for index in range(length): 176 | if index != length - 1: 177 | fp.write(emailPaswd[index] + ":") 178 | else: # Don't add a ':' at the end of the line 179 | fp.write(emailPaswd[index]) 180 | fp.write("\n") 181 | return 1 182 | else: 183 | # Check for duplicates 184 | if check_duplicate(path + "/data/" + first_letter + "/0UTLIERS/0utliers.txt", line): 185 | with open(path + "/data/" + first_letter + "/0UTLIERS/0utliers.txt", 'a') as fp: 186 | length = len(emailPaswd) 187 | # Iterate through each index of the list and write it to the file 188 | for index in range(length): 189 | if index != length - 1: 190 | fp.write(emailPaswd[index] + ":") 191 | else: # Don't add a ':' at the end of the line 192 | fp.write(emailPaswd[index]) 193 | fp.write("\n") 194 | return 1 195 | return 0 196 | else: # The directory already exists 197 | if folder_depth <= 1: # There is not at least two consecutive valid char 198 | # If the outlier dir doesn't exist; make it and start the file 199 | if not os.path.isdir(path + "/data/" + first_letter + "/0UTLIERS"): 200 | os.makedirs(path + "/data/" + first_letter + "/0UTLIERS") 201 | with open(path + "/data/" + first_letter + "/0UTLIERS/0utliers.txt", 'a') as fp: 202 | length = len(emailPaswd) 203 | # Iterate through each index of the list and write it to the file 204 | for index in range(length): 205 | if index != length - 1: 206 | fp.write(emailPaswd[index] + ":") 207 | else: # Don't add a ':' at the end of the line 208 | fp.write(emailPaswd[index]) 209 | fp.write("\n") 210 | return 1 211 | else: # If the outlier dir already exists append the line to the file 212 | if check_duplicate(path + "/data/" + first_letter + "/0UTLIERS/0utliers.txt", line): 213 | with open(path + "/data/" + first_letter + "/0UTLIERS/0utliers.txt", 'a') as fp: 214 | length = len(emailPaswd) 215 | # Iterate through each index of the list and write it to the file 216 | for index in range(length): 217 | if index != length - 1: 218 | fp.write(emailPaswd[index] + ":") 219 | else: # Don't add a ':' at the end of the line 220 | fp.write(emailPaswd[index]) 221 | fp.write("\n") 222 | return 1 223 | return 0 224 | 225 | # Check to see if the third letter doesn't have a directory 226 | if not os.path.isdir(path + "/data/" + first_letter + "/" + second_letter + "/" + third_letter): 227 | # Check to see if we start with at least three valid char 228 | if folder_depth >= 3: 229 | # Make the directory 230 | os.makedirs(path + "/data/" + first_letter + "/" + second_letter + "/" + third_letter) 231 | else: 232 | if not os.path.isdir(path + "/data/" + first_letter + "/" + second_letter + "/0UTLIERS"): 233 | os.makedirs(path + "/data/" + first_letter + "/" + second_letter + "/0UTLIERS") 234 | with open(path + "/data/" + first_letter + "/" + second_letter + "/0UTLIERS/0utliers.txt", 'a') as fp: 235 | length = len(emailPaswd) 236 | # Iterate through each index of the list and write it to the file 237 | for index in range(length): 238 | if index != length - 1: 239 | fp.write(emailPaswd[index] + ":") 240 | else: # Don't add a ':' at the end of the line 241 | fp.write(emailPaswd[index]) 242 | fp.write("\n") 243 | return 1 244 | else: # If the outlier dir already exists append the line to the file 245 | if check_duplicate(path + "/data/" + first_letter + "/" + second_letter + "/0UTLIERS/0utliers.txt", line): 246 | with open(path + "/data/" + first_letter + "/" + second_letter + "/0UTLIERS/0utliers.txt", 'a') as fp: 247 | length = len(emailPaswd) 248 | # Iterate through each index of the list and write it to the file 249 | for index in range(length): 250 | if index != length - 1: 251 | fp.write(emailPaswd[index] + ":") 252 | else: # Don't add a ':' at the end of the line 253 | fp.write(emailPaswd[index]) 254 | fp.write("\n") 255 | return 1 256 | return 0 257 | else: # The directory already exists 258 | if folder_depth <= 2: # There is not at least three consecutive valid char 259 | # If the outlier dir doesn't exist; make it and start the file 260 | if not os.path.isdir(path + "/data/" + first_letter + "/" + second_letter + "/0UTLIERS"): 261 | os.makedirs(path + "/data/" + first_letter + "/" + second_letter + "/0UTLIERS") 262 | with open(path + "/data/" + first_letter + "/" + second_letter + "/0UTLIERS/0utliers.txt", 'a') as fp: 263 | length = len(emailPaswd) 264 | # Iterate through each index of the list and write it to the file 265 | for index in range(length): 266 | if index != length - 1: 267 | fp.write(emailPaswd[index] + ":") 268 | else: # Don't add a ':' at the end of the line 269 | fp.write(emailPaswd[index]) 270 | fp.write("\n") 271 | return 1 272 | else: # If the outlier dir already exists append the line to the file 273 | if check_duplicate(path + "/data/" + first_letter + "/" + second_letter + "/0UTLIERS/0utliers.txt", line): 274 | with open(path + "/data/" + first_letter + "/" + second_letter + "/0UTLIERS/0utliers.txt", 'a') as fp: 275 | length = len(emailPaswd) 276 | # Iterate through each index of the list and write it to the file 277 | for index in range(length): 278 | if index != length - 1: 279 | fp.write(emailPaswd[index] + ":") 280 | else: # Don't add a ':' at the end of the line 281 | fp.write(emailPaswd[index]) 282 | fp.write("\n") 283 | return 1 284 | return 0 285 | 286 | # Checks to see if the file in the third directory doesn't exists 287 | if not os.path.isfile(path + "/data/" + first_letter + "/" + second_letter + "/" + third_letter + "/" + fourth_letter + ".txt"): 288 | if folder_depth == 4: # The file doesn't exist in the third dir but there is 4 valid chars 289 | # Make the file 290 | with open(path + "/data/" + first_letter + "/" + second_letter + "/" + third_letter + "/" + fourth_letter + ".txt", 'a') as output_file: 291 | length = len(emailPaswd) 292 | # Iterate through each index of the list and write it to the file 293 | for index in range(length): 294 | if index != length-1: 295 | output_file.write(emailPaswd[index] + ":") 296 | else: # Don't add a ':' at the end of the line 297 | output_file.write(emailPaswd[index]) 298 | output_file.write("\n") 299 | return 1 300 | elif folder_depth == 3: # Check to see if the fourth letter is an outlier EX) exa!mple@example.com 301 | if not os.path.isdir(path + "/data/" + first_letter + "/" + second_letter + "/" + third_letter + "/0UTLIERS"): 302 | os.makedirs(path + "/data/" + first_letter + "/" + second_letter + "/" + third_letter + "/0UTLIERS") 303 | # Make the 0UTLIERS file 304 | with open(path + "/data/" + first_letter + "/" + second_letter + "/" + third_letter + "/0UTLIERS/0utliers.txt", 'a') as output_file: 305 | if check_duplicate(path + "/data/" + first_letter + "/" + second_letter + "/" + third_letter + "/0UTLIERS/0utliers.txt", line): 306 | length = len(emailPaswd) 307 | # Iterate through each index of the list and write it to the file 308 | for index in range(length): 309 | if index != length - 1: 310 | output_file.write(emailPaswd[index] + ":") 311 | else: # Dont add a ':' at the end of the line 312 | output_file.write(emailPaswd[index]) 313 | output_file.write("\n") 314 | return 1 315 | return 0 316 | else: # The file exists 317 | if folder_depth == 4: # The file does exist in the third dir but there is 4 valid chars 318 | if check_duplicate(path + "/data/" + first_letter + "/" + second_letter + "/" + third_letter + "/" + fourth_letter + ".txt", line): 319 | # Append the file 320 | with open(path + "/data/" + first_letter + "/" + second_letter + "/" + third_letter + "/" + fourth_letter + ".txt", 'a') as output_file: 321 | length = len(emailPaswd) 322 | # Iterate through each index of the list and write it to the file 323 | for index in range(length): 324 | if index != length - 1: 325 | output_file.write(emailPaswd[index] + ":") 326 | else: # Dont add a ':' at the end of the line 327 | output_file.write(emailPaswd[index]) 328 | output_file.write("\n") 329 | return 1 330 | return 0 331 | elif folder_depth == 3: # The file does exist in the third dir but there is only 3 valid chars 332 | # Check to see if you need to make the 0UTLIERS dir 333 | if not os.path.isdir(path + "/data/" + first_letter + "/" + second_letter + "/" + third_letter + "/0UTLIERS"): 334 | os.makedirs(path + "/data/" + first_letter + "/" + second_letter + "/" + third_letter + "/0UTLIERS") 335 | # Check for duplicates and then write to the file 336 | if check_duplicate(path + "/data/" + first_letter + "/" + second_letter + "/" + third_letter + "/0UTLIERS/0utliers.txt", line): 337 | # Append the 0UTLIERS file 338 | with open(path + "/data/" + first_letter + "/" + second_letter + "/" + third_letter + "/0UTLIERS/0utliers.txt", 'a') as output_file: 339 | length = len(emailPaswd) 340 | # Iterate through each index of the list and write it to the file 341 | for index in range(length): 342 | if index != length - 1: 343 | output_file.write(emailPaswd[index] + ":") 344 | else: # Dont add a ':' at the end of the line 345 | output_file.write(emailPaswd[index]) 346 | output_file.write("\n") 347 | return 1 348 | return 0 349 | 350 | # NOT a valid email address or the username is NOT >= 4; or there is more than one '@' in the username 351 | else: 352 | if not os.path.isdir(path + "/data/NOTVALID"): 353 | os.makedirs(path + "/data/NOTVALID/") 354 | with open(path + "/data/NOTVALID/FAILED_TEST.txt", 'a') as fp: 355 | length = len(emailPaswd) 356 | # Iterate through each index of the list and write it to the file 357 | for index in range(length): 358 | if index != length - 1: 359 | fp.write(emailPaswd[index] + ":") 360 | else: # Don't add a ':' at the end of the line 361 | fp.write(emailPaswd[index]) 362 | fp.write("\n") 363 | return 1 364 | else: # The directory already exists 365 | if line != "": 366 | if check_duplicate(path + "/data/NOTVALID/FAILED_TEST.txt", line): 367 | # Open the file; check if it's a duplicate and write to the file 368 | with open(path + "/data/NOTVALID/FAILED_TEST.txt", 'a') as fp: 369 | length = len(emailPaswd) 370 | # Iterate through each index of the list and write it to the file 371 | for index in range(length): 372 | if index != length - 1: 373 | fp.write(emailPaswd[index] + ":") 374 | else: # Don't add a ':' at the end of the line 375 | fp.write(emailPaswd[index]) 376 | fp.write("\n") 377 | return 1 378 | return 0 379 | except OSError: 380 | raise 381 | return 0 382 | 383 | 384 | def main(): 385 | start_time = time.time() 386 | total_lines = 0 # The amount of lines that are not white-space 387 | written_lines = 0 # The amount of lines written 388 | 389 | RED = '\033[0;31m' 390 | GREEN = '\033[0;32m' 391 | YELLOW = '\033[1;33m' 392 | NC = '\033[0m' # No Color 393 | 394 | # Check to see if the arguments are correct 395 | if len(args) == 2 and args[1] != "": 396 | path = os.getcwd() 397 | print(GREEN + "[+]" + NC + " Attempting to open file " + GREEN + args[1] + NC) 398 | # Directory guaranteed to exist from previous check in Import.sh 399 | with open(path + "/PutYourDataBasesHere/" + args[1], 'r') as fp: 400 | try: 401 | for line in fp: 402 | if total_lines % 10000 == 0 and total_lines != 0: 403 | print(GREEN + "[+]" + NC + " Processing line number: " + str(total_lines) + "\nLine: " + line) 404 | if line.strip() != "": 405 | written_lines += place_data(line.strip(), path) 406 | total_lines += 1 407 | except Exception as e: 408 | print(RED + "Exception: " + str(e) + NC) 409 | else: 410 | print(YELLOW + "[!]" + NC + " Invalid arguments provided") 411 | stop_time = time.time() 412 | print() 413 | print(GREEN + "[+]" + NC + " Total time: " + str(("%.2f" % (stop_time - start_time)) + " seconds")) 414 | print(GREEN + "[+]" + NC + " Total lines: " + str(("%.2f" % total_lines))) 415 | print(GREEN + "[+]" + NC + " Written lines: " + str(("%.2f" % written_lines))) 416 | 417 | 418 | main() 419 | -------------------------------------------------------------------------------- /query.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #Author Github: https://github.com/g666gle 4 | #Author Twitter: https://twitter.com/g666gle1 5 | #Date: 1/29/2019 6 | #Usage: ./query test@example.com 7 | 8 | RED='\033[0;31m' 9 | YELLOW='\033[1;33m' 10 | NC='\033[0m' # No Color 11 | 12 | # Checks to see if the user forgot to enter input 13 | if [ $# -eq 1 ];then 14 | if [ "${PWD##*/}" == "BaseQuery" ];then 15 | if ! [ -e "$1" ];then 16 | ./search.sh "$1" 17 | else 18 | # A file was inputed 19 | cat "$1" | while read -r email;do 20 | echo 21 | ./search.sh "$email" 22 | done 23 | fi 24 | else 25 | printf "${RED}ERROR: Please change directories to the BaseQuery root directory${NC}\n" 26 | fi 27 | else 28 | printf "${YELLOW}[!]${NC} Please enter one email address or a file with one email address per line\n" 29 | fi 30 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #Author Github: https://github.com/g666gle 4 | #Author Twitter: https://twitter.com/g666gle1 5 | #Date: 1/29/2019 6 | #Usage: ./run.sh 7 | 8 | RED='\033[0;31m' 9 | GREEN='\033[0;32m' 10 | YELLOW='\033[1;33m' 11 | NC='\033[0m' # No Color 12 | 13 | clear 14 | echo " _ _ _ _ _ _ _ _ _ _ " 15 | echo " / /\ / /\ / /\ /\ \ /\ \ /\_\ /\ \ /\ \ /\ \ /\_\ " 16 | echo " / / \ / / \ / / \ / \ \ / \ \ / / / _ / \ \ / \ \\\\ \ \ / / / " 17 | echo " / / /\ \ / / /\ \ / / /\ \__ / /\ \ \ / /\ \ \ \ \ \__ /\_\ / /\ \ \ / /\ \ \\\\ \ \_/ / / " 18 | echo " / / /\ \ \ / / /\ \ \ / / /\ \___\ / / /\ \_\ / / /\ \ \ \ \___\ / / // / /\ \_\ / / /\ \_\\\\ \___/ / " 19 | echo " / / /\ \_\ \ / / / \ \ \ \ \ \ \/___// /_/_ \/_/ / / / \ \_\ \__ / / / // /_/_ \/_/ / / /_/ / / \ \ \_/ " 20 | echo " / / /\ \ \___\ / / /___/ /\ \ \ \ \ / /____/\ / / / _ / / / / / / / / // /____/\ / / /__\/ / \ \ \ " 21 | echo " / / / \ \ \__/ / / /_____/ /\ \ _ \ \ \ / /\____\/ / / / /\ \/ / / / / / / // /\____\/ / / /_____/ \ \ \ " 22 | echo " / / /____\_\ \ / /_________/\ \ \ /_/\__/ / / / / /______ / / /__\ \ \/ / / /___/ / // / /______ / / /\ \ \ \ \ \ " 23 | echo " / / /__________\/ / /_ __\ \_\\\\ \/___/ / / / /_______\ / / /____\ \ \/ / /____\/ // / /_______\/ / / \ \ \ \ \_\ " 24 | echo " \/_____________/\_\___\ /____/_/ \_____\/ \/__________/ \/________\_\/\/_________/ \/__________/\/_/ \_\/ \/_/ " 25 | echo 26 | 27 | while true;do 28 | echo 29 | echo "Options:" 30 | echo " [1] Import Your data" 31 | echo " [2] Calculate Import Time" 32 | echo " [3] Query" 33 | echo " [4] Harvest Email Addresses" 34 | echo " [5] Message" 35 | echo " [Q] Quit" 36 | echo 37 | read -p "Option Number-> " answer 38 | 39 | # Check to see if the answer is only letters 40 | if [[ "$answer" =~ ^[a-zA-Z]+$ ]];then 41 | if [[ "$answer" == [Qq] ]];then 42 | clear 43 | exit 44 | fi 45 | 46 | # Check to see if the answer is only numbers 47 | elif [[ "$answer" =~ ^[0-9]+$ ]];then 48 | 49 | if [ "$answer" -eq 1 ];then 50 | if [ "${PWD##*/}" == "BaseQuery" ];then 51 | ./Import.sh 52 | echo 53 | else 54 | printf "${RED}ERROR: Please change directories to the BaseQuery root directory${NC}\n" 55 | fi 56 | 57 | elif [ "$answer" -eq 2 ];then 58 | echo 59 | echo "Please enter the number of lines you wish to import..." 60 | read -p "> " num_lines 61 | if [[ "$num_lines" =~ ^[0-9]+$ ]];then 62 | # 10114 is about the number of lines processed in one second on average 63 | secs=$(echo "$num_lines/10114" | bc -l) 64 | mins=$(echo "$secs/60" | bc -l) 65 | hours=$(echo "$mins/60" | bc -l) 66 | days=$(echo "$hours/24" | bc -l) 67 | years=$(echo "$days/365" | bc -l) 68 | printf "The import time should take ABOUT %0.2f seconds which is...\n" "$secs" 69 | printf " %0.2f minutes which is...\n" "$mins" 70 | printf " %0.2f hours which is...\n" "$hours" 71 | printf " %0.2f days\n" "$days" 72 | printf " %0.2f years\n" "$years" 73 | else 74 | printf "${YELLOW}[!]${NC} Invalid input\n" 75 | fi 76 | echo 77 | 78 | elif [ "$answer" -eq 3 ];then 79 | if [ "${PWD##*/}" == "BaseQuery" ];then 80 | echo 81 | printf "Please enter an email address or the full path to a file with one email per line. \n" 82 | printf " ex) test@example.com\n" 83 | printf " ex) /home/user/Desktop/email_list.txt\n\n" 84 | read -p "> " email 85 | ./query.sh "$email" 86 | echo 87 | else 88 | printf "${RED}ERROR: Please change directories to the BaseQuery root directory${NC}\n" 89 | fi 90 | 91 | elif [ "$answer" -eq 4 ];then 92 | if [ "${PWD##*/}" == "BaseQuery" ];then 93 | echo 94 | echo "Quick Search (1) or In-depth Search (2)? (Enter 1 or 2)" 95 | read -p "> " preference 96 | if [[ "$preference" =~ ^[0-9]+$ ]];then 97 | if [ "$preference" -eq 1 ];then 98 | printf "${GREEN}Code taken from https://github.com/laramies/theHarvester${NC}\n" 99 | printf "${GREEN} Go check him out${NC}\n" 100 | if ! [ -d ./theHarvester ];then 101 | printf "${YELLOW}[!]${NC} Installing theHarvester\n" 102 | git clone https://github.com/laramies/theHarvester.git &> /dev/null 103 | fi 104 | printf "${YELLOW}[!]${NC} Checking requirements\n" 105 | python3 -m pip install -r requirements.txt &> /dev/null 106 | if [ "$( pip3 freeze | grep -c numpy )" -eq 0 ];then 107 | printf "${YELLOW}[!]${NC} Installing additional dependencies\n" 108 | pip3 install numpy &> /dev/null 109 | fi 110 | printf "${YELLOW}[!] PLACE ANY API KEYS IN $(pwd)/theHarvester/api-keys.yaml${NC}\n" 111 | echo "Domain name? ex) google.com" 112 | read -p "> " domain 113 | echo "Limit for the amount of email addresses? ex) 500" 114 | read -p "> " limit 115 | printf " 116 | ${RED}source:${NC} baidu, bing, bingapi, censys, crtsh, cymon, 117 | dogpile, duckduckgo, google, googleCSE, google- 118 | certificates, google-profiles, hunter, intelx, 119 | linkedin, netcraft, pgp, securityTrails, threatcrowd, 120 | trello, twitter, vhost, virustotal, yahoo, all\n" 121 | echo 122 | echo "Source? ex) all" 123 | read -p "> " source 124 | cd ./theHarvester 125 | python3 ./theHarvester.py -d "$domain" -l "$limit" -b "$source" 126 | cd .. 127 | echo 128 | printf "${RED}COPY ONLY THE EMAIL ADDRESSES AND SAVE THEM TO A .TXT FILE${NC}\n" 129 | printf "${RED}YOU CAN USE THE TEXT FILE AS INPUT TO QUERY ALL OF THEM AT ONCE${NC}\n" 130 | echo 131 | 132 | elif [ "$preference" -eq 2 ];then 133 | printf "${YELLOW}[!]${NC} Checking if Python 2 is installed\n" 134 | sudo apt-get install python -y &> /dev/null 135 | sudo apt-get install curl -y &> /dev/null 136 | pip install dns.resolver &> /dev/null 137 | 138 | # Checking to see if the SimplyEmail directory is already there 139 | if ! [ -d ./SimplyEmail ];then 140 | printf "${YELLOW}[!]${NC} Installing SimplyEmail\n" 141 | curl -s https://raw.githubusercontent.com/killswitch-GUI/SimplyEmail/master/setup/oneline-setup.sh | bash &> /dev/null 142 | fi 143 | 144 | # Checking to see if curl and python-magic are already installed 145 | 146 | if [ "$( pip freeze | grep -c python-magic )" -eq 0 ];then 147 | printf "${YELLOW}[!]${NC} Installing additional dependencies\n" 148 | pip install python-magic &> /dev/null 149 | fi 150 | if [ "$( pip freeze | grep -c fake_useragent )" -eq 0 ];then 151 | printf "${YELLOW}[!]${NC} Installing additional dependencies\n" 152 | pip install fake_useragent &> /dev/null 153 | fi 154 | 155 | echo "Domain name? ex) google.com" 156 | read -p "> " domain 157 | cd ./SimplyEmail 158 | echo $(pwd) 159 | python SimplyEmail.py -all -v -e $domain 160 | echo python SimplyEmail.py -all -e $domain 161 | cd .. 162 | fi # Checking if answer equals 1 or 2 163 | fi # Cheking if answer is numeric 164 | else 165 | printf "${RED}ERROR: Please change directories to the BaseQuery root directory${NC}\n" 166 | fi # Checking proper directory 167 | 168 | elif [ "$answer" -eq 5 ];then 169 | echo 170 | echo "Hey... thanks for downloading Base Query, I've spent way too many hours coding this" 171 | echo "Base Query is a great program to help you organize and query all those pesky databases you have laying around" 172 | echo "With a tripple nested structure and a careful design your querys should be INSTANTANEOUS! Or ya know like really fast." 173 | echo "Something broken? Check the logs and then message me!" 174 | echo "For more information regarding use check the README file" 175 | echo "Found a bug? Just want to talk? Message me on GitHub or Twitter https://github.com/g666gle" 176 | echo " https://twitter.com/g666gle1" 177 | echo " V1.0" 178 | echo 179 | 180 | fi 181 | 182 | fi 183 | read -sp "Press Enter to continue..." 184 | clear 185 | 186 | done 187 | -------------------------------------------------------------------------------- /search.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #Author Github: https://github.com/g666gle 4 | #Author Twitter: https://twitter.com/g666gle1 5 | #Date: 1/29/2019 6 | #Usage: N/A 7 | 8 | RED='\033[0;31m' 9 | GREEN='\033[0;32m' 10 | YELLOW='\033[1;33m' 11 | NC='\033[0m' # No Color 12 | 13 | if [ "${PWD##*/}" == "BaseQuery" ];then 14 | # Grab everything before the @ sign 15 | user_name=$(echo "$1" | cut -d @ -f 1 | awk '{print tolower($0)}') 16 | email=$(echo "$1" | cut -d : -f 1 | awk '{print tolower($0)}') 17 | # Check to make sure the user name is at least 4 and the email has a @ 18 | if [ ${#user_name} -ge 4 ] && [[ $email == *"@"* ]];then 19 | # Grab each individual character 20 | first_char=${user_name:0:1} # {variable name: starting position : how many letters} 21 | second_char=${user_name:1:1} 22 | third_char=${user_name:2:1} 23 | fourth_char=${user_name:3:1} 24 | 25 | # Check the first directory 26 | if [ -d ./data/"$first_char" ];then 27 | # Check the second directory 28 | if [ -d ./data/"$first_char"/"$second_char" ];then 29 | # Check the third directory 30 | if [ -d ./data/"$first_char"/"$second_char"/"$third_char" ];then 31 | printf "${GREEN}Email Address: $email${NC}\n" 32 | # Check to see if the file exists 33 | if [ -e ./data/"$first_char"/"$second_char"/"$third_char"/"$fourth_char".txt ];then 34 | # Open the file and search for the email address then only keep the passwords, iterate through the passwords and echo then 35 | cat ./data/"$first_char"/"$second_char"/"$third_char"/"$fourth_char".txt | grep -i "$email" | cut -d : -f 2- | while read -r Password;do 36 | printf "Password: ${RED}$Password${NC}\n" 37 | done 38 | 39 | # Check to see if the email is in the NOT VALID file 40 | if [[ -d ./data/NOTVALID && -e ./data/NOTVALID/FAILED_TEST.txt ]];then 41 | cat ./data/NOTVALID/FAILED_TEST.txt | grep -i "$email" | cut -d : -f 2- | while read -r Password;do 42 | printf "Password: ${RED}$Password${NC}\n" 43 | done 44 | fi 45 | else 46 | printf "${GREEN}Email Address: $email${NC}\n" 47 | # The file does not exists 48 | # Check to make sure the directory exists and the file exists for 0UTLIERS 49 | if [[ -d ./data/$first_char/$second_char/$third_char/0UTLIERS && -e ./data/$first_char/$second_char/$third_char/0UTLIERS/0utliers.txt ]];then 50 | cat ./data/"$first_char"/"$second_char"/"$third_char"/0UTLIERS/0utliers.txt | grep -i "$email" | cut -d : -f 2- | while read -r Password;do 51 | printf "Password: ${RED}$Password${NC}\n" 52 | done 53 | fi 54 | 55 | # Check to see if the email is in the NOT VALID file 56 | if [[ -d ./data/NOTVALID && -e ./data/NOTVALID/FAILED_TEST.txt ]];then 57 | cat ./data/NOTVALID/FAILED_TEST.txt | grep -i "$email" | cut -d : -f 2- | while read -r Password;do 58 | printf "Password: ${RED}$Password${NC}\n" 59 | done 60 | fi 61 | fi 62 | else 63 | printf "${GREEN}Email Address: $email${NC}\n" 64 | # The third letter directory does not exists 65 | if [[ -d ./data/$first_char/$second_char/0UTLIERS && -e ./data/$first_char/$second_char/0UTLIERS/0utliers.txt ]];then 66 | cat ./data/"$first_char"/"$second_char"/0UTLIERS/0utliers.txt | grep -i "$email" | cut -d : -f 2- | while read -r Password;do 67 | printf "Password: ${RED}$Password${NC}\n" 68 | done 69 | fi 70 | 71 | # Check to see if the email is in the NOT VALID file 72 | if [[ -d ./data/NOTVALID && -e ./data/NOTVALID/FAILED_TEST.txt ]];then 73 | cat ./data/NOTVALID/FAILED_TEST.txt | grep -i "$email" | cut -d : -f 2- | while read -r Password;do 74 | printf "Password: ${RED}$Password${NC}\n" 75 | done 76 | fi 77 | fi 78 | else 79 | printf "${GREEN}Email Address: $email${NC}\n" 80 | # The second letter directory does not exists 81 | if [[ -d ./data/$first_char/0UTLIERS && -e ./data/$first_char/0UTLIERS/0utliers.txt ]];then 82 | cat ./data/"$first_char"/0UTLIERS/0utliers.txt | grep -i "$email" | cut -d : -f 2- | while read -r Password;do 83 | printf "Password: ${RED}$Password${NC}\n" 84 | done 85 | fi 86 | 87 | # Check to see if the email is in the NOT VALID file 88 | if [[ -d ./data/NOTVALID && -e ./data/NOTVALID/FAILED_TEST.txt ]];then 89 | cat ./data/NOTVALID/FAILED_TEST.txt | grep -i "$email" | cut -d : -f 2- | while read -r Password;do 90 | printf "Password: ${RED}$Password${NC}\n" 91 | done 92 | fi 93 | fi 94 | else 95 | printf "${GREEN}Email Address: $email${NC}\n" 96 | # The first letter directory does not exists 97 | if [[ -d ./data/0UTLIERS && -e ./data/0UTLIERS/0utliers.txt ]];then 98 | cat ./data/0UTLIERS/0utliers.txt | grep -i "$email" | cut -d : -f 2- | while read -r Password;do 99 | printf "Password: ${RED}$Password${NC}\n" 100 | done 101 | fi 102 | 103 | # Check to see if the email is in the NOT VALID file 104 | if [[ -d ./data/NOTVALID && -e ./data/NOTVALID/FAILED_TEST.txt ]];then 105 | cat ./data/NOTVALID/FAILED_TEST.txt | grep -i "$email" | cut -d : -f 2- | while read -r Password;do 106 | printf "Password: ${RED}$Password${NC}\n" 107 | done 108 | fi 109 | fi 110 | else 111 | printf "${GREEN}Email Address: $email${NC}\n" 112 | if [[ $email == *"@"* ]];then 113 | # The username is either not >= 4 or the email doesn't contain an @ 114 | # Check to see if the email is in the NOT VALID file 115 | if [[ -d ./data/NOTVALID && -e ./data/NOTVALID/FAILED_TEST.txt ]];then 116 | cat ./data/NOTVALID/FAILED_TEST.txt | grep -i "^$email" | cut -d : -f 2- | while read -r Password;do 117 | printf "Password: ${RED}$Password${NC}\n" 118 | done 119 | fi 120 | else 121 | printf "${YELLOW}[!]${NC} Please enter one email address or a file with one email address per line\n" 122 | fi 123 | fi 124 | 125 | else 126 | printf "${RED}ERROR: Please change directories to the BaseQuery root directory${NC}\n" 127 | fi 128 | --------------------------------------------------------------------------------