# Cross-python writing function
def writeData(f, data):
if Python3:
- f.write(bytes(data, 'UTF-8'))
+ f.write(bytes(data, "UTF-8"))
else:
- f.write(str(data).encode('UTF-8'))
+ f.write(str(data).encode("UTF-8"))
# This function doesn't list hidden files
def listdir_nohidden(path):
- return glob.glob(os.path.join(path, '*'))
+ return glob.glob(os.path.join(path, "*"))
# Project Settings
BASEDIR_PATH = os.path.dirname(os.path.realpath(__file__))
def main():
parser = argparse.ArgumentParser(description="Creates a unified hosts file from hosts stored in data subfolders.")
- parser.add_argument("--auto", "-a", dest="auto", default=False, action='store_true', help="Run without prompting.")
- parser.add_argument("--replace", "-r", dest="replace", default=False, action='store_true', help="Replace your active hosts file with this new hosts file.")
+ parser.add_argument("--auto", "-a", dest="auto", default=False, action="store_true", help="Run without prompting.")
+ parser.add_argument("--replace", "-r", dest="replace", default=False, action="store_true", help="Replace your active hosts file with this new hosts file.")
parser.add_argument("--ip", "-i", dest="targetip", default="0.0.0.0", help="Target IP address. Default is 0.0.0.0.")
- parser.add_argument("--extensions", "-e", dest="extensions", default=[], nargs='*', help="Host extensions to include in the final hosts file.")
+ parser.add_argument("--extensions", "-e", dest="extensions", default=[], nargs="*", help="Host extensions to include in the final hosts file.")
parser.add_argument("--output", "-o", dest="outputsubfolder", default="", help="Output subfolder for generated hosts file.")
- parser.add_argument("--noupdate", "-n", dest="noupdate", default=False, action='store_true', help="Don't update from host data sources.")
+ parser.add_argument("--noupdate", "-n", dest="noupdate", default=False, action="store_true", help="Don't update from host data sources.")
global settings
# ... intersected with the extensions passed-in as arguments, then sorted.
settings["extensions"] = sorted( list(set(options["extensions"]).intersection(settings["extensions"])) )
- with open(settings["readmedatafilename"], 'r') as f:
+ with open(settings["readmedatafilename"], "r") as f:
settings["readmedata"] = json.load(f)
promptForUpdate()
finalFile = removeDupsAndExcl(mergeFile)
finalizeFile(finalFile)
updateReadmeData()
- printSuccess('Success! The hosts file has been saved in folder ' + settings["outputsubfolder"] + '\nIt contains ' +
- "{:,}".format(settings["numberofrules"]) + ' unique entries.')
+ printSuccess("Success! The hosts file has been saved in folder " + settings["outputsubfolder"] + "\nIt contains " +
+ "{:,}".format(settings["numberofrules"]) + " unique entries.")
promptForMove(finalFile)
# Prompt the User
def promptForUpdate():
# Create hosts file if it doesn't exists
- if not os.path.isfile(os.path.join(BASEDIR_PATH, 'hosts')):
+ if not os.path.isfile(os.path.join(BASEDIR_PATH, "hosts")):
try:
- open(os.path.join(BASEDIR_PATH, 'hosts'), 'w+').close()
+ open(os.path.join(BASEDIR_PATH, "hosts"), "w+").close()
except:
printFailure("ERROR: No 'hosts' file in the folder, try creating one manually")
updateAllSources()
else:
if not settings["auto"]:
- print ("OK, we\'ll stick with what we\'ve got locally.")
+ print ("OK, we'll stick with what we've got locally.")
def promptForExclusions():
response = "no" if settings["auto"] else query_yes_no("Do you want to exclude any domains?\n" +
displayExclusionOptions()
else:
if not settings["auto"]:
- print ("OK, we\'ll only exclude domains in the whitelist.")
+ print ("OK, we'll only exclude domains in the whitelist.")
def promptForMoreCustomExclusions():
response = query_yes_no("Do you have more domains you want to enter?")
# Cross-python call
updatedFile = getFileByUrl(updateURL)
try:
- updatedFile = updatedFile.replace('\r', '') #get rid of carriage-return symbols
+ updatedFile = updatedFile.replace("\r", "") #get rid of carriage-return symbols
# This is cross-python code
- dataFile = open(os.path.join(settings["datapath"], source, settings["datafilenames"]), 'wb')
+ dataFile = open(os.path.join(settings["datapath"], source, settings["datafilenames"]), "wb")
writeData(dataFile, updatedFile)
dataFile.close()
except:
def getUpdateURLsFromFile(source):
pathToUpdateFile = os.path.join(settings["datapath"], source, settings["updateurlfilename"])
if os.path.exists(pathToUpdateFile):
- updateFile = open(pathToUpdateFile, 'r')
+ updateFile = open(pathToUpdateFile, "r")
retURLs = updateFile.readlines()
# .strip()
updateFile.close()
else:
retURL = None
- printFailure('Warning: Can\'t find the update file for source ' + source + '\n' +
- 'Make sure that there\'s a file at ' + pathToUpdateFile)
+ printFailure("Warning: Can't find the update file for source " + source + "\n" +
+ "Make sure that there's a file at " + pathToUpdateFile)
return retURLs
# End Update Logic
def getUpdateURLFromFile(source):
pathToUpdateFile = os.path.join(settings["datapath"], source, settings["updateurlfilename"])
if os.path.exists(pathToUpdateFile):
- updateFile = open(pathToUpdateFile, 'r')
+ updateFile = open(pathToUpdateFile, "r")
retURL = updateFile.readline().strip()
updateFile.close()
else:
retURL = None
- printFailure('Warning: Can\'t find the update file for source ' + source + '\n' +
- 'Make sure that there\'s a file at ' + pathToUpdateFile)
+ printFailure("Warning: Can't find the update file for source " + source + "\n" +
+ "Make sure that there's a file at " + pathToUpdateFile)
return retURL
# End Update Logic
def createInitialFile():
mergeFile = tempfile.NamedTemporaryFile()
for source in settings["sources"]:
- curFile = open(os.path.join(settings["datapath"], source, settings["datafilenames"]), 'r')
+ curFile = open(os.path.join(settings["datapath"], source, settings["datafilenames"]), "r")
#Done in a cross-python way
writeData(mergeFile, curFile.read())
for source in settings["extensions"]:
- curFile = open(os.path.join(settings["extensionspath"], source, settings["datafilenames"]), 'r')
+ curFile = open(os.path.join(settings["extensionspath"], source, settings["datafilenames"]), "r")
#Done in a cross-python way
writeData(mergeFile, curFile.read())
# Another mode is required to read and write the file in Python 3
if Python3:
- finalFile = open(os.path.join(settings["outputpath"], 'hosts'), 'w+b')
+ finalFile = open(os.path.join(settings["outputpath"], "hosts"), "w+b")
else:
- finalFile = open(os.path.join(settings["outputpath"], 'hosts'), 'w+')
+ finalFile = open(os.path.join(settings["outputpath"], "hosts"), "w+")
mergeFile.seek(0) # reset file pointer
hostnames = set()
hostnames.add("broadcasthost")
exclusions = settings["exclusions"]
for line in mergeFile.readlines():
- write = 'true'
+ write = "true"
# Explicit encoding
line = line.decode("UTF-8")
# replace tabs with space
- line = line.replace('\t+', ' ')
+ line = line.replace("\t+", " ")
# Trim trailing whitespace
line = line.rstrip() + "\n"
# Testing the first character doesn't require startswith
- if line[0] == '#' or re.match(r'^\s*$', line[0]):
+ if line[0] == "#" or re.match(r'^\s*$', line[0]):
# Cross-python write
writeData(finalFile, line)
continue
- if '::1' in line:
+ if "::1" in line:
continue
strippedRule = stripRule(line) #strip comments
hostname, normalizedRule = normalizeRule(strippedRule) # normalize rule
for exclude in exclusions:
if exclude in line:
- write = 'false'
+ write = "false"
break
- if normalizedRule and (hostname not in hostnames) and (write == 'true'):
+ if normalizedRule and (hostname not in hostnames) and (write == "true"):
writeData(finalFile, normalizedRule)
hostnames.add(hostname)
numberOfRules += 1
if result:
hostname, suffix = result.group(2,3)
hostname = hostname.lower().strip() # explicitly lowercase and trim the hostname
- if suffix is not '':
+ if suffix is not "":
# add suffix as comment only, not as a separate host
return hostname, "%s %s #%s\n" % (settings["targetip"], hostname, suffix)
else:
splitLine = line.split()
if len(splitLine) < 2 :
# just return blank
- return ''
+ return ""
else:
- return splitLine[0] + ' ' + splitLine[1]
+ return splitLine[0] + " " + splitLine[1]
def writeOpeningHeader(finalFile):
finalFile.seek(0) #reset file pointer
fileContents = finalFile.read() #save content
finalFile.seek(0) #write at the top
- writeData(finalFile, '# This hosts file is a merged collection of hosts from reputable sources,\n')
- writeData(finalFile, '# with a dash of crowd sourcing via Github\n#\n')
- writeData(finalFile, '# Date: ' + time.strftime("%B %d %Y", time.gmtime()) + '\n')
+ writeData(finalFile, "# This hosts file is a merged collection of hosts from reputable sources,\n")
+ writeData(finalFile, "# with a dash of crowd sourcing via Github\n#\n")
+ writeData(finalFile, "# Date: " + time.strftime("%B %d %Y", time.gmtime()) + "\n")
if settings["extensions"]:
- writeData(finalFile, '# Extensions added to this file: ' + ", ".join(settings["extensions"]) + '\n')
- writeData(finalFile, '# Number of unique domains: ' + "{:,}".format(settings["numberofrules"]) + '\n#\n')
- writeData(finalFile, '# Fetch the latest version of this file: https://raw.githubusercontent.com/StevenBlack/hosts/master/'+ os.path.join(settings["outputsubfolder"],"") + 'hosts\n')
- writeData(finalFile, '# Project home page: https://github.com/StevenBlack/hosts\n#\n')
- writeData(finalFile, '# ===============================================================\n')
- writeData(finalFile, '\n')
- writeData(finalFile, '127.0.0.1 localhost\n')
- writeData(finalFile, '127.0.0.1 localhost.localdomain\n')
- writeData(finalFile, '127.0.0.1 local\n')
- writeData(finalFile, '255.255.255.255 broadcasthost\n')
- writeData(finalFile, '::1 localhost\n')
- writeData(finalFile, 'fe80::1%lo0 localhost\n')
- if platform.system() == 'Linux':
- writeData(finalFile, '127.0.1.1 ' + socket.gethostname() + '\n')
- writeData(finalFile, '\n')
+ writeData(finalFile, "# Extensions added to this file: " + ", ".join(settings["extensions"]) + "\n")
+ writeData(finalFile, "# Number of unique domains: " + "{:,}".format(settings["numberofrules"]) + "\n#\n")
+ writeData(finalFile, "# Fetch the latest version of this file: https://raw.githubusercontent.com/StevenBlack/hosts/master/"+ os.path.join(settings["outputsubfolder"],"") + "hosts\n")
+ writeData(finalFile, "# Project home page: https://github.com/StevenBlack/hosts\n#\n")
+ writeData(finalFile, "# ===============================================================\n")
+ writeData(finalFile, "\n")
+ writeData(finalFile, "127.0.0.1 localhost\n")
+ writeData(finalFile, "127.0.0.1 localhost.localdomain\n")
+ writeData(finalFile, "127.0.0.1 local\n")
+ writeData(finalFile, "255.255.255.255 broadcasthost\n")
+ writeData(finalFile, "::1 localhost\n")
+ writeData(finalFile, "fe80::1%lo0 localhost\n")
+ if platform.system() == "Linux":
+ writeData(finalFile, "127.0.1.1 " + socket.gethostname() + "\n")
+ writeData(finalFile, "\n")
preamble = os.path.join(BASEDIR_PATH, "myhosts")
if os.path.isfile(preamble):
extensionsKey = "-".join(settings["extensions"])
generationData = {}
- generationData["location"] = os.path.join(settings["outputsubfolder"], '')
+ generationData["location"] = os.path.join(settings["outputsubfolder"], "")
generationData["entries"] = settings["numberofrules"]
settings["readmedata"][extensionsKey] = generationData
- with open(settings["readmedatafilename"], 'w') as f:
+ with open(settings["readmedatafilename"], "w") as f:
json.dump(settings["readmedata"], f)
def moveHostsFileIntoPlace(finalFile):
- if os.name == 'posix':
+ if os.name == "posix":
dnsCacheFound = False
print ("Moving the file requires administrative privileges. " +
"You might need to enter your password.")
if subprocess.call(["/usr/bin/sudo", "cp", os.path.abspath(finalFile.name), "/etc/hosts"]):
printFailure("Moving the file failed.")
print ("Flushing the DNS Cache to utilize new hosts file...")
- if platform.system() == 'Darwin':
+ if platform.system() == "Darwin":
dnsCacheFound = True
if subprocess.call(["/usr/bin/sudo", "killall", "-HUP", "mDNSResponder"]):
printFailure("Flushing the DNS Cache failed.")
printSuccess("Flushing DNS by restarting networking.service succeeded")
if not dnsCacheFound:
printFailure("Unable to determine DNS management tool.")
- elif os.name == 'nt':
+ elif os.name == "nt":
print ("Automatically moving the hosts file in place is not yet supported.")
print ("Please move the generated file to %SystemRoot%\system32\drivers\etc\hosts")
def removeOldHostsFile(): # hotfix since merging with an already existing hosts file leads to artefacts and duplicates
- oldFilePath = os.path.join(BASEDIR_PATH, 'hosts')
- open(oldFilePath, 'a').close() # create if already removed, so remove wont raise an error
- backupFilePath = os.path.join(BASEDIR_PATH, 'hosts-{0}'.format(time.strftime("%Y-%m-%d-%H-%M-%S")))
+ oldFilePath = os.path.join(BASEDIR_PATH, "hosts")
+ open(oldFilePath, "a").close() # create if already removed, so remove wont raise an error
+ backupFilePath = os.path.join(BASEDIR_PATH, "hosts-{0}".format(time.strftime("%Y-%m-%d-%H-%M-%S")))
shutil.copy(oldFilePath, backupFilePath) # make a backup copy, marking the date in which the list was updated
os.remove(oldFilePath)
- open(oldFilePath, 'a').close() # create new empty hostsfile
+ open(oldFilePath, "a").close() # create new empty hostsfile
# End File Logic
sys.stdout.write(colorize(question, colors.PROMPT) + prompt)
# Changed to be cross-python
choice = myInput().lower()
- if default is not None and choice == '':
+ if default is not None and choice == "":
return default
elif choice in valid.keys():
return valid[choice]
## end of http://code.activestate.com/recipes/577058/ }}}
def isValidDomainFormat(domain):
- if domain == '':
- print ("You didn\'t enter a domain. Try again.")
+ if domain == "":
+ print ("You didn't enter a domain. Try again.")
return False
domainRegex = re.compile("www\d{0,3}[.]|https?")
if domainRegex.match(domain):
# Colors
class colors:
- PROMPT = '\033[94m'
- SUCCESS = '\033[92m'
- FAIL = '\033[91m'
- ENDC = '\033[0m'
+ PROMPT = "\033[94m"
+ SUCCESS = "\033[92m"
+ FAIL = "\033[91m"
+ ENDC = "\033[0m"
def colorize(text, color):
return color + text + colors.ENDC