raspap-webgui-mirror/includes/provider.php

316 lines
9.7 KiB
PHP
Executable file
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
require_once 'includes/config.php';
/*
* Display VPN provider configuration
*/
function DisplayProviderConfig()
{
// initialize status object
$status = new \RaspAP\Messages\StatusMessage;
// set defaults
$id = $_SESSION["providerID"];
$binPath = getProviderValue($id, "bin_path");
$providerName = getProviderValue($id, "name");
$providerVersion = getProviderVersion($id, $binPath);
$installPage = getProviderValue($id, "install_page");
$publicIP = get_public_ip();
$serviceStatus = 'down';
$statusDisplay = 'down';
if (!file_exists($binPath)) {
$status->addMessage(sprintf(_('Expected %s binary not found at: %s'), $providerName, $binPath), 'warning');
$status->addMessage(sprintf(_('Visit the <a href="%s" target="_blank">installation instructions</a> for %s\'s Linux CLI.'), $installPage, $providerName), 'warning');
$ctlState = 'disabled';
$providerVersion = 'not found';
} elseif (empty($providerVersion)) {
$status->addMessage(sprintf(_('Unable to execute %s binary found at: %s'), $providerName, $binPath), 'warning');
$status->addMessage(_('Check that binary is executable and permissions exist in raspap.sudoers'), 'warning');
$ctlState = 'disabled';
$providerVersion = 'not found';
} else {
// fetch provider status
$serviceStatus = getProviderStatus($id, $binPath);
$statusDisplay = $serviceStatus == "down" ? "inactive" : "active";
// fetch provider log
$providerLog = getProviderLog($id, $binPath, $country);
// fetch account info
$accountInfo = getAccountInfo($id, $binPath, $providerName);
$accountLink = getProviderValue($id, "account_page");
// fetch available countries
$countries = getCountries($id, $binPath);
}
if (!RASPI_MONITOR_ENABLED) {
if (isset($_POST['SaveProviderSettings'])) {
if (isset($_POST['country'])) {
$country = trim($_POST['country']);
if (strlen($country) == 0) {
$status->addMessage('Select a country from the server location list', 'danger');
} else {
$return = saveProviderConfig($status, $binPath, $country, $id);
}
}
} elseif (isset($_POST['StartProviderVPN'])) {
$status->addMessage('Attempting to connect VPN provider', 'info');
$cmd = getCliOverride($id, 'cmd_overrides', 'connect');
exec("sudo $binPath $cmd", $return);
$return = stripArtifacts($return);
foreach ($return as $line) {
if (strlen(trim($line)) > 0) {
$line = preg_replace('/\e\[\?[0-9]*l\s(.*)\e.*$/', '$1', $line);
$line = preg_replace('/\e\[0m\e\[[0-9;]*m(.*)/', '$1', $line);
$status->addMessage($line, 'info');
}
}
} elseif (isset($_POST['StopProviderVPN'])) {
$status->addMessage('Attempting to disconnect VPN provider', 'info');
$cmd = getCliOverride($id, 'cmd_overrides', 'disconnect');
exec("sudo $binPath $cmd", $return);
$return = stripArtifacts($return);
foreach ($return as $line) {
if (strlen(trim($line)) > 0) {
$line = preg_replace('/\[1;33;49m(.*)\[0m/', '$1', $line);
$status->addMessage($line, 'info');
}
}
}
}
echo renderTemplate(
"provider", compact(
"status",
"serviceStatus",
"statusDisplay",
"providerName",
"providerVersion",
"accountInfo",
"accountLink",
"countries",
"country",
"providerLog",
"publicIP",
"ctlState"
)
);
}
/**
* Validates VPN provider settings
*
* @param object $status
* @param string $binPath
* @param string $country
* @param integer $id (optional)
*/
function saveProviderConfig($status, $binPath, $country, $id = null)
{
$status->addMessage(sprintf(_('Attempting to connect to %s'),$country), 'info');
$cmd = getCliOverride($id, 'cmd_overrides', 'connect');
// mullvad requires relay set location before connect
if ($id == 2) {
exec("sudo $binPath relay set location $country", $return);
exec("sudo $binPath $cmd", $return);
} else {
exec("sudo $binPath $cmd $country", $return);
}
$return = stripArtifacts($return);
foreach ($return as $line) {
if ( strlen(trim($line)) >0 ) {
$status->addMessage($line, 'info');
}
}
}
/**
* Removes artifacts from shell_exec string values
*
* @param string $output
* @param string $pattern
* @return string $result
*/
function stripArtifacts($output, $pattern = null)
{
$result = preg_replace('/[-\/\n\t\\\\'.$pattern.'|]/', '', $output);
return $result;
}
/**
* Retrieves an override for provider CLI
*
* @param integer $id
* @param string $group
* @param string $item
* @return string $override
*/
function getCliOverride($id, $group, $item)
{
$obj = json_decode(file_get_contents(RASPI_CONFIG_PROVIDERS), true);
if ($obj === null) {
return false;
} else {
$id--;
if ($obj['providers'][$id][$group][$item] === null) {
return $item;
} else {
return $obj['providers'][$id][$group][$item];
}
}
}
/**
* Retreives VPN provider status
*
* @param integer $id
* @param string $binPath
* @return string $status
*/
function getProviderStatus($id, $binPath)
{
$cmd = getCliOverride($id, 'cmd_overrides', 'status');
$pattern = getCliOverride($id, 'regex', 'status');
exec("sudo $binPath $cmd", $cmd_raw);
$cmd_raw = strtolower(stripArtifacts($cmd_raw[0]));
if (!empty($cmd_raw[0])) {
if (preg_match($pattern, $cmd_raw, $match)) {
$status = "down";
} else {
$status = "up";
}
} else {
$status = "down";
}
return $status;
}
/**
* Retrieves available countries
*
* @param integer $id
* @param string $binPath
* @return array $countries
*/
function getCountries($id, $binPath)
{
$countries = [];
$cmd = getCliOverride($id, 'cmd_overrides', 'countries');
$pattern = getCliOverride($id, 'regex', 'pattern');
$replace = getCliOverride($id, 'regex', 'replace');
$slice = getCliOverride($id, 'regex', 'slice');
exec("sudo $binPath $cmd", $output);
// CLI country output differs considerably between different providers.
// Ideally, custom parsing would be avoided in favor of a pure regex solution
switch ($id) {
case 1: // expressvpn
$output = array_slice($output, $slice);
foreach ($output as $item) {
$item = preg_replace($pattern, $replace, $item);
$parts = explode(',', $item);
$key = trim($parts[0]);
$value = trim($parts[1]);
$countries[$key] = $value;
}
break;
case 2: // mullvad
foreach ($output as $item) {
$item = preg_replace($pattern, $replace, $item);
if (strlen(trim($item) >0)) {
preg_match('/\s+([a-z0-9-]+)\s.*$/', $item, $match);
if (count($match) > 1) {
$key = $match[1];
$item = str_pad($item, strlen($item)+16,' ', STR_PAD_LEFT);
$countries[$key] = $item;
} else {
preg_match('/\(([a-z]+)\)/', $item, $match);
$key = $match[1];
if (strlen($match[1]) == 3) {
$item = str_pad($item, strlen($item)+8,' ', STR_PAD_LEFT);
}
$countries[$key] = $item;
}
}
}
break;
case 3: // nordvpn
$output = stripArtifacts($output,'\s');
$arrTmp = explode(",", $output[0]);
$countries = array_combine($arrTmp, $arrTmp);
foreach ($countries as $key => $value) {
$countries[$key] = str_replace("_", " ", $value);
}
break;
default:
break;
}
$select = array(' ' => _("Select a country..."));
$countries = $select + $countries;
return $countries;
}
/**
* Retrieves provider log
*
* @param integer $id
* @param string $binPath
* @param string $country
* @return string $log
*/
function getProviderLog($id, $binPath, &$country)
{
$cmd = getCliOverride($id, 'cmd_overrides', 'log');
exec("sudo $binPath $cmd", $cmd_raw);
$output = stripArtifacts($cmd_raw);
foreach ($output as $item) {
if (preg_match('/Country: (\w+)/', $item, $match)) {
$country = $match[1];
}
$providerLog.= ltrim($item) .PHP_EOL;
}
return $providerLog;
}
/**
* Retrieves provider version information
*
* @param integer $id
* @param string $binPath
* @return string $version
*/
function getProviderVersion($id, $binPath)
{
$cmd = getCliOverride($id, 'cmd_overrides', 'version');
$version = shell_exec("sudo $binPath $cmd");
$version = preg_replace('/^[^\w]+\s*/', '', $version);
return $version;
}
/**
* Retrieves provider account info
*
* @param integer $id
* @param string $binPath
* @param string $providerName
* @return array
*/
function getAccountInfo($id, $binPath, $providerName)
{
$cmd = getCliOverride($id, 'cmd_overrides', 'account');
exec("sudo $binPath $cmd", $acct);
foreach ($acct as &$item) {
$item = preg_replace('/^[^\w]+\s*/', '', $item);
}
if (empty($acct)) {
$msg = sprintf(_("Account information not available from %s's Linux CLI."), $providerName);
$acct[] = $msg;
}
return $acct;
}