def genovpnFiles(vpn_provider): if not ovpnFilesAvailable(getVPNLocation(vpn_provider)): # Fetch the list of locations available. If there are multiple, the user can select locations = getLocationFiles(getVPNLocation(vpn_provider)) default_label = "Default" i = 0 for location in locations: locations[i] = location[location.index("LOCATIONS")+10:location.index(".txt")] if locations[i] == "" : locations[i] = default_label i = i + 1 selected_profile = "" if len(locations) == 0: errorTrace("vpnproviders.py", "No LOCATIONS.txt files found in VPN directory. Cannot generate ovpn files.") if len(locations) > 1: selected_location = xbmcgui.Dialog().select("Select connections profile", locations) selected_profile = locations[selected_location] if selected_profile == default_label : selected_profile = "" addon = xbmcaddon.Addon() addon.setSetting("vpn_locations_list", selected_profile) # Delete any old files in other directories debugTrace("Deleting all generated ovpn files") removeGeneratedFiles() # Generate new ones try: provider_gen = fixOVPNFiles(getVPNLocation(vpn_provider), selected_profile) except: errorTrace("Couldn't generate new .ovpn files") provider_gen = False xbmc.sleep(500) return provider_gen else: return True
def getShellfireMessages(vpn_provider, last_time, last_id): # Return any message ID and message available from the provider # Never return a message for a paid account unless a last_time of 0 is being used to force it if getAccountType() > 0 and not last_time == 0: return "", "" # Fetch any available deal rc, api_data = sendAPI("?action=getAvailablePricingDeal", "Retrieving messages", "", False) # Adding 'Success' to the end of this line will return a test message # Check the call worked and that it was successful. If there's no message, a bad response is returned if not rc: return "", "" if not api_data["status"] == "success": return "", "" try: # Extract and format the message id = api_data["data"]["pricingDealId"] message = api_data["data"]["name"] + " - " + api_data["data"]["description"] + " - Only available until " ts = int(api_data["data"]["validUntil"]) message = message + time.strftime("%b %d", time.gmtime(ts)) message = message + " - " + api_data["data"]["url"] # Don't return a message if the same message was displayed < 1 week ago if (not last_time == 0) and (last_time + 604800 > now()) and last_id == id: return "", "" except Exception as e: errorTrace("alternativeShellfire.py", "Couldn't format message returned") errorTrace("alternativeShellfire.py", "JSON received is \n" + json.dumps(api_data, indent=4)) return "", "" return id, message
def copySystemdFiles(): # Delete any existing openvpn.service and copy openvpn service file to config directory service_source = getAddonPath(True, "openvpn.service") service_dest = getSystemdPath("system.d/openvpn.service") debugTrace("Copying openvpn.service " + service_source + " to " + service_dest) if not fakeSystemd(): if xbmcvfs.exists(service_dest): xbmcvfs.delete(service_dest) xbmcvfs.copy(service_source, service_dest) if not xbmcvfs.exists(service_dest): raise IOError('Failed to copy service ' + service_source + " to " + service_dest) # Delete any existing openvpn.config and copy first VPN to openvpn.config config_source = sudo_setting = xbmcaddon.Addon( getID()).getSetting("1_vpn_validated") if service_source == "": errorTrace("vpnplatform.py", "Nothing has been validated") config_dest = getSystemdPath("openvpn.config") debugTrace("Copying openvpn.config " + config_source + " to " + config_dest) if not fakeSystemd(): if xbmcvfs.exists(config_dest): xbmcvfs.delete(config_dest) xbmcvfs.copy(config_source, config_dest) if not xbmcvfs.exists(config_dest): raise IOError('Failed to copy service ovpn ' + config_source + " to " + config_dest)
def getTokenNordVPN(): # Return a token that can be used on API calls token, renew, expiry, _ = getTokens() # If the expiry time is passed, renew the token if expiry.isdigit() and int(expiry) < now(): if renewNordVPN(renew): token, _, _, _ = getTokens() return token else: # Force an authenticate to happen token = "" # The authentication call is made during connection validation, which will validate everything and fetch # the tokens. If a reboot happens and the tokens disappear, then we need to force an authenticate again if token == "": addon = xbmcaddon.Addon(getID()) if authenticateNordVPN(addon.getSetting("vpn_provider_validated"), addon.getSetting("vpn_username_validated"), addon.getSetting("vpn_password_validated")): token, _, _, _ = getTokens() return token else: errorTrace("alternativeNord.py", "Couldn't authenticate or renew the user ID") resetTokens() raise RuntimeError("Couldn't get a user ID token") debugTrace("Using existing user ID token") return token
def getVPNConnectionStatus(): # Open the openvpn output file and parse it for known phrases # Return 'connected', 'auth failed', 'network failed', 'error' or '' if fakeConnection(): return connection_status.UNKNOWN # **** ADD MORE PLATFORMS HERE **** # Might not need to mess with this too much if the log output from openvpn is the same p = getPlatform() if p == platforms.LINUX or p == platforms.RPI: path = getVPNLogFilePath() state = connection_status.UNKNOWN if xbmcvfs.exists(path): debugTrace("Reading log file") log = open(path,'r') lines = log.readlines() for line in lines: if "Initialization Sequence Completed" in line: state = connection_status.CONNECTED break if "AUTH_FAILED" in line: state = connection_status.AUTH_FAILED if "TLS Error" in line: state = connection_status.NETWORK_FAILED if "Connection timed out" in line: state = connection_status.TIMEOUT log.close() # Haven't found what's expected so return an empty stream if not state == connection_status.UNKNOWN: debugTrace("VPN connection status is " + str(state)) return state else: errorTrace("platform.py", "Tried to get VPN connection status but log file didn't exist") return connection_status.ERROR
def getIPInfo(addon): # Based this code on a routine in the VPN for OPENELEC plugin # Generate request to find out where this IP is based # Return ip info source, ip, location, isp source = addon.getSetting("ip_info_source") if not source in getIPSources(): addon.setSetting("ip_info_source", getIPSources()[0]) source == getIPSources()[0] debugTrace("Getting IP info from " + source) retry = 0 while retry < 5: ip, country, region, city, isp = getIPInfoFrom(source) if ip == "no info": debugTrace("No location information was returned for IP using " + source) # Got a response but couldn't format it. No point retrying return source, "no info", "unknown", "unknown" elif ip == "error": errorTrace("common.py", "Something bad happened when trying to get a response from iplocation.net " + isp) # Didn't get a valid response so want to retry three times in case service was busy if retry == 2 : return source + " (not available)", "unknown", "unknown", "unknown" xbmc.sleep(3000) else: # Worked, exit loop break retry = retry + 1 location = "" if not (region == "-" or region == "Not Available"): location = region if not (country == "-" or country == "Not Available"): if not location == "": location = location + ", " location = location + country return source, ip, location, isp
def deleteTestFile(): try: if xbmcvfs.exists(getTestFilePath()): xbmcvfs.delete(getTestFilePath()) except Exception as e: errorTrace("vpnplatform.py", "Couldn't delete test file") errorTrace("vpnplatform.py", str(e))
def getVPNConnectionStatus(): # Open the openvpn output file and parse it for known phrases # Return 'connected', 'auth failed', 'network failed', 'error' or '' if fakeConnection(): return connection_status.UNKNOWN # **** ADD MORE PLATFORMS HERE **** # Might not need to mess with this too much if the log output from different platform openvpns are the same p = getPlatform() if p == platforms.LINUX or p == platforms.RPI or p == platforms.WINDOWS: path = getVPNLogFilePath() state = connection_status.UNKNOWN if xbmcvfs.exists(path): debugTrace("Reading log file") log = open(path, 'r') lines = log.readlines() for line in lines: if "Initialization Sequence Completed" in line: state = connection_status.CONNECTED break if "AUTH_FAILED" in line: state = connection_status.AUTH_FAILED if "private key password verification failed" in line: state = connection_status.AUTH_FAILED if "TLS Error" in line: state = connection_status.NETWORK_FAILED if "Connection timed out" in line: state = connection_status.TIMEOUT if "Inactivity timeout" in line: state = connection_status.TIMEOUT if "Error opening configuration file" in line: state = connection_status.FILE_ERROR if p == platforms.WINDOWS and "ROUTE" in line and "Access is denied" in line: # This is a Windows, not running Kodi as administrator error state = connection_status.ACCESS_DENIED break if p == platforms.WINDOWS and "FlushIpNetTable" in line and "Access is denied" in line: # This is a Windows, not running Kodi as administrator error state = connection_status.ACCESS_DENIED break #if "ERROR: Linux route" in line: # state = connection_status.ROUTE_FAILED # This tests for a Linux route failure, only it's commented out as # it can legitimately fail if the route already exists. If it fails # for other reasons, I can't tell the different just yet. # break log.close() # Haven't found what's expected so return an empty stream if not state == connection_status.UNKNOWN: debugTrace("VPN connection status is " + str(state)) return state else: errorTrace( "vpnplatform.py", "Tried to get VPN connection status but log file didn't exist") return connection_status.ERROR
def checkVPNCommand(addon): # Issue the openvpn command and see if the output is a bunch of commands if not fakeConnection(): p = getPlatform() # Issue the openvpn command, expecting to get the options screen back if p == platforms.RPI or p == platforms.LINUX: # Issue Linux command command = getOpenVPNPath() + " > " + getVPNLogFilePath() + " &" if useSudo(): command = "sudo " + command infoTrace("platform.py", "Testing openvpn with : " + command) os.system(command) elif p == platforms.WINDOWS: # Issue Windows command command = getOpenVPNPath() args = shlex.split(command) outfile = open(getVPNLogFilePath(), 'w') proc = subprocess.Popen(args, stdout=outfile, creationflags=subprocess.SW_HIDE, shell=True) # **** ADD MORE PLATFORMS HERE **** # Waiting for the log file to appear xbmc.sleep(1000) i = 0 while not xbmcvfs.exists(getVPNLogFilePath()) and i < 10: xbmc.sleep(1000) i = i + 1 # If the log file appears, check it's what we expect if xbmcvfs.exists(getVPNLogFilePath()): log_file = open(getVPNLogFilePath(), 'r') log_file_lines = log_file.readlines() log_file.close() i = 0 # Look for a phrase we'd expect to see if the call # worked and the list of options was displayed for line in log_file_lines: if "General Options" in line: return True i = i + 1 # Write the log file in case there's something in it errorTrace("platform.py", "Ran openvpn command and it failed") writeVPNLog() else: errorTrace("platform.py", "Ran openvpn command and VPN log didn't appear") # Display an error message dialog_msg = "The OpenVPN executable isn't working. Check the log, then from a command line prompt type 'openvpn' and fix any problems reported\n" xbmcgui.Dialog().ok(addon.getAddonInfo("name"), dialog_msg) return False else: return True
def getipstack(json_data): try: ip = json_data["ip"] country = json_data["country_name"] region = json_data["region_name"] city = json_data["city"] return ip, country, region, city, "Unknown" except Exception as e: errorTrace("ipinfo.py", "Couldn't parse JSON data " + str(json_data)) errorTrace("ipinfo.py", str(e)) return None, None, None, None, None
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 getipinfo(json_data): try: ip = json_data["ip"] country = json_data["country"] region = json_data["region"] city = json_data["city"] isp = json_data["org"] return ip, country, region, city, isp except Exception as e: errorTrace("ipinfo.py", "Couldn't parse JSON data " + str(json_data)) errorTrace("ipinfo.py", str(e)) return None, None, None, None, None
def writeVPNLog(): # Write the openvpn output log to the error file try: log_file = open(getVPNLogFilePath(), 'r') log_output = log_file.readlines() log_file.close() infoTrace("platform.py", "VPN log file start >>>") for line in log_output: print line infoTrace("platform.py", "<<< VPN log file end") except: errorTrace("platform.py", "Couldn't write VPN error log")
def writeVPNLog(): # Write the openvpn output log to the error file try: log_file = open(getVPNLogFilePath(), "r") log_output = log_file.readlines() log_file.close() infoTrace("platform.py", "VPN log file start >>>") for line in log_output: print line infoTrace("platform.py", "<<< VPN log file end") except: errorTrace("platform.py", "Couldn't write VPN error log")
def fakeItTillYouMakeIt(fake): try: if fake: if not fakeConnection(): f = open(getUserDataPath(fake_name),'w') f.close() else: if fakeConnection(): xbmcvfs.delete(getUserDataPath(fake_name)) except Exception as e: errorTrace("vpnplatform.py", "fakeItTillYouMakeIt " + str(fake) + " failed") errorTrace("vpnplatform.py", str(e))
def checkVPNCommand(addon): # Issue the openvpn command and see if the output is a bunch of commands if not fakeConnection(): p = getPlatform() # Issue the openvpn command, expecting to get the options screen back if p == platforms.RPI or p == platforms.LINUX: # Issue Linux command command = getOpenVPNPath() + " > " + getVPNLogFilePath() + " &" if useSudo(): command = "sudo " + command infoTrace("platform.py", "Testing openvpn with : " + command) os.system(command) elif p == platforms.WINDOWS: # Issue Windows command command = getOpenVPNPath() args = shlex.split(command) outfile = open(getVPNLogFilePath(), "w") proc = subprocess.Popen(args, stdout=outfile, creationflags=subprocess.SW_HIDE, shell=True) # **** ADD MORE PLATFORMS HERE **** # Waiting for the log file to appear xbmc.sleep(1000) i = 0 while not xbmcvfs.exists(getVPNLogFilePath()) and i < 10: xbmc.sleep(1000) i = i + 1 # If the log file appears, check it's what we expect if xbmcvfs.exists(getVPNLogFilePath()): log_file = open(getVPNLogFilePath(), "r") log_file_lines = log_file.readlines() log_file.close() i = 0 # Look for a phrase we'd expect to see if the call # worked and the list of options was displayed for line in log_file_lines: if "General Options" in line: return True i = i + 1 # Write the log file in case there's something in it errorTrace("platform.py", "Ran openvpn command and it failed") writeVPNLog() else: errorTrace("platform.py", "Ran openvpn command and VPN log didn't appear") # Display an error message dialog_msg = "The OpenVPN executable isn't working. Check the log, then from a command line prompt type 'openvpn' and fix any problems reported\n" xbmcgui.Dialog().ok(addon.getAddonInfo("name"), dialog_msg) return False else: return True
def writeTestFile(): # Write the command test output to the error file try: log_file = open(getTestFilePath(), 'r') log_output = log_file.readlines() log_file.close() infoTrace("vpnplatform.py", "Command test file start >>>") for line in log_output: infoPrint(line) infoTrace("vpnplatform.py", "<<< Command test file end") except Exception as e: errorTrace("vpnplatform.py", "Couldn't write test file") errorTrace("vpnplatform.py", str(e))
def startService(): # Routine for config to call to request that service starts. Can time out if there's no response # Check to see if service is not already running (shouldn't be...) if not xbmcgui.Window(10000).getProperty("VPN_Manager_Service_Control") == "stopped": return True debugTrace("Requesting service restarts") # Update start property and wait for service to respond or timeout xbmcgui.Window(10000).setProperty("VPN_Manager_Service_Control", "start") for i in range (0, 30): xbmc.sleep(1000) if xbmcgui.Window(10000).getProperty("VPN_Manager_Service_Control") == "started": return True # No response in 30 seconds, service is probably dead errorTrace("common.py", "Couldn't communicate with VPN monitor service, didn't acknowledge a start") return False
def stopService(): # Routine for config to call to request service stops and waits until that happens # Check to see if the service has stopped previously if xbmcgui.Window(10000).getProperty("VPN_Manager_Service_Control") == "stopped": return True debugTrace("Requesting service stops") # Update start property and wait for service to respond or timeout xbmcgui.Window(10000).setProperty("VPN_Manager_Service_Control", "stop") for i in range (0, 30): xbmc.sleep(1000) if xbmcgui.Window(10000).getProperty("VPN_Manager_Service_Control") == "stopped": return True # Haven't had a response in 30 seconds which is badness errorTrace("common.py", "Couldn't communicate with VPN monitor service, didn't acknowledge a stop") return False
def recordAction(action): log = getActionLogName(False) old_log = getActionLogName(True) addon = xbmcaddon.Addon("service.zomboided.tools") if addon.getSetting("enable_action_log") == "true": try: if xbmcvfs.exists(log): st = xbmcvfs.Stat(log) size = st.st_size() if size > 1024000: # Limit log files to 1MB...this allow for ~10000 entries debugTrace("Action log size is " + str(size) + ", starting new action log") if xbmcvfs.exists(old_log): xbmcvfs.delete(old_log) xbmcvfs.rename(log, old_log) except Exception as e: errorTrace("common.py", "Couldn't manage existing action log file") errorTrace("common.py", str(e)) try: log_file = open(log, 'a+') time = datetime.datetime.fromtimestamp(now()) log_file.write(str(time) + " " + action + "\n") log_file.close() except Exception as e: errorTrace("common.py", "Couldn't record action") errorTrace("common.py", str(e))
def writeKeyPass(key_pass_name, password): # Return the password being used for a given key file try: if xbmcvfs.exists(key_pass_name): xbmcvfs.delete(key_pass_name) debugTrace("Writing key password file " + key_pass_name) pass_file = open(key_pass_name, 'w') pass_file.write(password) pass_file.close() return True except Exception as e: errorTrace("vpnproviders.py", "Failed to write key password file to userdata") errorTrace("vpnproviders.py", str(e)) return False
def popupSysBox(): if not getID() == "": addon = xbmcaddon.Addon(getID()) dialog_text_l = "" dialog_text_r = "" data_left = getSystemData(addon, True, True, False, False) data_right = getSystemData(addon, False, False, False, True) for line in data_left: if line.startswith("[B]") and not dialog_text_l == "": dialog_text_l = dialog_text_l + "\n" dialog_text_l = dialog_text_l + line + "\n" for line in data_right: if line.startswith("[B]") and not dialog_text_r == "": dialog_text_r = dialog_text_r + "\n" dialog_text_r = dialog_text_r + line + "\n" showInfoBox("System Information", dialog_text_l, dialog_text_r) else: errorTrace("sysbox.py", "VPN service is not ready")
def clearUserData(): # Deleting everything here, but not deleting 'DEFAULT.txt' as # any existing user and password info will get deleted path = getUserDataPath("UserDefined" + "/*.*") debugTrace("Deleting contents of User Defined directory" + path) files = glob.glob(path) try: for file in files: if not file.endswith("DEFAULT.txt") and xbmcvfs.exists(file): debugTrace("Deleting " + file) xbmcvfs.delete(file) except Exception as e: errorTrace("userdefined.py", "Couldn't clear the UserDefined directory") errorTrace("userdefined.py", str(e)) return False return True
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 copyKeyAndCert(vpn_provider, ovpn_name, user_key, user_cert): # Copy the user key and cert to the userdata directory key_dest = getUserDataPath(vpn_provider + "/" + getKeyName(vpn_provider, ovpn_name)) key_source = user_key cert_dest = getUserDataPath(vpn_provider + "/" + getCertName(vpn_provider, ovpn_name)) cert_source = user_cert try: debugTrace("Copying key " + key_source + " to " + key_dest) if xbmcvfs.exists(key_dest): xbmcvfs.delete(key_dest) xbmcvfs.copy(key_source, key_dest) debugTrace("Copying cert " + cert_source + " to " + cert_dest) if xbmcvfs.exists(cert_dest): xbmcvfs.delete(cert_dest) xbmcvfs.copy(cert_source, cert_dest) return True except: errorTrace("vpnproviders.py", "Failed to copy user key or cert file to userdata") return False
def getVPNConnectionStatus(): # Open the openvpn output file and parse it for known phrases # Return 'connected', 'auth failed', 'network failed', 'error' or '' if fakeConnection(): return connection_status.UNKNOWN # **** ADD MORE PLATFORMS HERE **** # Might not need to mess with this too much if the log output from different platform openvpns are the same p = getPlatform() if p == platforms.LINUX or p == platforms.RPI or p == platforms.WINDOWS: path = getVPNLogFilePath() state = connection_status.UNKNOWN if xbmcvfs.exists(path): debugTrace("Reading log file") log = open(path, "r") lines = log.readlines() for line in lines: if "Initialization Sequence Completed" in line: state = connection_status.CONNECTED break if "AUTH_FAILED" in line: state = connection_status.AUTH_FAILED if "TLS Error" in line: state = connection_status.NETWORK_FAILED if "Connection timed out" in line: state = connection_status.TIMEOUT if p == platforms.WINDOWS and "ROUTE" in line and "Access is denied" in line: # This is a Windows, not running Kodi as administrator error state = connection_status.ACCESS_DENIED break # if "ERROR: Linux route" in line: # state = connection_status.ROUTE_FAILED # This tests for a Linux route failure, only it's commented out as # it can legitimately fail if the route already exists. If it fails # for other reasons, I can't tell the different just yet. # break log.close() # Haven't found what's expected so return an empty stream if not state == connection_status.UNKNOWN: debugTrace("VPN connection status is " + str(state)) return state else: errorTrace("platform.py", "Tried to get VPN connection status but log file didn't exist") return connection_status.ERROR
def writeVPNLog(): # Write the openvpn output log to the error file try: if xbmcvfs.exists(getVPNLogFilePath()): log_file = open(getVPNLogFilePath(), 'r') log_output = log_file.readlines() log_file.close() infoTrace("vpnplatform.py", "VPN log file start >>>") for line in log_output: line = line.strip("\n") infoPrint(line) infoTrace("vpnplatform.py", "<<< VPN log file end") else: infoTrace("vpnplatform.py", "No VPN log file exists to write") except Exception as e: errorTrace("vpnplatform.py", "Couldn't write VPN error log") errorTrace("vpnplatform.py", str(e))
def writeVPNConfiguration(ovpn): # Write the openvpn configuration to the error file try: if xbmcvfs.exists(ovpn): ovpn_file = open(ovpn, 'r') ovpn_output = ovpn_file.readlines() ovpn_file.close() infoTrace("vpnplatform.py", "VPN configuration " + ovpn + " start >>>") for line in ovpn_output: line = line.strip("\n") infoPrint(line) infoTrace("vpnplatform.py", "<<< VPN configuration file end") else: infoTrace("vpnplatform.py", "No VPN configuration " + ovpn + " exists to write") except Exception as e: errorTrace("vpnplatform.py", "Couldn't write VPN error log") errorTrace("vpnplatform.py", str(e))
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 writeCredentials(addon): # Write the credentials file try: credentials_path = getCredentialsPath(addon) debugTrace("Writing VPN credentials file to " + credentials_path) credentials = open(credentials_path,'w') credentials.truncate() credentials.close() credentials = open(credentials_path,'a') credentials.write(addon.getSetting("vpn_username")+"\n") credentials.write(addon.getSetting("vpn_password")+"\n") credentials.close() except: errorTrace("common.py", "Couldn't create credentials file " + credentials_path) return False xbmc.sleep(500) return True
def getServices(): # Get the list of services rc, api_data = sendAPI("?action=getAllVpnDetails", "Retrieving list of services", "", True) if not rc: return None # Extract and return the list of service levels the user is entitled to try: services = [] service_list = "" for item in api_data["data"]: services.append(item["eAccountType"] +";" + str(item["iVpnId"])) service_list = service_list + item["eAccountType"] + ", (" + str(item["iVpnId"]) + ") " debugTrace("Found services " + service_list) return services except Exception as e: errorTrace("alternativeShellfire.py", "Couldn't parse the data that came back when listing the serice levels") errorTrace("alternativeShellfire.py", str(e)) return None
def checkPidofCommand(addon): # Disable this for now as kodi.bin may not exist on all systems return True # Only necessary with Linux, sees if pidof is installed/working p = getPlatform() if p == platforms.RPI or p == platforms.LINUX: # Issue Linux command command = getPidofPath() + " kodi.bin > " + getTestFilePath( ) + " 2>&1 &" if useSudo(): command = "sudo " + command infoTrace("vpnplatform.py", "Testing pidof with : " + command) os.system(command) else: return True # Waiting for the log file to appear xbmc.sleep(1000) i = 0 while not xbmcvfs.exists(getTestFilePath()) and i < 10: xbmc.sleep(1000) i = i + 1 # If the log file appears, check it's what we expect if xbmcvfs.exists(getTestFilePath()): log_file = open(getTestFilePath(), 'r') log_file_lines = log_file.readlines() log_file.close() # If this worked, the first line should be a number for line in log_file_lines: line = line.strip() if line.isdigit(): deleteTestFile() return True # Write the log file in case there's something in it errorTrace("vpnplatform.py", "Ran pidof command and it failed") writeTestFile() dialog_msg = "The command 'pidof' is required to run this add-on. Please install it and ensure it's available on the command path." else: errorTrace("vpnplatform.py", "Ran pidof command and the log didn't appear") dialog_msg = "The 'pidof' command isn't writing out a response. Try changing the Kodi log directory setting in Settings-Debug menu and retry." # Display an error message xbmcgui.Dialog().ok(addon.getAddonInfo("name"), dialog_msg) return False
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 checkKillallCommand(addon): # Only necessary with Linux, sees if killall is installed/working p = getPlatform() if p == platforms.RPI or p == platforms.LINUX: # Issue Linux command command = getKillallPath() + " vpnmanagertest > " + getTestFilePath( ) + " 2>&1 &" if useSudo(): command = "sudo " + command infoTrace("vpnplatform.py", "Testing killall with : " + command) os.system(command) else: return True # Waiting for the log file to appear xbmc.sleep(1000) i = 0 while not xbmcvfs.exists(getTestFilePath()) and i < 10: xbmc.sleep(1000) i = i + 1 # If the log file appears, check it's what we expect if xbmcvfs.exists(getTestFilePath()): log_file = open(getTestFilePath(), 'r') log_file_lines = log_file.readlines() log_file.close() # Look for a phrase we'd expect to see if the call # worked and a killall error message was displayed for line in log_file_lines: if "vpnmanagertest" in line: deleteTestFile() return True # Write the log file in case there's something in it errorTrace("vpnplatform.py", "Ran killall command and it failed") writeTestFile() dialog_msg = "The command 'killall' is required to run this add-on. Please install it and ensure it's available on the command path." else: errorTrace("vpnplatform.py", "Ran killall command and the log didn't appear") dialog_msg = "The 'killall' command isn't writing out a response. Try changing the Kodi log directory setting in Settings-Debug menu and retry." # Display an error message xbmcgui.Dialog().ok(addon.getAddonInfo("name"), dialog_msg) return False
def isVPNTaskRunning(): # Return True if the VPN task is still running, or the VPN connection is still active # Return False if the VPN task is no longer running and the connection is not active if fakeConnection(): return True p = getPlatform() if p == platforms.LINUX or p == platforms.RPI: try: command = "pidof openvpn" if useSudo(): command = "sudo " + command debugTrace("(Linux) Checking VPN task with " + command) pid = os.system(command) # This horrible call returns 0 if it finds a process, it's not returning the PID number if pid == 0: return True return False except: errorTrace("platform.py", "VPN task list failed") return False if p == platforms.WINDOWS: try: command = 'tasklist /FI "IMAGENAME eq OPENVPN.EXE"' debugTrace("(Windows) Checking VPN task with " + command) args = shlex.split(command) out = subprocess.check_output(args, creationflags=subprocess.SW_HIDE, shell=True).strip() if "openvpn.exe" in out: return True else: return False except: errorTrace("platform.py", "VPN task list failed") return False # **** ADD MORE PLATFORMS HERE **** return False
def makeButtonsFile(): # Use the buttons template to build a file to run at boot to check for a button press and run some commands addon = xbmcaddon.Addon("service.zomboided.tools") template_filename = xbmc.translatePath( "special://home/addons/service.zomboided.tools/BUTTONS.txt") python_filename = getButtonsPythonName() # Read the template file in try: if xbmcvfs.exists(template_filename): template_file = open(template_filename, 'r') template = template_file.readlines() template_file.close() i = 0 for line in template: if "#GPIOBUTTON" in line: template[i] = line.replace( "#GPIOBUTTON", addon.getSetting("button_gpio_number")) if "#GPIOLED" in line: template[i] = line.replace( "#GPIOLED", addon.getSetting("led_gpio_number")) if "#OSCOMMANDS" in line: commands = "" for j in range(1, 10): cmd = addon.getSetting("button_command_" + str(j)) if not cmd == "": if not j == 1: commands = commands + " " commands = commands + 'os.system("' + cmd + '")\n' else: break template[i] = line.replace("#OSCOMMANDS", commands) i += 1 except Exception as e: errorTrace("common.py", "Couldn't read the buttons template file") errorTrace("common.py", str(e)) return False # Write a new button file debugTrace("Writing an updated python button file") try: output = open(python_filename, 'w') for line in template: output.write(line) output.close() return True except Exception as e: errorTrace("common.py", "Couldn't write the new python buttons file") errorTrace("common.py", str(e)) return False
def getServices(): # Get the list of services rc, api_data = sendAPI("?action=getAllVpnDetails", "Retrieving list of services", "", True) if not rc: return None # Extract and return the list of service levels the user is entitled to try: services = [] service_list = "" for item in api_data["data"]: services.append(item["eAccountType"] + ";" + str(item["iVpnId"])) service_list = service_list + item["eAccountType"] + ", (" + str( item["iVpnId"]) + ") " debugTrace("Found services " + service_list) return services except Exception as e: errorTrace( "alternativeShellfire.py", "Couldn't parse the data that came back when listing the serice levels" ) errorTrace("alternativeShellfire.py", str(e)) return none
def copyLog(): addon = xbmcaddon.Addon("service.zomboided.tools") addon_name = addon.getAddonInfo("name") # Copy the log file log_path = "" dest_path = "" try: log_path = xbmc.translatePath("special://logpath/kodi.log") start_dir = "" dest_folder = xbmcgui.Dialog().browse( 0, "Select folder to copy log file into", "files", "", False, False, start_dir, False) dest_path = "kodi " + datetime.datetime.now().strftime( "%y-%m-%d %H-%M-%S") + ".log" dest_path = dest_folder + dest_path.replace(" ", "_") debugTrace("Copying " + log_path + " to " + dest_path) addon = xbmcaddon.Addon("service.zomboided.tools") infoTrace( "managefiles.py", "Copying log file to " + dest_path + ". Using version " + addon.getSetting("version_number")) xbmcvfs.copy(log_path, dest_path) if not xbmcvfs.exists(dest_path): raise IOError('Failed to copy log ' + log_path + " to " + dest_path) dialog_message = "Copied log file to:\n" + dest_path except: errorTrace("managefiles.py", "Failed to copy log from " + log_path + " to " + dest_path) if xbmcvfs.exists(log_path): dialog_message = "Error copying log, try copying it to a different location." else: dialog_messsage = "Could not find the kodi.log file." errorTrace("managefiles.py", dialog_message + " " + log_path + ", " + dest_path) xbmcgui.Dialog().ok("Log Copy", dialog_message)
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 getButtonCommands(): # Use button activated commands from a userdata file instead of entering them addon = xbmcaddon.Addon("service.zomboided.tools") filename = xbmc.translatePath( "special://userdata/addon_data/service.zomboided.tools/COMMANDS.txt") # This will just warn the user on the settings screen we're using a file instead if xbmcvfs.exists(filename): addon.setSetting("button_override", "true") else: addon.setSetting("button_override", "false") if addon.getSetting("button_enabled") == "true": # Check if there's a bunch of commands in userdata to use instead try: if xbmcvfs.exists(filename): # Read the commands file and update settings commands_file = open(filename, 'r') commands = commands_file.readlines() commands_file.close() i = 1 for command in commands: command = command.strip(' \t\n\r') # Ignore lines beginning with a # if not command.startswith("#"): addon.setSetting("button_command_" + str(i), command) i += 1 if i == 11: break # Clear out any old commands for j in range(i, 10): addon.setSetting("button_command_" + str(j), "") except Exception as e: errorTrace( "common.py", "Couldn't use the userdata COMMANDS.txt file to populate the settings" ) errorTrace("common.py", str(e))
def getVPNConnectionStatus(): # Open the openvpn output file and parse it for known phrases # Return 'connected', 'auth failed', 'network failed', 'error' or '' if fakeConnection(): return connection_status.UNKNOWN # **** ADD MORE PLATFORMS HERE **** # Might not need to mess with this too much if the log output from openvpn is the same p = getPlatform() if p == platforms.LINUX or p == platforms.RPI: path = getVPNLogFilePath() state = connection_status.UNKNOWN if xbmcvfs.exists(path): debugTrace("Reading log file") log = open(path, 'r') lines = log.readlines() for line in lines: if "Initialization Sequence Completed" in line: state = connection_status.CONNECTED break if "AUTH_FAILED" in line: state = connection_status.AUTH_FAILED if "TLS Error" in line: state = connection_status.NETWORK_FAILED if "Connection timed out" in line: state = connection_status.TIMEOUT log.close() # Haven't found what's expected so return an empty stream if not state == connection_status.UNKNOWN: debugTrace("VPN connection status is " + str(state)) return state else: errorTrace( "platform.py", "Tried to get VPN connection status but log file didn't exist") return connection_status.ERROR
# This forces a connection validation after something stops playing if player.isPlaying(): playing = True if playing and not player.isPlaying(): playing = False timer = connection_retry_time + 1 # This just checks the connection is still good every hour, providing the player is not busy if vpn_setup and not player.isPlaying() and timer > connection_retry_time: addon = xbmcaddon.Addon() if addon.getSetting("vpn_reconnect") == "true": debugTrace("Reconnect timer triggered, checking connection") if not isVPNConnected() and not (getVPNState() == "off"): # Don't know why we're disconnected, but reconnect to the last known VPN errorTrace("service.py", "VPN monitor service detected VPN connection " + getVPNProfile() + " is not running when it should be") writeVPNLog() if getVPNRequestedProfile() == "": setVPNRequestedProfile(getVPNProfile()) setVPNRequestedProfileFriendly(getVPNProfileFriendly()) setVPNProfile("") setVPNProfileFriendly("") reconnect_vpn = True timer = 0 # Check to see if it's time for a reboot (providing we need to, and nothing is playing) if (not player.isPlaying()) and reboot_timer >= seconds_to_reboot_check: addon = xbmcaddon.Addon() reboot_timer = 0 # Assume the next check is in an hour seconds_to_reboot_check = 3600
if not getVPNRequestedProfile() == "": progress.close() xbmcgui.Dialog().ok(addon_name, "Connection to VPN being attempted and will be aborted. Try again in a few seconds.") setAPICommand("Disconnect") success = False if success: # Stop the VPN monitor xbmc.sleep(100) progress.update(0, progress_title, "Pausing VPN monitor...") xbmc.sleep(100) if not stopService(): progress.close() # Display error result in an ok dialog errorTrace("resetVPN.py", "VPN monitor service is not running, can't reset VPNs") xbmcgui.Dialog().ok(progress_title, "Error, Service not running. Check log and re-enable.") success = False # Disconnect and reset all connections if success: progress.update(20, progress_title, "VPN monitor paused") xbmc.sleep(DIALOG_SPEED) progress.update(40, progress_title, "Stopping any active VPN connection...") xbmc.sleep(100) resetVPNConnections(addon) # Reset any validated values addon.setSetting("vpn_provider_validated", "") addon.setSetting("vpn_username_validated", "") addon.setSetting("vpn_password_validated", "")
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 = getAddonList(vpn_provider, "*.ovpn") # 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) for connection in ovpn_connections: try: f = open(connection, 'r+') debugTrace("Processing file " + connection) lines = f.readlines() f.seek(0) f.truncate() # Get the profile friendly name in case we need to generate key/cert names name = connection[connection.rfind(getSeparator())+1:] # Update the necessary values in the ovpn file for line in lines: # Update path to pass.txt if not isUserDefined(vpn_provider) or addon.getSetting("user_def_credentials") == "true": if line.startswith("auth-user-pass"): line = "auth-user-pass " + getAddonPathWrapper(vpn_provider + "/" + "pass.txt\n") # Update port numbers if line.startswith("remote "): 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" # Update user cert and key if usesUserKeys(vpn_provider): if line.startswith("cert "): line = "cert " + getUserDataPathWrapper(vpn_provider + "/" + getCertName(vpn_provider, name) + "\n") if line.startswith("key "): line = "key " + getUserDataPathWrapper(vpn_provider + "/" + getKeyName(vpn_provider, name) + "\n") # For user defined profile we need to replace any path tags with the addon dir path if isUserDefined(vpn_provider): line = line.replace("#PATH", getAddonPathWrapper(vpn_provider)) # Set the logging level if line.startswith("verb "): line = "verb " + verb_value + "\n" f.write(line) f.close() except: errorTrace("vpnproviders.py", "Failed to update ovpn file") return False # Flag that the files have been generated writeGeneratedFile(vpn_provider) return True
def connectVPN(connection_order, vpn_profile): # Don't know where this was called from so using plugin name to get addon handle addon = xbmcaddon.Addon("service.vpn.manager") addon_name = addon.getAddonInfo("name") # If we've not arrived here though the addon (because we've used the add-on setting # on the option menu), we want to surpress running the wizard as there's no need. addon.setSetting("vpn_wizard_run", "true") # Check openvpn installed and runs if not addon.getSetting("checked_openvpn") == "true": if checkVPNInstall(addon): addon.setSetting("checked_openvpn", "true") else: return if not addon.getSetting("ran_openvpn") == "true": stopVPN() if checkVPNCommand(addon): addon.setSetting("ran_openvpn", "true") else: return # The VPN protocol can be blank if this is a new run and the wizard is being used. # Force it to UDP as that's the most optimal and let them change in the settings. vpn_protocol = addon.getSetting("vpn_protocol") if vpn_protocol == "": addon.setSetting("vpn_protocol", "UDP") vpn_protocol = "UDP" # Do some stuff to set up text used in dialog windows connection_title = "" # Adjust strings below if changing number of conn_max if connection_order == "0" : connection_title = "" if connection_order == "1" : connection_title = " first" if connection_order == "2" : connection_title = " second" if connection_order == "3" : connection_title = " third" if connection_order == "4" : connection_title = " fourth" if connection_order == "5" : connection_title = " fifth" if connection_order == "6" : connection_title = " sixth" if connection_order == "7" : connection_title = " seventh" if connection_order == "8" : connection_title = " eighth" if connection_order == "9" : connection_title = " ninth" if connection_order == "10" : connection_title = " tenth" state = "" forceCycleLock() # Display a progress dialog box (put this on the screen quickly before doing other stuff) progress = xbmcgui.DialogProgress() progress_title = "Connecting to" + connection_title + " VPN." progress.create(addon_name,progress_title) debugTrace(progress_title) # Pause the monitor service progress_message = "Pausing VPN monitor." progress.update(1, progress_title, progress_message) if not stopService(): progress.close() # Display error result in an ok dialog errorTrace("common.py", "VPN monitor service is not running, can't start VPN") xbmcgui.Dialog().ok(progress_title, "Error, Service not running.\nCheck log and re-enable.") return if not progress.iscanceled(): progress_message = "VPN monitor paused." debugTrace(progress_message) progress.update(5, progress_title, progress_message) xbmc.sleep(500) # Stop any active VPN connection if not progress.iscanceled(): progress_message = "Stopping any active VPN connection." progress.update(6, progress_title, progress_message) stopVPNConnection() if not progress.iscanceled(): progress_message = "Disconnected from VPN." progress.update(10, progress_title, progress_message) xbmc.sleep(500) # Install the VPN provider existing_connection = "" if not progress.iscanceled(): vpn_provider = addon.getSetting("vpn_provider") # This is some code to copy the user name from a default file rather than use the user entered values. # It exists to help development where swapping between providers constantly is tedious. default_path = getUserDataPath(getVPNLocation(vpn_provider) + "/DEFAULT.txt") if connection_order == "1" and xbmcvfs.exists(default_path): default_file = open(default_path, 'r') default = default_file.readlines() default_file.close() default_value = default[0].strip(' \t\n\r') addon.setSetting("vpn_username", default_value) default_value = default[1].strip(' \t\n\r') addon.setSetting("vpn_password", default_value) # Reset the username/password if it's not being used if not usesPassAuth(vpn_provider): addon.setSetting("vpn_username", "") addon.setSetting("vpn_password", "") vpn_username = addon.getSetting("vpn_username") vpn_password = addon.getSetting("vpn_password") # Reset the setting indicating we've a good configuration for just this connection if not connection_order == "0": existing_connection = addon.getSetting(connection_order + "_vpn_validated") addon.setSetting(connection_order + "_vpn_validated", "") addon.setSetting(connection_order + "_vpn_validated_friendly", "") last_provider = addon.getSetting("vpn_provider_validated") last_credentials = addon.getSetting("vpn_username_validated") + " " + addon.getSetting("vpn_password_validated") if last_provider == "" : last_provider = "?" # Provider or credentials we've used previously have changed so we need to reset all validated connections vpn_credentials = vpn_username + " " + vpn_password if not last_provider == vpn_provider: last_credentials = "?" if not last_credentials == vpn_credentials: debugTrace("Credentials have changed since last time lthrough so need to revalidate") resetVPNConfig(addon, 1) # Generate or fix the OVPN files if we've not done this previously provider_gen = True if not progress.iscanceled(): if not ovpnFilesAvailable(getVPNLocation(vpn_provider)): # Fetch the list of locations available. If there are multiple, the user can select locations = getLocationFiles(getVPNLocation(vpn_provider)) default_label = "Default" i = 0 for location in locations: locations[i] = location[location.index("LOCATIONS")+10:location.index(".txt")] if locations[i] == "" : locations[i] = default_label i = i + 1 selected_profile = "" if len(locations) == 0: errorTrace("common.py", "No LOCATIONS.txt files found in VPN directory. Cannot generate ovpn files.") if len(locations) > 1: selected_location = xbmcgui.Dialog().select("Select connections profile", locations) selected_profile = locations[selected_location] if selected_profile == default_label : selected_profile = "" addon.setSetting("vpn_locations_list", selected_profile) progress_message = "Setting up VPN provider " + vpn_provider + "." progress.update(11, progress_title, progress_message) # Delete any old files in other directories debugTrace("Deleting all generated ovpn files") removeGeneratedFiles() # Generate new ones try: provider_gen = fixOVPNFiles(getVPNLocation(vpn_provider), selected_profile) except: errorTrace("Couldn't generate new .ovpn files") provider_gen = False xbmc.sleep(500) if provider_gen: if not progress.iscanceled(): progress_message = "Using VPN provider " + vpn_provider progress.update(15, progress_title, progress_message) xbmc.sleep(500) # Set up user credentials file if not progress.iscanceled() and usesPassAuth(vpn_provider): credentials_path = getCredentialsPath(addon) debugTrace("Attempting to use the credentials in " + credentials_path) if (not last_credentials == vpn_credentials) or (not xbmcvfs.exists(credentials_path)) or (not connectionValidated(addon)): progress_message = "Configuring authentication settings for user " + vpn_username + "." progress.update(16, progress_title, progress_message) provider_gen = writeCredentials(addon) got_keys = True keys_copied = True cancel_attempt = False cancel_clear = False if provider_gen: ovpn_name = "" if not progress.iscanceled(): if usesPassAuth(vpn_provider): progress_message = "Using authentication settings for user " + vpn_username + "." else: progress_message = "User authentication not used with " + vpn_provider + "." progress.update(19, progress_title, progress_message) xbmc.sleep(500) # Display the list of connections if not progress.iscanceled(): if not connection_order == "0": debugTrace("Displaying list of connections") all_connections = getProfileList(vpn_provider) ovpn_connections = getFilteredProfileList(all_connections, vpn_protocol, addon) ovpn_connections.sort() connections = getFriendlyProfileList(vpn_provider, ovpn_connections) if len(connections) > 0: if existing_connection == "": cancel_text = "[I]Cancel connection attempt[/I]" else: cancel_text = "[I]Cancel connection attempt and clear connection[/I]" cancel_clear = True connections.append(cancel_text) selected_connection = xbmcgui.Dialog().select("Select " + connection_title + " VPN profile", connections) # Based on the value selected, get the path name to the ovpn file ovpn_name = connections[selected_connection] if ovpn_name == cancel_text: ovpn_name = "" cancel_attempt = True else: ovpn_connection = ovpn_connections[selected_connection] else: ovpn_name = getFriendlyProfileName(vpn_provider, vpn_profile) ovpn_connection = vpn_profile if not progress.iscanceled() and not ovpn_name == "": # Fetch the key from the user if one is needed if usesUserKeys(getVPNLocation(vpn_provider)): # If a key already exists, skip asking for it if not (gotKeys(getVPNLocation(vpn_provider), ovpn_name)): # Stick out a helpful message if this is first time through if not gotKeys(getVPNLocation(vpn_provider), ""): xbmcgui.Dialog().ok(addon_name, vpn_provider + " provides unique key and certificate files to authenticate, typically called [I]client.key and client.crt[/I] or [I]user.key and user.crt[/I]. Make these files available on an accessable drive or USB key.") # Get the last directory browsed to avoid starting from the top start_dir = xbmcgui.Window(10000).getProperty("VPN_Manager_User_Directory") if usesSingleKey(getVPNLocation(vpn_provider)): select_title = "Select the user key file to use for all connections" else: select_title = "Select the user key file to use for this individual connection" key_file = xbmcgui.Dialog().browse(1, select_title, "files", ".key", False, False, start_dir, False) if key_file.endswith(".key"): start_dir = os.path.dirname(key_file) + getSeparator() if usesSingleKey(getVPNLocation(vpn_provider)): select_title = "Select the user certificate file to use for all connections" else: select_title = "Select the user certificate file to use for this individual connection" crt_file = xbmcgui.Dialog().browse(1, select_title, "files", ".crt", False, False, start_dir, False) if crt_file.endswith(".crt"): start_dir = os.path.dirname(crt_file) + getSeparator() xbmcgui.Window(10000).setProperty("VPN_Manager_User_Directory", start_dir) keys_copied = copyKeyAndCert(getVPNLocation(vpn_provider), ovpn_name, key_file, crt_file) got_keys = keys_copied else: got_keys = False else: got_keys = False # Try and connect to the VPN provider using the entered credentials if not progress.iscanceled() and not ovpn_name == "" and got_keys: progress_message = "Connecting using profile " + ovpn_name + "." debugTrace(progress_message) # Start the connection and wait a second before starting to check the state startVPN(ovpn_connection) i = 0 # Bad network takes over a minute to spot so loop for a bit longer (each loop is 2 seconds) loop_max = 38 if fakeConnection(): loop_max = 2 percent = 20 while i <= loop_max: progress.update(percent, progress_title, progress_message) xbmc.sleep(2000) state = getVPNConnectionStatus() if not (state == connection_status.UNKNOWN or state == connection_status.TIMEOUT) : break if progress.iscanceled(): break i = i + 1 percent = percent + 2 # Mess with the state to make it look as if we've connected to a VPN if fakeConnection() and not progress.iscanceled() and provider_gen and not ovpn_name == "" and got_keys: state = connection_status.CONNECTED # Determine what happened during the connection attempt if state == connection_status.CONNECTED : # Success, VPN connected! Display an updated progress window whilst we work out where we're connected to progress_message = "Connected, restarting VPN monitor." progress.update(97, progress_title, progress_message) # Set the final message to indicate success progress_message = "Connected, VPN monitor restarted." _, ip, country, isp = getIPInfo(addon) dialog_message = "Connected to a VPN in " + country + ".\nUsing profile " + ovpn_name + ".\nExternal IP address is " + ip + ".\nService Provider is " + isp + "." infoTrace("common.py", dialog_message) if ifDebug(): writeVPNLog() # Store that setup has been validated and the credentials used setVPNProfile(ovpn_connection) setVPNProfileFriendly(ovpn_name) if not connection_order == "0": addon.setSetting("vpn_provider_validated", vpn_provider) addon.setSetting("vpn_username_validated", vpn_username) addon.setSetting("vpn_password_validated", vpn_password) addon.setSetting(connection_order + "_vpn_validated", ovpn_connection) addon.setSetting(connection_order + "_vpn_validated_friendly", ovpn_name) setVPNState("started") setVPNRequestedProfile("") setVPNRequestedProfileFriendly("") setVPNLastConnectedProfile("") setVPNLastConnectedProfileFriendly("") setConnectionErrorCount(0) # Indicate to the service that it should update its settings updateService() elif progress.iscanceled() or cancel_attempt: # User pressed cancel. Don't change any of the settings as we've no idea how far we got # down the path of installing the VPN, configuring the credentials or selecting the connection # We're assuming here that if the VPN or user ID has been changed, then the connections are invalid # already. If the cancel happens during the connection validation, we can just use the existing one. # Set the final message to indicate user cancelled operation progress_message = "Cancelling connection attempt, restarting VPN monitor." progress.update(97, progress_title, progress_message) # Set the final message to indicate cancellation progress_message = "Cancelling connection attempt, VPN monitor restarted." # Restore the previous connection info dialog_message = "Cancelled connection attempt.\n" if not connection_order == "0": if not isVPNConnected(): if cancel_clear: dialog_message = dialog_message + "This connection has been removed from the list of valid connections." else: dialog_message = dialog_message + "This connection has not been validated." resetVPNConfig(addon, int(connection_order)) else: dialog_message = dialog_message + "Please reconnect." # Don't know how far we got, if we were trying to connect and then got cancelled, # there might still be an instance of openvpn running we need to kill stopVPN() else: # An error occurred, The current connection is already invalidated. The VPN credentials might # be ok, but if they need re-entering, the user must update them which will force a reset. progress_message = "Error connecting to VPN, restarting VPN monitor." progress.update(97, progress_title, progress_message) xbmc.sleep(500) # Set the final message to show an error occurred progress_message = "Error connecting to VPN, VPN monitor restarted." # First set of errors happened prior to trying to connect if not provider_gen: dialog_message = "Error creating OVPN or credentials file for provider.\nCheck log to determine cause of failure." elif not got_keys: if not keys_copied: dialog_message = "Failed to copy supplied user key and cert files.\nCheck log and retry." else: dialog_message = "User key and certificate files are required, but were not provided. Locate the files and try again." elif ovpn_name == "": dialog_message = "No unused VPN profiles were available for " + vpn_protocol + " protocol.\nChange VPN provider settings." else: # This second set of errors happened because we tried to connect and failed if state == connection_status.AUTH_FAILED: dialog_message = "Error connecting to VPN, authentication failed.\nCheck your username and password." credentials_path = getCredentialsPath(addon) if not connection_order == "0": addon.setSetting("vpn_username_validated", "") addon.setSetting("vpn_password_validated", "") elif state == connection_status.NETWORK_FAILED: dialog_message = "Error connecting to VPN, could not estabilish connection.\nCheck your username, password and network connectivity and retry." elif state == connection_status.TIMEOUT: dialog_message = "Error connecting to VPN, connection has timed out.\nTry using a different VPN profile or retry." else: dialog_message = "Error connecting to VPN, something unexpected happened.\nRetry to check openvpn operation and then check log." addon.setSetting("ran_openvpn", "false") # Output what when wrong with the VPN to the log writeVPNLog() if not connection_order == "0" : resetVPNConfig(addon, int(connection_order)) errorTrace("common.py", dialog_message) # The VPN might be having a spaz still so we want to ensure it's stopped stopVPN() # Restart service if not startService(): progress.close() errorTrace("common.py", "VPN monitor service is not running, VPN has started") dialog_message = "Error, Service not running.\nCheck log and reboot." else: # Close out the final progress dialog progress.update(100, progress_title, progress_message) xbmc.sleep(500) progress.close() freeCycleLock() # Display connection result in an ok dialog xbmcgui.Dialog().ok(progress_title, dialog_message) # Refresh the screen if this is not being done on settings screen if connection_order == "0" : xbmc.executebuiltin('Container.Refresh')
show_filters = False elif filters[i] == id_reset: # Delete all of the filters if len(filters) > 5: del filters[0:len(filters)-5] elif filters[i] == id_single: # Ask user for window ID new_filter = editSingle("") if not new_filter == "": filters.insert(len(filters)-5, new_filter) elif filters[i] == id_range: # Ask user for range of window IDs new_filter = editRange("") if not new_filter == "": filters.insert(len(filters)-5, new_filter) else: # Edit or delete an existing filter if not xbmcgui.Dialog().yesno(addon_name, "Edit or delete window ID filter " + filters[i] + "?", nolabel="Edit", yeslabel="Delete"): if "-" in filters[i]: new_filter = editRange(filters[i]) else: new_filter = editSingle(filters[i]) if not new_filter == "": filters.insert(len(filters)-5, new_filter) else: del filters[i] command = "Addon.OpenSettings(" + getID() + ")" xbmc.executebuiltin(command) else: errorTrace("windowfilter.py", "VPN service is not ready") debugTrace("-- Exit windowfilter.py --")
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
title = "Connected - " + getVPNProfileFriendly() connections.insert(0, disconnect_text) else: title = "Disconnected" connections.insert(0, disconnected_text) connections.append(cancel_text) i = xbmcgui.Dialog().select(title, connections) if connections[i] == disconnect_text or connections[i] == disconnected_text: setAPICommand("Disconnect") elif not connections[i] == cancel_text: if getVPNProfile() == location_connections[i-1] and (allowReconnection(vpn_provider) or addon.getSetting("allow_cycle_reconnect") == "true"): setAPICommand("Reconnect") else: if isAlternative(vpn_provider) and addon.getSetting("table_display_type") == "All connections": _, connection, user_text, ignore = getAlternativeLocation(vpn_provider, connections[i], 0, True) if not ignore and not user_text == "": xbmcgui.Dialog().ok(addon_name, user_text) else: connection = location_connections[i-1] if not connection == "": setAPICommand(connection) freeCycleLock() else: xbmcgui.Dialog().notification(addon_name, "VPN is not set up and authenticated.", xbmcgui.NOTIFICATION_ERROR, 10000, True) else: errorTrace("table.py", "VPN service is not ready") debugTrace("-- Exit table.py --")
setAPICommand("Restart") elif lcommand == "reconnect": setAPICommand("Reconnect") elif lcommand == "getip": setAPICommand("GetIP") elif lcommand.startswith("connect"): connection = command[8:].strip(' \t\n\r') if connection.isdigit(): c = int(connection) addon = xbmcaddon.Addon(getID()) # Adjust the 11 below to change conn_max if c > 0 and c < 11: connection = addon.getSetting(str(c) + "_vpn_validated") if not connection == "": setAPICommand(connection) else: errorTrace("api.py", "Connection requested, " + str(c) + " has not been validated") else: errorTrace("api.py", "Invalid connection, " + str(c) + " requested") else: if xbmcvfs.exists(connection): setAPICommand(connection) else: errorTrace("api.py", "Requested connection, " + connection + " does not exist") else: errorTrace("api.py", "Unrecognised command: " + command) else: errorTrace("api.py", "VPN service is not ready") debugTrace("-- Exit api.py --")
def sendAPI(command, command_text, api_data, check_response): # Common routine to send an API command try: response = "" rc = True rest_url = REQUEST_URL + command auth_token,_,_,_ = getTokens() # Login again if the token is blank and the command is not login anyway if auth_token == "" and not "=login" in command: debugTrace("Logging in again because auth token not valid") addon = xbmcaddon.Addon(getID()) rc = authenticateShellfire(addon.getSetting("vpn_provider"), addon.getSetting("vpn_username"), addon.getSetting("vpn_password")) auth_token,_,_,_ = getTokens() if auth_token == "" or not rc: raise Exception(command_text + " was not authorized") if ifHTTPTrace(): infoTrace("alternativeShellfire.py", command_text + " " + rest_url) else: debugTrace(command_text) req = urllib2.Request(rest_url, api_data, REQUEST_HEADERS) if not auth_token == "": req.add_header("x-authorization-token", auth_token) t_before = now() response = urllib2.urlopen(req) api_data = json.load(response) t_after = now() response.close() # Trace if the command took a long time if ifJSONTrace(): infoTrace("alternativeShellfire.py", "JSON received is \n" + json.dumps(api_data, indent=4)) if t_after - t_before > TIME_WARN: infoTrace("alternativeShellfire.py", command_text + " took " + str(t_after - t_before) + " seconds") # Check the response and fail if it's bad if check_response: if not api_data["status"] == "success": raise Exception(command_text + " returned bad response, " + api_data["status"]) except urllib2.HTTPError as e: errorTrace("alternativeShellfire.py", command_text + " failed") errorTrace("alternativeShellfire.py", "API call was " + rest_url) if not api_data == "": errorTrace("alternativeShellfire.py", "Data returned was \n" + json.dumps(api_data, indent=4)) errorTrace("alternativeShellfire.py", "Response was " + str(e.code) + " " + e.reason) errorTrace("alternativeShellfire.py", e.read()) rc = False except Exception as e: errorTrace("alternativeShellfire.py", command_text + " failed") errorTrace("alternativeShellfire.py", "API call was " + rest_url) if not api_data == "": errorTrace("alternativeShellfire.py", "Data returned was \n" + json.dumps(api_data, indent=4)) errorTrace("alternativeShellfire.py", "Response was " + str(type(e)) + " " + str(e)) rc = False return rc, api_data
dest_path = "" try: log_path = getLogPath() start_dir = "" dest_folder = xbmcgui.Dialog().browse(0, "Select folder to copy log file into", "files", "", False, False, start_dir, False) dest_path = "kodi " + datetime.datetime.now().strftime("%y-%m-%d %H-%M-%S") + ".log" dest_path = dest_folder + dest_path.replace(" ", "_") # Write VPN log to log before copying writeVPNLog() debugTrace("Copying " + log_path + " to " + dest_path) addon = xbmcaddon.Addon("service.vpn.manager") infoTrace("managefiles.py", "Copying log file to " + dest_path + ". Using version " + addon.getSetting("version_number")) xbmcvfs.copy(log_path, dest_path) dialog_message = "Copied log file to:\n" + dest_path except: errorTrace("Failed to copy log from " + log_path + " to " + dest_path) if xbmcvfs.exists(log_path): dialog_message = "Error copying log, try copying it to a different location." else: dialog_messsage = "Could not find the kodi.log file." errorTrace("managefiles.py", dialog_message + " " + log_path + ", " + dest_path) xbmcgui.Dialog().ok("Log Copy", dialog_message) # Delete the user key and cert files elif action == "user": if addon.getSetting("1_vpn_validated") == "" or xbmcgui.Dialog().yesno(addon_name, "Deleting key and certificate files will reset all VPN connections. Connections must be re-validated before use.\nContinue?"): # Reset the connection before we do anything else if isVPNConnected(): resetVPNConnections(addon)
def getShellfirePreFetch(vpn_provider): # Fetch and store location info filename = getAddonPath(True, vpn_provider + "/" + SHELLFIRE_LOCATIONS) if xbmcvfs.exists(filename): try: st = xbmcvfs.Stat(filename) create_time = int(st.st_ctime()) t = now() # Fetch again if this is more than a day old otherwise use what there is if create_time + 86400 < t: debugTrace("Create time of " + filename + " is " + str(create_time) + " time now is " + str(t) + ", fetching location data again") else: debugTrace("Create time of " + filename + " is " + str(create_time) + " time now is " + str(t) + ", using existing data") # Less than a day old, so using the existing file return True except Exception as e: errorTrace("alternativeShellfire.py", "List of countries exist but couldn't get the time stamp for " + filename) errorTrace("alternativeShellfire.py", str(e)) return False # Download the list of locations error = True try: response = "" api_data = "" rest_url = "https://www.shellfire.de/webservice/serverlist.php" if ifHTTPTrace(): infoTrace("alternativeShellfire.py", "Downloading list of locations using " + rest_url) else: debugTrace("Downloading list of locations") # This is not a JSON call, a header and servers are returned in a ; separated list req = urllib2.Request(rest_url, "", REQUEST_HEADERS) t_before = now() response = urllib2.urlopen(req) api_data = response.read() t_after = now() response.close() if ifJSONTrace(): infoTrace("alternativeShellfire.py", "Text received is \n" + api_data) if t_after - t_before > TIME_WARN: infoTrace("alternativeShellfire.py", "Retrieving list of locations took " + str(t_after - t_before) + " seconds") except urllib2.HTTPError as e: errorTrace("alternativeShellfire.py", "Couldn't retrieve the list of locations") errorTrace("alternativeShellfire.py", "API call was " + rest_url) if not api_data == "": errorTrace("alternativeShellfire.py", "Data returned was \n" + api_data) errorTrace("alternativeShellfire.py", "Response was " + str(e.code) + " " + e.reason) errorTrace("alternativeShellfire.py", e.read()) return False except Exception as e: errorTrace("alternativeShellfire.py", "Couldn't retrieve the list of locations") errorTrace("alternativeShellfire.py", "API call was " + rest_url) if not api_data == "": errorTrace("alternativeShellfire.py", "Data returned was \n" + api_data) errorTrace("alternativeShellfire.py", "Response was " + str(type(e)) + " " + str(e)) return False # The first line has the headers, so find the position of the information that's interesting api_table = api_data.split("\n") headers = api_table[0].split(";") id_pos = headers.index("iVpnServerId") country_pos = headers.index("Country") city_pos = headers.index("sCity") host_pos = headers.index("sHost") type_pos = headers.index("eServerType") debugTrace("Header decoded. ID is " + str(id_pos) + ", Country is " + str(country_pos) + ", City is " + str(city_pos) + ", Host is " + str(host_pos) + ", Type is " + str(type_pos)) api_table[0] = "" try: line = "" cleaned_data = [] debugTrace("Parsing the text and extracting the country, server and type") for line in api_table: server_data = line.split(";") # Avoid parsing empty lines, or lines where there's not enough data if len(server_data) > 5: cleaned_data.append(server_data[country_pos] + " - " + server_data[city_pos] + " (S" + server_data[id_pos] + ")," + server_data[host_pos] + "," + server_data[type_pos] + "," + server_data[id_pos] + "\n") except Exception as e: errorTrace("alternativeShellfire`.py", "Couldn't parse the list of locations for " + vpn_provider) if not server_data == "": errorTrace("alternativeShellfire.py", "Processing line " + line) errorTrace("alternativeShellfire.py", str(e)) return False # Sort the locations alphabetically cleaned_data.sort() try: line = "" debugTrace("Parsing the text and writing the list of locations") output = open(filename, 'w') # Parse the data and create list containing the stuff we care about for line in cleaned_data: output.write(line) output.close() return True except Exception as e: errorTrace("alternativeShellfire`.py", "Couldn't write the list of locations for " + vpn_provider + " to " + filename) if not server_data == "": errorTrace("alternativeShellfire.py", "Processing server " + line) errorTrace("alternativeShellfire.py", str(e)) # Delete the location file if the was a problem creating it. This will force a download next time through try: if xbmcvfs.exists(filename): errorTrace("alternativeShellfire.py", "Deleting location file " + filename + " to clean up after previous error") xbmcvfs.delete(filename) except Exception as e: errorTrace("alternativeShellfire.py", "Couldn't delete the location file " + filename) errorTrace("alternativeShellfire.py", str(e)) 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 getShellfireLocationsCommon(vpn_provider, exclude_used, friendly, servers): # Return a list of all of the locations 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 + "/" + SHELLFIRE_LOCATIONS) # If the list of locations 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): 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 [] try: service = ACCOUNT_TYPES.index(getAccountType()) except Exception as e: errorTrace("alternativeShellfire.py", "Don't have an account for " + vpn_provider) errorTrace("alternativeShellfire.py", str(e)) return [] try: # Read the locations from the file and list by account type locations_file = open(filename, 'r') locations = locations_file.readlines() locations_file.close() return_locations = [] # List the free servers return_locations.append(TITLE_START + "Free Locations" + TITLE_END) for l in locations: country, server, type, server_id = l.split(",") server_id = server_id.strip(" \n") if type == ACCOUNT_TYPES[0]: if not exclude_used or not country in used: if friendly: return_locations.append(SERVER_START + country + SERVER_END) elif servers: return_locations.append(SERVER_START + server + SERVER_END) else: return_locations.append(type + getShellfireLocationName(vpn_provider, country)) # List the paid servers return_locations.append(TITLE_START + "Paid Locations" + TITLE_END) for l in locations: country, server, type, server_id = l.split(",") server_id = server_id.strip(" \n") if not type == ACCOUNT_TYPES[0]: if ACCOUNT_TYPES.index(type) > service: start = UPGRADE_START end = UPGRADE_END else: start = SERVER_START end = SERVER_END if not exclude_used or not country in used: if friendly: return_locations.append(start + country + end) elif servers: return_locations.append(start + server + end) else: return_locations.append(type + getShellfireLocationName(vpn_provider, country)) return return_locations 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 [] return []
def disconnectVPN(): # Don't know where this was called from so using plugin name to get addon handle addon = xbmcaddon.Addon("service.vpn.manager") addon_name = addon.getAddonInfo("name") debugTrace("Disconnecting the VPN") forceCycleLock() # Show a progress box before executing stop progress = xbmcgui.DialogProgress() progress_title = "Disconnecting from VPN." progress.create(addon_name,progress_title) # Pause the monitor service progress_message = "Pausing VPN monitor." progress.update(1, progress_title, progress_message) if not stopService(): progress.close() # Display error in an ok dialog, user will need to do something... errorTrace("common.py", "VPN monitor service is not running, can't stop VPN") xbmcgui.Dialog().ok(progress_title, "Error, Service not running.\nCheck log and reboot.") freeCycleLock() return xbmc.sleep(500) progress_message = "Stopping any active VPN connection." progress.update(1, progress_title, progress_message) # Kill the VPN connection if the user hasn't gotten bored waiting if not progress.iscanceled(): stopVPNConnection() xbmc.sleep(500) progress_message = "Disconnected from VPN, restarting VPN monitor" setVPNLastConnectedProfile("") setVPNLastConnectedProfileFriendly("") setVPNState("off") else: progress_message = "Disconnect cancelled, restarting VPN monitor" # Restart service if not startService(): progress.close() errorTrace("common.py", "VPN monitor service is not running, VPN has stopped") dialog_message = "Error, Service not running.\nCheck log and reboot." else: # Close out the final progress dialog progress.update(100, progress_title, progress_message) xbmc.sleep(500) progress.close() # Update screen and display result in an ok dialog xbmc.executebuiltin('Container.Refresh') _, ip, country, isp = getIPInfo(addon) dialog_message = "Disconnected from VPN.\nNetwork location is " + country + ".\nExternal IP address is " + ip + ".\nService Provider is " + isp infoTrace("common.py", "Disconnected from the VPN") freeCycleLock() xbmcgui.Dialog().ok(addon_name, dialog_message)
# it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # This module assists with the import of a user defined VPN provider import xbmc from libs.utility import debugTrace, errorTrace, infoTrace, newPrint, getID from libs.userdefined import importWizard debugTrace("Entered import.py") if not getID() == "": importWizard() # Return to the settings screen command = "Addon.OpenSettings(" + getID() + ")" xbmc.executebuiltin(command) else: errorTrace("import.py", "VPN service is not ready") debugTrace("Exit import.py")