def getShellfireCerts(product_id, vpn_provider, country): # If the certs already exist, then just return # This is assuming that all of the certs remain the same, and are good for all connections for an account account_id = getAccountID() ca_name = getAddonPath(True, vpn_provider + "/" + "ca.crt") cert_name = getAddonPath(True, vpn_provider + "/" + "sf" + account_id + ".crt") key_name = getAddonPath(True, vpn_provider + "/" + "sf" + account_id + ".key") if xbmcvfs.exists(ca_name) and xbmcvfs.exists( cert_name) and xbmcvfs.exists(key_name): return True # Get the set of certificates that ar needed to connect rc, api_data = sendAPI("?action=getCertificates", "Retrieving certificates", '{"productId": "' + product_id + '"}', True) if not rc: return False # Write all of the certs to a file for item in api_data["data"]: cert_name = item["name"] if not writeCert(vpn_provider, cert_name, item["content"]): return False return True
def getAddonPathWrapper(name): # Return the fully qualified add-on path and file name if generateVPNs(): return "/storage/.kodi/addons/service.vpn.manager/" + name else: if getPlatform() == platforms.WINDOWS: return getAddonPath(True, name).replace("\\", "\\\\") else: return getAddonPath(True, name)
def createCustomFile(sT_confiG, ovpn_connection, sT_dnS_patH, protO_typE, protO_nuM, vpn_provider, sT_dnS_adD, sT_dnS_typE): pathToAuthFile = str(getAddonPath(True, vpn_provider + "/pass.txt")) pathToDnsPatch = str(getAddonPath(True, vpn_provider + "/dnsLeak.py")) with open(sT_dnS_patH, 'w') as config_file: config_file.write(sT_confiG + '\nauth-user-pass ' + pathToAuthFile) config_file.write("\nup '/bin/bash -c \"python " + pathToDnsPatch + '"\'' + "\ndown '/bin/bash -c \"python " + pathToDnsPatch + '"\'')
def getAddonPathWrapper(path): # This function resets the VPN profiles to the standard VPN Manager install # location as per OpenELEC, or to the platform install location force_default_install = fakeConnection() if force_default_install: return "/storage/.kodi/addons/service.vpn.manager/" + path else: if getPlatform() == platforms.WINDOWS: return getAddonPath(True, path).replace("\\", "\\\\") else: return getAddonPath(True, path)
def getClientId(): global clientId vpn_provider = addon.getSetting("vpn_provider") if os.path.isfile(getAddonPath(True, vpn_provider + "/loginDetails.txt")): with open(getAddonPath(True, vpn_provider + "/loginDetails.txt"), 'r') as fx: lines = fx.readlines() if lines[2]: clientId = lines[2] else: clientId = 'Not valid'
def removeGeneratedFiles(): for provider in providers: if ovpnGenerated(provider): if isUserDefined(provider): # If this is the user defined provider, delete everything files = getAddonList(provider, "*") else: # If this is a regular provider, delete just the ovpn files files = getAddonList(provider, "*.ovpn") for file in files: xbmcvfs.delete(file) filename = getAddonPath(True, provider + "/GENERATED.txt") if xbmcvfs.exists(filename): xbmcvfs.delete(filename) filename = getAddonPath(True, provider + "/TRANSLATE.txt") if xbmcvfs.exists(filename): xbmcvfs.delete(filename)
def generatePP(): # Data is stored as a bunch of ovpn files # File name has location. File has the server profiles = getProfileList("PerfectPrivacy") location_file = getLocations("PerfectPrivacy", "") for profile in profiles: geo = profile[profile.rfind("\\") + 1:profile.index(".ovpn")] geo = geo.replace("TelAviv", "Tel Aviv") geo = geo.replace("Hongkong", "Hong Kong") geo = geo.replace("NewYork", "New York") geo_key = geo + "_ta.key" if not xbmcvfs.exists(getAddonPath(True, "PerfectPrivacy/" + geo_key)): geo = "****ERROR****" profile_file = open(profile, 'r') lines = profile_file.readlines() profile_file.close() servers = "" ports = "" for line in lines: if line.startswith("remote "): _, server, port = line.split() if not servers == "": servers = servers + " " servers = servers + server if not ports == "": ports = ports + " " ports = ports + port output_line = geo + " (UDP)," + servers + "," + "udp," + ports + ",#TLSKEY=" + geo_key + "\n" location_file.write(output_line) location_file.close()
def getLocationFiles(vpn_provider): # Return the locations files, add any user version to the end of the list locations = glob.glob(getAddonPath(True, vpn_provider + "/LOCATIONS*.txt")) user_locations = getUserDataPath(vpn_provider + "/LOCATIONS.txt") if xbmcvfs.exists(user_locations): locations.append(user_locations.replace(".txt", " User.txt")) return locations
def writeDefaultUpFile(): p = getPlatform() if p == platforms.LINUX or p == platforms.RPI: infoTrace("vpnproviders.py", "Writing default up script") up = open(getAddonPath(True, "up.sh"), 'w') up.write("#!/bin/bash\n") up.write("iptables -F\n") up.write( "iptables -A INPUT -i tun0 -m state --state ESTABLISHED,RELATED -j ACCEPT\n" ) up.write("iptables -A INPUT -i tun0 -j DROP\n") up.close() command = "chmod +x " + getAddonPath(True, "up.sh") if useSudo(): command = "sudo " + command infoTrace("vpnproviders.py", "Fixing default up.sh " + command) os.system(command)
def generateSecureVPN(): # Can't use a template as SecureVPN use multiple everything. # Copy the file to the target directory and strip it of user keys existing_profiles = glob.glob( getUserDataPath("providers/SecureVPN" + "/*.ovpn")) for connection in existing_profiles: xbmcvfs.delete(connection) # Get the list from the provider data directory profiles = getProfileList("SecureVPN") destination_path = getAddonPath(True, "SecureVPN" + "/") for profile in profiles: shortname = profile[profile.index("SecureVPN") + 10:] shortname = shortname[:shortname.index(".")] proto = "(UDP)" filename = shortname + " " + proto + ".ovpn" profile_file = open(profile, 'r') output_file = open(destination_path + filename, 'w') profile_contents = profile_file.readlines() profile_file.close() output = "" i = 0 write = True for line in profile_contents: line = line.strip(' \t\n\r') if not (line == "" or line.startswith("#")): if "<key>" in line or "<cert>" in line: write = False if "</key>" in line: write = True line = "key #USERKEY" if "</cert>" in line: write = True line = "cert #USERCERT" if write: output_file.write(line + "\n") i = i + 1 output_file.close()
def generatePP(): # Data is stored as a bunch of ovpn files # File name has location. File has the server profiles = getProfileList("PerfectPrivacy") location_file = getLocations("PerfectPrivacy", "") for profile in profiles: geo = profile[profile.rfind("\\")+1:profile.index(".ovpn")] geo = geo.replace("TelAviv", "Tel Aviv") geo = geo.replace("Hongkong", "Hong Kong") geo = geo.replace("NewYork", "New York") geo_key = geo + "_ta.key" if not xbmcvfs.exists(getAddonPath(True, "PerfectPrivacy/" + geo_key)): geo = "****ERROR****" profile_file = open(profile, 'r') lines = profile_file.readlines() profile_file.close() servers = "" ports = "" for line in lines: if line.startswith("remote "): _, server, port = line.split() if not servers == "" : servers = servers + " " servers = servers + server if not ports == "" : ports = ports + " " ports = ports + port output_line = geo + " (UDP)," + servers + "," + "udp," + ports + ",#TLSKEY=" + geo_key + "\n" location_file.write(output_line) location_file.close()
def generateWiTopia(): # Data is stored in a flat text file # City name followed by server name, or just server name (starts with vpn.) location_file = getLocations("WiTopia", "") source_file = open(getAddonPath(True, "providers/WiTopia/Servers.txt"), 'r') source = source_file.readlines() source_file.close() city = "" cont = "" for line in source: line = line.strip(" \t\n\r") if not line.startswith("vpn."): if line.startswith("-"): cont = line.replace("-", "") if not cont == "": cont = cont + " - " else: city = line else: if city == "": city = line.replace("vpn.","").replace(".witopia.net","") city = string.capwords(city) geo = cont + city server = line output_line_udp = geo + " (UDP)," + server + "," + "udp,1194" + "\n" city = "" location_file.write(output_line_udp) location_file.close()
def getTemplateFile(vpn_provider): def_temp = getAddonPath(True, vpn_provider + "/TEMPLATE.txt") user_temp = getUserDataPath(vpn_provider + "/TEMPLATE.txt") if xbmcvfs.exists(user_temp): return user_temp else: return def_temp
def copyUserDefinedFiles(): # Copy everything in the user directory to the addon directory infoTrace("vpnproviders.py", "Copying user defined files from userdata directory") source_path = getUserDataPath((user_def_str) + "/") dest_path = getAddonPath(True, user_def_str + "/") # Get the list of connection profiles and another list of strings to abuse for the selection screen try: files = getUserDataList(user_def_str, "*") if len(files) == 0: errorTrace( "vpnproviders.py", "No User Defined files available to copy from " + source_path) return False for file in files: name = file[file.rfind(getSeparator()) + 1:] dest_file = dest_path + getSeparator() + name xbmcvfs.copy(file, dest_file) return True except Exception as e: errorTrace( "vpnproviders.py", "Error copying files from " + source_path + " to " + dest_path) errorTrace("vpnproviders.py", str(e)) return False
def generateVyprVPN(): # Data is stored in a flat text file # There appear to be a regular set of servers, which are either goldenfrog or vyprvpn # And an alternative set of servers that are available via some giganews hook up. # Both use the same certificate. location_file_vypr = getLocations("VyprVPN", "VyprVPN Account") location_file_giga = getLocations("VyprVPN", "Giganews Account") source_file = open(getAddonPath(True, "providers/VyprVPN/Servers.txt"), 'r') source = source_file.readlines() source_file.close() for line in source: tokens = line.split() for t in tokens: if ".goldenfrog.com" in t: server = t.strip(' \t\n\r') geo = line.replace(server, "") geo = geo.strip(' \t\n\r') server = server.replace("vpn.goldenfrog.com", "vyprvpn.com") if "," in geo: geo = "USA - " + geo[:geo.index(",")] output_line_vypr = geo + " (UDP)," + server + "," + "udp,1194" + "\n" server = server.replace("vyprvpn.com", "vpn.giganews.com") output_line_giga = geo + " (UDP)," + server + "," + "udp,1194" + "\n" location_file_vypr.write(output_line_vypr) location_file_giga.write(output_line_giga) location_file_vypr.close() location_file_giga.close()
def getShellfireOvpn(product_id, vpn_provider, country): # Retrieve the ovpn parameters and make them into an ovpn file rc, api_data = sendAPI("?action=getOpenVpnParams", "Retrieving openvpn params", '{"productId": "' + product_id + '"}', True) if not rc: return False # Parse the parameters and override some of them params = api_data["data"]["params"].split("--") filename = getAddonPath(True, vpn_provider + "/" + country + ".ovpn") output = open(filename, 'w') country_cert = "sf" + getAccountID() for p in params: p = p.strip(" \n") if p.startswith("service "): p = "" if p.startswith("ca "): p = "ca " + getAddonPathWrapper(vpn_provider + "/ca.crt") if p.startswith("cert "): p = "cert " + getAddonPathWrapper(vpn_provider + "/" + country_cert + ".crt") if p.startswith("key "): p = "key " + getAddonPathWrapper(vpn_provider + "/" + country_cert + ".key") if not p == "": output.write(p + "\n") output.close() return True
def generateVPNht(): # Data is stored in a flat text file # Location on one line, then server on the next location_file_smartdns = getLocations("VPN.ht", "With SmartDNS") location_file_without = getLocations("VPN.ht", "Without SmartDNS") location_file_all = getLocations("VPN.ht", "All Connections") source_file = open(getAddonPath(True, "providers/VPN.ht/Servers.txt"), 'r') source = source_file.readlines() source_file.close() i = 0 for line in source: if i == 0: i = 1 geo = line.strip(' \t\n\r') else: i = 0 server = line.strip(' \t\n\r') serverudp = server for j in range (1, 7): serverudp = serverudp + " " + server output_line_udp = geo + " (UDP)," + serverudp + "," + "udp,1194 1195 1196 1197 1198 1199 1200" + "\n" output_line_udp_no = geo + " (UDP SmartDNS)," + serverudp + "," + "udp,1194 1195 1196 1197 1198 1199 1200" + ",#REMOVE=1\n" output_line_tcp_no = geo + " (TCP)," + server + "," + "tcp,443" + ",#REMOVE=1\n" output_line_tcp = geo + " (TCP SmartDNS)," + server + "," + "tcp,443" + "\n" location_file_smartdns.write(output_line_udp) location_file_smartdns.write(output_line_tcp) location_file_without.write(output_line_udp_no) location_file_without.write(output_line_tcp_no) location_file_all.write(output_line_udp) location_file_all.write(output_line_tcp) location_file_all.write(output_line_udp_no) location_file_all.write(output_line_tcp_no) location_file_smartdns.close() location_file_without.close() location_file_all.close()
def generateLimeVPN(): # Can't use a template as LimeVPN use server certs. # Copy the file to the target directory and strip it of user keys existing_profiles = glob.glob(getAddonPath(True, "LimeVPN" + "/*.ovpn")) for connection in existing_profiles: xbmcvfs.delete(connection) # Get the list from the provider data directory profiles = getProfileList("LimeVPN") destination_path = getAddonPath(True, "LimeVPN" + "/") for profile in profiles: shortname = profile[profile.index("LimeVPN") + 8:] shortname = shortname.replace("_openvpn_remote_access_l3", "") shortname = shortname[:shortname.index(".")] shortname = shortname.replace("aus", "au") shortname = shortname.replace("sw", "se") shortname = shortname.replace("sk", "kr") countryname = resolveCountry(shortname[0:2].upper()) if len(shortname) == 3: shortname = " " + shortname[2:3] else: shortname = "" proto = " (UDP)" filename = countryname + shortname + proto + ".ovpn" profile_file = open(profile, 'r') output_file = open(destination_path + filename, 'w') profile_contents = profile_file.readlines() profile_file.close() output = "" i = 0 write = True newPrint(destination_path + filename) for line in profile_contents: line = line.strip(' \t\n\r') if not (line == "" or line.startswith("#")): if "<key>" in line or "<cert>" in line: write = False if "</key>" in line: write = True line = "" if "</cert>" in line: write = True line = "" if write and not line == "": output_file.write(line + "\n") newPrint(line) i = i + 1 output_file.close()
def getAddonPathWrapper(path): # This function resets the VPN profiles to the standard VPN Manager install # location as per OpenELEC, or to the platform install location force_default_install = fakeConnection() if force_default_install: return "/storage/.kodi/addons/service.purevpn.monitor/" + path else: return getAddonPath(True, path)
def removeGeneratedFiles(): for provider in providers: if ovpnGenerated(provider): ovpn_connections = getProfileList(provider) for connection in ovpn_connections: xbmcvfs.delete(connection) filename = getAddonPath(True, provider + "/GENERATED.txt") if xbmcvfs.exists(filename) : xbmcvfs.delete(filename)
def updateVPNFiles(vpn_provider): # If the OVPN files aren't generated then they need to be updated with location info infoTrace("vpnproviders.py", "Updating VPN profiles for " + vpn_provider) # Get the list of VPN profile files ovpn_connections = getProfileList(vpn_provider) # See if there's a port override going on addon = xbmcaddon.Addon("service.vpn.manager") if addon.getSetting("default_udp") == "true": portUDP = "" else: portUDP = addon.getSetting("alternative_udp_port") if addon.getSetting("default_tcp") == "true": portTCP = "" else: portTCP = addon.getSetting("alternative_tcp_port") for connection in ovpn_connections: try: f = open(connection, 'r+') debugTrace("Processing file " + connection) lines = f.readlines() f.seek(0) f.truncate() # Update the necessary values in the ovpn file for line in lines: if "auth-user-pass" in line: line = "auth-user-pass " + getAddonPathWrapper(vpn_provider + "/" + "pass.txt\n") if "remote " in line: port = "" for newline in lines: if "proto " in newline: if "tcp" in newline and not portTCP == "": port = portTCP if "udp" in newline and not portUDP == "": port = portUDP if not port == "": tokens = line.split() line = "remote " + tokens[1] + " " + port + "\n" f.write(line) f.close() except: errorTrace("profileupdate.py", "Failed to update ovpn file") return False # Write a file to indicate successful update of the ovpn files ovpn_file = open(getAddonPath(True, vpn_provider + "/GENERATED.txt"), 'w') ovpn_file.close() return True
def getShellfireCerts(product_id, vpn_provider, country): # If the certs already exist, then just return # This is assuming that all of the certs remain the same, and are good for all connections for an account account_id = getAccountID() ca_name = getAddonPath(True, vpn_provider + "/" + "ca.crt") cert_name = getAddonPath(True, vpn_provider + "/" + "sf" + account_id + ".crt") key_name = getAddonPath(True, vpn_provider + "/" + "sf" + account_id + ".key") if xbmcvfs.exists(ca_name) and xbmcvfs.exists(cert_name) and xbmcvfs.exists(key_name): return True # Get the set of certificates that ar needed to connect rc, api_data = sendAPI("?action=getCertificates", "Retrieving certificates", '{"productId": "' + product_id + '"}', True) if not rc: return False # Write all of the certs to a file for item in api_data["data"]: cert_name = item["name"] if not writeCert(vpn_provider, cert_name, item["content"]): return False return True
def generateNordVPN(): # Can't use a template here as NordVPN use multiple certificate and keys. # Copy the file to the target directory and rename it to something more tidy # Latest can be found at https://nordvpn.com/api/files/zip # Remove what's there to start with existing_profiles = glob.glob(getAddonPath(True, "NordVPN" + "/*.ovpn")) for connection in existing_profiles: xbmcvfs.delete(connection) # Get the list from the provider data directory profiles = getProfileList("NordVPN") destination_path = getAddonPath(True, "NordVPN" + "/") for profile in profiles: shortname = profile[profile.index("NordVPN") + 8:] shortname = shortname[:shortname.index(".")] if not "-" in shortname: shortname = resolveCountry( (shortname[0:2]).upper()) + " " + shortname[2:] else: if "lt-lv1" in shortname: shortname = "Lithuania - Latvia 1" if "tw-hk1" in shortname: shortname = "Taiwan - Hong Kong 1" if "us-ca2" in shortname: shortname = "United States - Canada 2" if "nl1-ru1" in shortname: shortname = "Netherlands - Russia 1" if "ru-nl1" in shortname: shortname = "Russia - Netherlands 1" if "lv-tor1" in shortname: shortname = "Latvia Tor 1" if "se-tor1" in shortname: shortname = "Sweden Tor 1" proto = "" if "tcp443" in profile: proto = "(TCP)" if "udp1194" in profile: proto = "(UDP)" filename = shortname + " " + proto + ".ovpn" profile_file = open(profile, 'r') output_file = open(destination_path + filename, 'w') profile_contents = profile_file.readlines() profile_file.close() output = "" i = 0 for line in profile_contents: line = line.strip(' \t\n\r') if not line == "" and not line.startswith("#mute") and not ( i < 15 and line.startswith("#")): output_file.write(line + "\n") i = i + 1
def createUnPass(): global status, lag, clientId, vpn_username, vpn_password, vpn_provider, addon digests = [] # The function will check if there is any diffrence between the usernames before and after by comparing the hash files before and after. # If there is a diffrence it will forward to check credentials. if no diffrence will discontinue. # Will create a file with username and password. fname2 = getAddonPath(True, vpn_provider + "/tempauth.txt") with open(fname2, 'w') as file: vpn_username = addon.getSetting("vpn_username") vpn_password = addon.getSetting("vpn_password") file.write(vpn_username + '\n' + vpn_password) file.close() # Will check for the older file having username and password and will compare the two files using their hashes. fname3 = getAddonPath(True, vpn_provider + "/auth.txt") if os.path.isfile(fname3): for filename in [fname2, fname3]: hasher = hashlib.md5() with open(filename, 'rb') as f: buf = f.read() hasher.update(buf) a = hasher.hexdigest() digests.append(a) # If hashes are diffrent will replace the older file with new one and throw a call to get the clientId for latest credential else do nothing if (digests[0] == digests[1]) == False: debugTrace('Hashes are diffrent') shutil.copy2(fname2, fname3) throwCall() createDetailsFile() # If first use, and cant find old file (auth1) then will not compare and will continue with call to get the clientId for latest credentials else: shutil.copy2(fname2, fname3) throwCall() createDetailsFile() # Remove temporary created auth file i.e. tempauth if os.path.isfile(fname2): os.remove(fname2)
def generateNordVPN(): # Can't use a template here as NordVPN use multiple certificate and keys. # Copy the file to the target directory and rename it to something more tidy # Use the file name to find the country in the servers file # Remove what's there to start with existing_profiles = glob.glob(getAddonPath(True, "NordVPN" + "/*.ovpn")) for connection in existing_profiles: xbmcvfs.delete(connection) # Get the list from the provider data directory profiles = getProfileList("NordVPN") destination_path = getAddonPath(True, "NordVPN" + "/") source_file = open(getAddonPath(True, "providers/NordVPN/Servers.txt"), 'r') servers = source_file.readlines() source_file.close() for profile in profiles: shortname = profile[profile.index("NordVPN") + 9:] server = shortname[:shortname.index(".com") + 4] geo = "" for line in servers: if server in line: geo = line[:line.index(server) - 1] geo = geo.replace("#", "") geo = geo.strip(' \t\n\r') if "tcp443" in shortname: proto = "(TCP)" if "udp1194" in shortname: proto = "(UDP)" filename = geo + " " + proto + ".ovpn" profile_file = open(profile, 'r') output_file = open(destination_path + filename, 'w') profile_contents = profile_file.readlines() profile_file.close() output = "" i = 0 for line in profile_contents: line = line.strip(' \t\n\r') if not line == "" and not line.startswith("#mute") and not ( i < 15 and line.startswith("#")): output_file.write(line + "\n") i = i + 1
def removeGeneratedFiles(): for provider in providers: if ovpnGenerated(provider): if isUserDefined(provider): # If this is the user defined provider, delete everything files = getAddonList(provider, "*") else: # If this is a regular provider, delete just the ovpn files files = getAddonList(provider, "*.ovpn") for file in files: xbmcvfs.delete(file) filename = getAddonPath(True, provider + "/GENERATED.txt") if xbmcvfs.exists(filename) : xbmcvfs.delete(filename)
def generateCelo(): # Data is stored as a bunch of ovpn files # File name has location. File has the server profiles = getProfileList("Celo") location_file = getLocations("Celo", "") for profile in profiles: geo = profile[profile.rfind("\\") + 1:profile.index(".ovpn")] geo_key = (geo + "_ta.key").replace(" ", "_") geo_cert = (geo + "_ca.crt").replace(" ", "_") if not xbmcvfs.exists(getAddonPath(True, "Celo/" + geo_key)): geo = "****ERROR****" if not xbmcvfs.exists(getAddonPath(True, "Celo/" + geo_cert)): geo = "****ERROR****" profile_file = open(profile, 'r') lines = profile_file.readlines() profile_file.close() servers_udp = "" servers_tcp = "" ports_udp = "" ports_tcp = "" for line in lines: if line.startswith("remote "): _, server, port, proto = line.split() proto = proto.lower() if proto == "udp": if not servers_udp == "": servers_udp = servers_udp + " " servers_udp = servers_udp + server if not ports_udp == "": ports_udp = ports_udp + " " ports_udp = ports_udp + port if proto == "tcp": if not servers_tcp == "": servers_tcp = servers_tcp + " " servers_tcp = servers_tcp + server if not ports_tcp == "": ports_tcp = ports_tcp + " " ports_tcp = ports_tcp + port output_line_udp = geo + " (UDP)," + servers_udp + "," + "udp," + ports_udp + ",#TLSKEY=" + geo_key + " #CERT=" + geo_cert + "\n" output_line_tcp = geo + " (TCP)," + servers_tcp + "," + "tcp," + ports_tcp + ",#TLSKEY=" + geo_key + " #CERT=" + geo_cert + "\n" location_file.write(output_line_udp) location_file.write(output_line_tcp) location_file.close()
def generateCelo(): # Data is stored as a bunch of ovpn files # File name has location. File has the server profiles = getProfileList("Celo") location_file = getLocations("Celo", "") for profile in profiles: geo = profile[profile.rfind("\\")+1:profile.index(".ovpn")] geo_key = (geo + "_ta.key").replace(" ", "_") geo_cert = (geo + "_ca.crt").replace(" ", "_") if not xbmcvfs.exists(getAddonPath(True, "Celo/" + geo_key)): geo = "****ERROR****" if not xbmcvfs.exists(getAddonPath(True, "Celo/" + geo_key)): geo = "****ERROR****" profile_file = open(profile, 'r') lines = profile_file.readlines() profile_file.close() servers_udp = "" servers_tcp = "" ports_udp = "" ports_tcp = "" for line in lines: if line.startswith("remote "): _, server, port, proto = line.split() proto = proto.lower() if proto == "udp": if not servers_udp == "" : servers_udp = servers_udp + " " servers_udp = servers_udp + server if not ports_udp == "" : ports_udp = ports_udp + " " ports_udp = ports_udp + port if proto == "tcp": if not servers_tcp == "" : servers_tcp = servers_tcp + " " servers_tcp = servers_tcp + server if not ports_tcp == "" : ports_tcp = ports_tcp + " " ports_tcp = ports_tcp + port output_line_udp = geo + " (UDP)," + servers_udp + "," + "udp," + ports_udp + ",#TLSKEY=" + geo_key + " #CERT=" + geo_cert + "\n" output_line_tcp = geo + " (TCP)," + servers_tcp + "," + "tcp," + ports_tcp + ",#TLSKEY=" + geo_key + " #CERT=" + geo_cert + "\n" location_file.write(output_line_udp) location_file.write(output_line_tcp) location_file.close()
def createDetailsFile(): global flag, status, clientId, vpn_provider # Creating a file for user's verification status and clientId fname1 = getAddonPath(True, vpn_provider + "/loginDetails.txt") if os.path.isfile(fname1): os.remove(fname1) with open(fname1, 'w') as file4: file4.write(flag + '\n' + status + '\n' + clientId) file4.close() debugTrace('File containing cliendId created')
def generateVPNUnlim(): # Data is stored in ovpn files with location info in Servers.txt location_file = getLocations("VPNUnlimited", "") source_file = open(getAddonPath(True, "providers/VPNUnlimited/Servers.txt"), 'r') servers = source_file.readlines() source_file.close() for entry in servers: geo = entry[:entry.index(",")].strip() server = entry[entry.index(",")+1:].strip() output_line_udp = geo + " (UDP)," + server + ",udp,443\n" output_line_tcp = geo + " (TCP)," + server + ",tcp,80\n" location_file.write(output_line_udp) location_file.write(output_line_tcp) location_file.close()
def generateNordVPN(): # Can't use a template here as NordVPN use multiple certificate and keys. # Copy the file to the target directory and rename it to something more tidy # Use the file name to find the country in the servers file # Remove what's there to start with existing_profiles = glob.glob(getAddonPath(True, "NordVPN" + "/*.ovpn")) for connection in existing_profiles: xbmcvfs.delete(connection) # Get the list from the provider data directory profiles = getProfileList("NordVPN") destination_path = getAddonPath(True, "NordVPN" + "/") source_file = open(getAddonPath(True, "providers/NordVPN/Servers.txt"), 'r') servers = source_file.readlines() source_file.close() for profile in profiles: shortname = profile[profile.index("NordVPN")+9:] server = shortname[:shortname.index(".com")+4] geo = "" for line in servers: if server in line: geo = line[:line.index(server)-1] geo = geo.replace("#", "") geo = geo.strip(' \t\n\r') if "tcp443" in shortname: proto = "(TCP)" if "udp1194" in shortname: proto = "(UDP)" filename = geo + " " + proto + ".ovpn" profile_file = open(profile, 'r') output_file = open(destination_path + filename, 'w') profile_contents = profile_file.readlines() profile_file.close() output = "" i = 0 for line in profile_contents: line = line.strip(' \t\n\r') if not line == "" and not line.startswith("#mute") and not (i < 15 and line.startswith("#")): output_file.write(line + "\n") i = i + 1
def generateNordVPN(): # Can't use a template here as NordVPN use multiple certificate and keys. # Copy the file to the target directory and rename it to something more tidy # Remove what's there to start with existing_profiles = glob.glob(getAddonPath(True, "NordVPN" + "/*.ovpn")) for connection in existing_profiles: xbmcvfs.delete(connection) # Get the list from the provider data directory profiles = getProfileList("NordVPN") destination_path = getAddonPath(True, "NordVPN" + "/") for profile in profiles: shortname = profile[profile.index("NordVPN")+8:] shortname = shortname[:shortname.index(".")] if not "-" in shortname: shortname = resolveCountry((shortname[0:2]).upper()) + " " + shortname[2:] else: if "lt-lv1" in shortname: shortname = "Lithuania - Latvia 1" if "tw-hk1" in shortname: shortname = "Taiwan - Hong Kong 1" if "us-ca2" in shortname: shortname = "United States - Canada 2" if "lv-tor1" in shortname: shortname = "Latvia Tor 1" if "se-tor1" in shortname: shortname = "Sweden Tor 1" proto = "" if "tcp443" in profile: proto = "(TCP)" if "udp1194" in profile: proto = "(UDP)" filename = shortname + " " + proto + ".ovpn" profile_file = open(profile, 'r') output_file = open(destination_path + filename, 'w') profile_contents = profile_file.readlines() profile_file.close() output = "" i = 0 for line in profile_contents: line = line.strip(' \t\n\r') if not line == "" and not line.startswith("#mute") and not (i < 15 and line.startswith("#")): output_file.write(line + "\n") i = i + 1
def generateVPNUnlim(): # Data is stored in ovpn files with location info in Servers.txt location_file = getLocations("VPNUnlimited", "") source_file = open( getAddonPath(True, "providers/VPNUnlimited/Servers.txt"), 'r') servers = source_file.readlines() source_file.close() for entry in servers: geo = entry[:entry.index(",")].strip() server = entry[entry.index(",") + 1:].strip() output_line_udp = geo + " (UDP)," + server + ",udp,443\n" output_line_tcp = geo + " (TCP)," + server + ",tcp,80\n" location_file.write(output_line_udp) location_file.write(output_line_tcp) location_file.close()
def writeCert(vpn_provider, cert_name, content): # Write out the certificate represented by the content filename = getAddonPath(True, vpn_provider + "/" + cert_name) try: line = "" debugTrace("Writing certificate " + cert_name) output = open(filename, 'w') # Output the content line by line for line in content: output.write(line) output.close() return True except Exception as e: errorTrace("alternativeShellfire`.py", "Couldn't write certificate " + filename) errorTrace("alternativeShellfire.py", str(e)) return False
def getNordVPNLocationsCommon(vpn_provider, exclude_used, friendly): # Return a list of all of the locations or location .ovpn files addon = xbmcaddon.Addon(getID()) # Get the list of used, validated location file names used = [] if exclude_used: # Adjust the 11 below to change conn_max for i in range(1, 11): s = addon.getSetting(str(i) + "_vpn_validated_friendly") if not s == "": used.append(s) filename = getAddonPath(True, vpn_provider + "/" + NORD_LOCATIONS) # If the list of countries doesn't exist (this can happen after a reinstall) # then go and do the pre-fetch first. Otherwise this shouldn't be necessary try: if not xbmcvfs.exists(filename): getNordVPNPreFetch(vpn_provider) except Exception as e: errorTrace( "alternativeNord.py", "Couldn't download the list of countries for " + vpn_provider + " from " + filename) errorTrace("alternativeNord.py", str(e)) return [] # Read the locations file and generate the location file name, excluding any that are used try: locations_file = open(filename, 'r') locations = locations_file.readlines() locations_file.close() return_locations = [] for l in locations: country, id = l.split(",") if not exclude_used or not country in used: if friendly: return_locations.append(country) else: return_locations.append( getNordVPNLocationName(vpn_provider, country)) return return_locations except Exception as e: errorTrace( "alternativeNord.py", "Couldn't read the list of countries for " + vpn_provider + " from " + filename) errorTrace("alternativeNord.py", str(e)) return []
def getBestPathWrapper(name): # This function will return the path to the user version of a given file # if it exists, otherwise it'll return the path the default add-on version # This is just about resetting the ovpn documents if neccesary if generateVPNs(): return "/storage/.kodi/addons/service.vpn.manager/" + path else: filename = getUserDataPath(name) if not xbmcvfs.exists(filename): filename = getAddonPath(True, name) else: infoTrace("vpnprovider.py", "Using userdata override " + filename) if getPlatform() == platforms.WINDOWS: return filename.replace("\\", "\\\\") else: return filename
def updateVPNFiles(vpn_provider): # If the OVPN files aren't generated then they need to be updated with location info infoTrace("vpnproviders.py", "Updating VPN profiles for " + vpn_provider) # Get the list of VPN profile files ovpn_connections = getProfileList(vpn_provider) # Set ports as default portUDP = "" portTCP = "" for connection in ovpn_connections: try: f = open(connection, 'r+') debugTrace("Processing file " + connection) lines = f.readlines() f.seek(0) f.truncate() # Update the necessary values in the ovpn file for line in lines: if "auth-user-pass" in line: line = "auth-user-pass " + getAddonPathWrapper(vpn_provider + "/" + "pass.txt\n") if "remote " in line: port = "" for newline in lines: if "proto " in newline: if "tcp" in newline and not portTCP == "": port = portTCP if "udp" in newline and not portUDP == "": port = portUDP if not port == "": tokens = line.split() line = "remote " + tokens[1] + " " + port + "\n" f.write(line) f.close() except: errorTrace("profileupdate.py", "Failed to update ovpn file") return False # Write a file to indicate successful update of the ovpn files ovpn_file = open(getAddonPath(True, vpn_provider + "/GENERATED.txt"), 'w') ovpn_file.close() return True
def getCountryId(countrY): addon = xbmcaddon.Addon("service.purevpn.monitor") vpn_provider = addon.getSetting("vpn_provider") fname = str(getAddonPath(True, vpn_provider + "/countriesList.json")) debugTrace(fname) with open(fname, 'r') as fp: return_list = json.load(fp) for key, value in return_list.items(): arr = [',', ')', '('] for character in arr: if character in value: value = value.replace(character, '') return_list[key] = value countrY_iD = return_list.keys()[return_list.values().index(str(countrY))] debugTrace(countrY_iD) return countrY_iD
def generatetigerVPN(): # Data is stored in a flat text file, each line representing a connection # valid for UDP and TCP using the standard ports location_file_full = getLocations("tigerVPN", "tigerVPN Full Account") location_file_lite = getLocations("tigerVPN", "tigerVPN Lite Account") source_file = open(getAddonPath(True, "providers/tigerVPN/tigerVPN.csv"), 'r') source = source_file.readlines() source_file.close() for line in source: server = line.split(',') output_line_udp = server[1] + " " + server[0] + " (UDP)," + server[2] + "," + "udp,1194" + "\n" output_line_tcp = server[1] + " " + server[0] + " (TCP)," + server[2] + "," + "tcp,443" + "\n" location_file_full.write(output_line_udp) location_file_full.write(output_line_tcp) if server[4].startswith("Lite"): location_file_lite.write(output_line_udp) location_file_lite.write(output_line_tcp) location_file_full.close() location_file_lite.close()
def copyUserDefinedFiles(): # Copy everything in the user directory to the addon directory infoTrace("vpnproviders.py", "Copying user defined files from userdata directory") source_path = getUserDataPath((user_def_str)+"/") dest_path = getAddonPath(True, user_def_str + "/") # Get the list of connection profiles and another list of strings to abuse for the selection screen try: files = getUserDataList(user_def_str, "*") if len(files) == 0: errorTrace("vpnproviders.py", "No User Defined files available to copy from " + source_path) return False for file in files: name = file[file.rfind(getSeparator())+1:] dest_file = dest_path + getSeparator() + name xbmcvfs.copy(file, dest_file) return True except: errorTrace("vpnproviders.py", "Error copying files from " + source_path + " to " + dest_path) return False
def generateHMA(): # Data is stored in a flat text file # <Continent> - <Country> xx.yy.rocks random.xx.yy.rocks location_file = getLocations("HMA", "") source_file = open(getAddonPath(True, "providers/HMA/Servers.txt"), 'r') source = source_file.readlines() source_file.close() for line in source: tokens = line.split() for t in tokens: if ".rocks" in t and not "random." in t: server = t.strip(' \t\n\r') geo = line.replace(server, "") geo = geo.replace("random.", "") geo = geo.strip(' \t\n\r') geo = geo.replace("USA,", "USA -") geo = geo.replace("UK,", "UK -") output_line_udp = geo + " (UDP)," + server + "," + "udp,53" + "\n" output_line_tcp = geo + " (TCP)," + server + "," + "tcp,443" + "\n" location_file.write(output_line_udp) location_file.write(output_line_tcp) location_file.close()
def generateVyprVPN(): # Data is stored in a flat text file # <Something> xx.yy.nordvpn.com location_file = getLocations("VyprVPN", "") source_file = open(getAddonPath(True, "providers/VyprVPN/Servers.txt"), 'r') source = source_file.readlines() source_file.close() for line in source: tokens = line.split() for t in tokens: if ".goldenfrog.com" in t: server = t.strip(' \t\n\r') geo = line.replace(server, "") geo = geo.strip(' \t\n\r') server = server.replace("vpn.goldenfrog.com", "vyprvpn.com") if "," in geo: geo = "USA - " + geo[:geo.index(",")] output_line_udp = geo + " (UDP)," + server + "," + "udp,1194" + "\n" # VyprVPN doesn't appear to support TCP, so UDP option only #output_line_tcp = geo + " (TCP 443)," + server + "," + "tcp,443" + "\n" location_file.write(output_line_udp) #location_file.write(output_line_tcp) location_file.close()
def generateTotalVPN(): # Data is stored in a flat text file # Location, tab, server - free locations are marked with a leading * location_file_full = getLocations("TotalVPN", "Full Account") location_file_free = getLocations("TotalVPN", "Free Account") source_file = open(getAddonPath(True, "providers/TotalVPN/Servers.txt"), 'r') source = source_file.readlines() source_file.close() for line in source: line = line.strip(" \t\n\r") geo, server = line.split("\t") geo = geo.strip(" *\t\n\r") geo = geo.replace(",", " -") output_line_udp = geo + " (UDP)," + server + "," + "udp,1194" + "\n" output_line_tcp = geo + " (TCP)," + server + "," + "tcp,443" + "\n" location_file_full.write(output_line_udp) location_file_full.write(output_line_tcp) if "*" in line: location_file_free.write(output_line_udp) location_file_free.write(output_line_tcp) location_file_full.close() location_file_free.close()
def generatetigerVPN(): # Data is stored in a flat text file, each line representing a connection # valid for UDP and TCP using the standard ports location_file_full = getLocations("tigerVPN", "tigerVPN Full Account") location_file_lite = getLocations("tigerVPN", "tigerVPN Lite Account") source_file = open(getAddonPath(True, "providers/tigerVPN/tigerVPN.csv"), 'r') source = source_file.readlines() source_file.close() for line in source: server = line.split(',') output_line_udp = server[1] + " " + server[0] + " (UDP)," + server[ 2] + "," + "udp,1194" + "\n" output_line_tcp = server[1] + " " + server[0] + " (TCP)," + server[ 2] + "," + "tcp,443" + "\n" location_file_full.write(output_line_udp) location_file_full.write(output_line_tcp) if server[4].startswith("Lite"): location_file_lite.write(output_line_udp) location_file_lite.write(output_line_tcp) location_file_full.close() location_file_lite.close()
def getAddonPathWrapper(name): # Return the fully qualified add-on path and file name if getPlatform() == platforms.WINDOWS: return getAddonPath(True, name).replace("\\", "\\\\") else: return getAddonPath(True, name)
def getAddonList(vpn_provider, filter): # Return the list of ovpn files for a given provider (aka directory name...) path = getAddonPath(True, getVPNLocation(vpn_provider) + "/" + filter) debugTrace("Getting list of profiles in " + path) return sorted(glob.glob(path))
def writeGeneratedFile(vpn_provider): # Write a file to indicate successful generation of the ovpn files ovpn_file = open(getAddonPath(True, vpn_provider + "/GENERATED.txt"), 'w') ovpn_file.close()
def generateOVPNFiles(vpn_provider, alternative_locations_name): # Generate the OVPN files for a VPN provider using the template and update with location info infoTrace("vpnproviders.py", "Generating OVPN files for " + vpn_provider + " using list " + alternative_locations_name) # See if there's a port override going on addon = xbmcaddon.Addon("service.vpn.manager") if addon.getSetting("default_udp") == "true": portUDP = "" else: portUDP = addon.getSetting("alternative_udp_port") if addon.getSetting("default_tcp") == "true": portTCP = "" else: portTCP = addon.getSetting("alternative_tcp_port") # Get the logging level verb_value = addon.getSetting("openvpn_verb") if verb_value == "": verb_value = "1" addon.setSetting("openvpn_verb", verb_value) # Load ovpn template try: debugTrace("Opening template file for " + vpn_provider) template_file = open(getAddonPath(True, vpn_provider + "/TEMPLATE.txt"), 'r') debugTrace("Opened template file for " + vpn_provider) template = template_file.readlines() template_file.close() except: errorTrace("vpnproviders.py", "Couldn't open the template file for " + vpn_provider) return False # Load locations file if not alternative_locations_name == "": if alternative_locations_name == "User": locations_name = getUserDataPath(vpn_provider + "/LOCATIONS.txt") else: locations_name = getAddonPath(True, vpn_provider + "/LOCATIONS " + alternative_locations_name + ".txt") else: locations_name = getAddonPath(True, vpn_provider + "/LOCATIONS.txt") try: debugTrace("Opening locations file for " + vpn_provider + "\n" + locations_name) locations_file = open(locations_name, 'r') debugTrace("Opened locations file for " + vpn_provider) locations = locations_file.readlines() locations_file.close() except: errorTrace("vpnproviders.py", "Couldn't open the locations file for " + vpn_provider + "\n" + locations_name) return False # For each location, generate an OVPN file using the template for location in locations: try: location_values = location.split(",") geo = location_values[0] servers = location_values[1].split() proto = location_values[2] ports = (location_values[3].strip(' \t\n\r')).split() port = "" # Initialise the set of values that can be modified by the location file tuples ca_cert = "ca.crt" ta_key = "ta.key" user_key = getUserDataPathWrapper(vpn_provider + "/" + getKeyName(vpn_provider, geo)) user_cert = getUserDataPathWrapper(vpn_provider + "/" + getCertName(vpn_provider, geo)) remove_flags = "" if len(location_values) > 4: # The final location value is a list of multiple x=y declarations. # These need to be parsed out and modified. modifier_tuples = (location_values[4].strip(' \t\n\r')).split() # Loop through all of the values splitting them into name value pairs for modifier in modifier_tuples: pair = modifier.split("=") if "#CERT" in pair[0]: ca_cert = pair[1].strip() if "#REMOVE" in pair[0]: remove_flags = pair[1].strip() if "#TLSKEY" in pair[0]: ta_key = pair[1].strip() if "#USERKEY" in pair[0]: user_key = pair[1].strip() if "#USERCERT" in pair[0]: user_cert = pair[1].strip() if proto == "udp" and not portUDP == "": port = portUDP if proto == "tcp" and not portTCP == "": port = portTCP if port == "" and len(ports) == 1: port = ports[0] except: errorTrace("vpnproviders.py", "Location file for " + vpn_provider + " invalid on line\n" + location) return False try: ovpn_file = open(getAddonPath(True, vpn_provider + "/" + geo + ".ovpn"), 'w') if proto == "tcp": servprot = "tcp-client" else: servprot = proto # Do a replace on the tags in the template with data from the location file for line in template: output_line = line.strip(' \t\n\r') # Must check to see if there's a remove tag on the line before looking for other tags if "#REMOVE" in output_line: if output_line[output_line.index("#REMOVE")+7] in remove_flags: # Remove the line if it's a flag this location doesn't care about output_line = "" else: # Delete the tag if this location doesn't want this line removed output_line = output_line.replace("#REMOVE" + output_line[output_line.index("#REMOVE")+7], "") output_line = output_line.replace("#PROTO", proto) output_line = output_line.replace("#SERVPROT", servprot) # If there are multiple servers then we'll need to duplicate the server # line (which starts with 'remote ') and fix the server. The rest of the # code will deal with the port which is the same for all lines (although # this assumption might not be true for all VPN providers...) if output_line.startswith("remote "): server_template = output_line server_lines = "" i = 0 for server in servers: if not server_lines == "" : server_lines = server_lines + "\n" server_lines = server_lines + server_template.replace("#SERVER", server) if port == "": server_lines = server_lines.replace("#PORT", ports[i]) i = i + 1 output_line = server_lines # There might be other places we use server and port, so still the do the replace output_line = output_line.replace("#SERVER", servers[0]) output_line = output_line.replace("#PORT", port) output_line = output_line.replace("#PASS", getAddonPathWrapper(vpn_provider + "/" + "pass.txt")) output_line = output_line.replace("#CERT", getAddonPathWrapper(vpn_provider + "/" + ca_cert)) output_line = output_line.replace("#TLSKEY", getAddonPathWrapper(vpn_provider + "/" + ta_key)) output_line = output_line.replace("#CRLVERIFY", getAddonPathWrapper(vpn_provider + "/" + "crl.pem")) output_line = output_line.replace("#USERKEY", user_key) output_line = output_line.replace("#USERCERT", user_cert) # Overwrite the verb value with the one in the settings if output_line.startswith("verb "): output_line = "verb " + verb_value # This is a little hack to remove a tag that doesn't work with TCP but is needed for UDP # Could do this with a #REMOVE, but doing it here is less error prone. if "explicit-exit-notify" in line and proto == "tcp": output_line = "" if not output_line == "" : ovpn_file.write(output_line + "\n") ovpn_file.close() debugTrace("Wrote location " + geo + " " + proto) except: errorTrace("vpnproviders.py", "Can't write a location file for " + vpn_provider + " failed on line\n" + location) return False # Flag that the files have been generated writeGeneratedFile(vpn_provider) return True
def cleanPassFiles(): # Delete the pass.txt file from all of the VPN provider directorys for provider in providers: filename = getAddonPath(True, provider + "/pass.txt") if xbmcvfs.exists(filename) : xbmcvfs.delete(filename)
def ovpnGenerated(vpn_provider): if isUserDefined(vpn_provider): return True if xbmcvfs.exists(getAddonPath(True, vpn_provider + "/TEMPLATE.txt")): return True return False
def ovpnFilesAvailable(vpn_provider): if xbmcvfs.exists(getAddonPath(True, vpn_provider + "/GENERATED.txt")): return True return False
def getShellfireLocation(vpn_provider, location, server_count, just_name): # Return the friendly and .ovpn name addon = xbmcaddon.Addon(getID()) # Just return if this is a title that's been passed in if location.startswith(TITLE_START): return "", "", "Select a location or server", True # Remove all of the tagging # There's some escaping of the UPGRADE_END characters when passed in via the add-on menu # This is why the command below searches for the end of the upgrade and strips it location = location.replace(UPGRADE_START, "") if "I]" in location: location = location[:(location.index("I]")-2)] location = location.strip(" ") filename = getAddonPath(True, vpn_provider + "/" + SHELLFIRE_LOCATIONS) try: if not xbmcvfs.exists(filename): getShellfirePreFetch(vpn_provider) except Exception as e: errorTrace("alternativeShellfire.py", "Couldn't download the list of locations for " + vpn_provider + " from " + filename) errorTrace("alternativeShellfire.py", str(e)) return "", "", "", False try: # Read the locations from the file and list by account type locations_file = open(filename, 'r') locations = locations_file.readlines() locations_file.close() for l in locations: if location in l: country, server, type, server_id = l.split(",") server_id = server_id.strip(" \n") break # Return an upgrade message if this server is not available to the user if ACCOUNT_TYPES.index(type) > ACCOUNT_TYPES.index(getAccountType()): _, message = getShellfireMessages(vpn_provider, 0, "") if message == "": message = "Get access to servers in over 30 countries with unlimited speed at shellfire.net/kodi" return "", "", "Upgrade to use this [B]" + type + "[/B] location.\n" + message, False # Generate the file name from the location location_filename = getShellfireLocationName(vpn_provider, country) if just_name: return location, location_filename, "", False except Exception as e: errorTrace("alternativeShellfire.py", "Couldn't read the list of locations for " + vpn_provider + " from " + filename) errorTrace("alternativeShellfire.py", str(e)) return "", "", "", False # Set the selected server for the VPN being used try: setShellfireServer(getAccountID(), server_id) # Set the protocol. If it's "UDP and TCP", choose UDP proto = addon.getSetting("vpn_protocol") if "UDP" in proto: proto = "UDP" if not setShellfireProtocol(getAccountID(), proto): raise Exception("Couldn't set the protocol") # Get the parameters associated with this server and put them in a file if not getShellfireOvpn(getAccountID(), vpn_provider, country): raise Exception("Couldn't create an OVPN file") # Get the certs associated with this server and put them in a file if not getShellfireCerts(getAccountID(), vpn_provider, country): raise Exception("Couldn't create the certificates") return country, location_filename, "", False except Exception as e: errorTrace("alternativeShellfire.py", "Couldn't read the list of locations for " + vpn_provider + " from " + filename) errorTrace("alternativeShellfire.py", str(e)) return "", "", "", False
def cleanGeneratedFiles(): # Delete the GENERATED.txt file from all of the VPN provider directorys for provider in providers: filename = getAddonPath(True, provider + "/GENERATED.txt") if xbmcvfs.exists(filename) : xbmcvfs.delete(filename)