500 lines
13 KiB
PHP
500 lines
13 KiB
PHP
<?php
|
|
|
|
/**
|
|
* vpanel-stack
|
|
* https://git.stack-source.com/msb/vpanel-stack
|
|
* Copyright (c) 2022 Matthew Saunders Brown <matthewsaundersbrown@gmail.com>
|
|
* GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
*/
|
|
|
|
class Panel {
|
|
|
|
function beforeRoute($f3) {
|
|
|
|
/* check for existing session */
|
|
if ($f3->exists('SESSION.expiration')) {
|
|
if ($f3->get('SESSION.expiration') > time()) {
|
|
$f3->set('SESSION.expiration', time() + $f3->get('TIMEOUT'));
|
|
if ($f3->get('PATH') == '/Login') {
|
|
$f3->reroute('/');
|
|
}
|
|
} else {
|
|
$f3->clear('SESSION.expiration');
|
|
$messages[] = "Login has expired. Please re-enter login info.";
|
|
$f3->set('SESSION.messages', $messages);
|
|
if ($f3->get('PATH') != '/Login') {
|
|
$f3->reroute('/Login');
|
|
}
|
|
}
|
|
} else {
|
|
if ($f3->get('PATH') != '/Login') {
|
|
$f3->reroute('/Login');
|
|
}
|
|
}
|
|
|
|
/* build subnav */
|
|
$nav_home = preg_replace('/^\//', '', $f3->get('BASE'));
|
|
$nav_path = $f3->get('PATH');
|
|
if ($nav_path != '/') {
|
|
$nav_parts = explode('/', $nav_path);
|
|
$nav_parts[0] = $nav_home;
|
|
$subnav = array();
|
|
$subnav_path = '';
|
|
foreach ($nav_parts as $k=>$v) {
|
|
$subnav_part = $v;
|
|
$subnav_path .= "/$subnav_part";
|
|
$subnav_name = str_replace('_', ' ', $v);
|
|
$subnav[$subnav_path] = $subnav_name;
|
|
}
|
|
array_shift($subnav);
|
|
$f3->set('NAV.subnav', $subnav);
|
|
$f3->set('NAV.subnav_count', count($subnav));
|
|
}
|
|
|
|
$f3->set('NAV.fullpath', preg_replace('/\/$/', '', $f3->get('REALM')));
|
|
|
|
}
|
|
|
|
public static function get($f3) {
|
|
/* If DNS admin is not enabled we need to display the server IP to be used for DNS settings */
|
|
if ($f3->get('VDNSADMIN') != '1') {
|
|
$f3->set('default_ip', $f3->get('SERVER.SERVER_ADDR'));
|
|
}
|
|
echo \Template::instance()->render('home.html');
|
|
}
|
|
|
|
public static function setPHPVersions($f3) {
|
|
|
|
$phpFPMVersion = readlink("/etc/alternatives/php-fpm.sock");
|
|
$phpFPMVersion = str_replace('/run/php/php', '', $phpFPMVersion);
|
|
$phpFPMVersion = str_replace('-fpm.sock', '', $phpFPMVersion);
|
|
exec("/usr/bin/update-alternatives --list php-fpm.sock | sed 's|/run/php/php||g' | cut -d \- -f 1", $phpFPMVersionsArray);
|
|
$f3->set('PHP.fpm_version', $phpFPMVersion);
|
|
$f3->set('PHP.fpm_versions_array', $phpFPMVersionsArray);
|
|
$f3->set('PHP.fpm_version_count', count($phpFPMVersionsArray));
|
|
|
|
}
|
|
|
|
public static function validateEmail($email) {
|
|
|
|
global $f3;
|
|
|
|
if (preg_match("/^[0-9A-z]([-_.+]?[0-9A-z])*@[0-9A-z]([-.]?[0-9A-z])*\.[A-z]{2,24}$/", $email)) {
|
|
return true;
|
|
} else {
|
|
$messages[] = "$email is not a validly formatted email address.";
|
|
if ($f3->exists('SESSION.messages')) {
|
|
$f3->set('SESSION.messages', array_merge($f3->get('SESSION.messages'), $messages));
|
|
} else {
|
|
$f3->set('SESSION.messages', $messages);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
public static function validateDomain ($domain) {
|
|
|
|
global $f3;
|
|
|
|
if (preg_match('/^[0-9a-z]([-.]?[0-9a-z])*\.[a-z]{2,24}$/i', $domain)) {
|
|
return true;
|
|
} else {
|
|
$messages[] = "$domain is not a validly formatted domain name.";
|
|
if ($f3->exists('SESSION.messages')) {
|
|
$f3->set('SESSION.messages', array_merge($f3->get('SESSION.messages'), $messages));
|
|
} else {
|
|
$f3->set('SESSION.messages', $messages);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
public static function validatePassword($password, $password_confirm) {
|
|
|
|
global $f3;
|
|
|
|
$messages = array();
|
|
|
|
if($password != $password_confirm) {
|
|
|
|
$messages[] = "Passwords do not match.";
|
|
|
|
}
|
|
|
|
if(strlen($password) < 8) {
|
|
|
|
$messages[] = "Password must be at least 8 characters long.";
|
|
|
|
}
|
|
|
|
if(strlen($password) < 15) {
|
|
|
|
$character_class = 0;
|
|
|
|
if (preg_match('/[[:lower:]]/', $password)) {
|
|
|
|
$character_class++;
|
|
|
|
}
|
|
|
|
if (preg_match('/[[:upper:]]/', $password)) {
|
|
|
|
$character_class++;
|
|
|
|
}
|
|
|
|
if (preg_match('/[[:digit:]]/', $password)) {
|
|
|
|
$character_class++;
|
|
|
|
}
|
|
|
|
if (preg_match('/[[:punct:]]/', $password)) {
|
|
|
|
$character_class++;
|
|
|
|
}
|
|
|
|
if ($character_class < 3) {
|
|
|
|
$messages[] = "Passwords under 15 characters must contain characters from at least three of the following four groups: Lower Case Letters, Upper Case Leters, Numbers, Puncuation/Special Characters. Passwords 15 or more characters long do not have any complexity requirements.";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (preg_match('/^[[:punct:]]/', $password)) {
|
|
|
|
$messages[] = "Password may not begin with Puncuation/Special Characters.";
|
|
|
|
}
|
|
|
|
if (!preg_match('/^[[:lower:][:upper:][:digit:][:punct:]]{8,}$/', $password)) {
|
|
|
|
$messages[] = "Password may only contain characters from these four groups: Lower Case Letters, Upper Case Letters, Numbers, Puncuation/Special Characters.";
|
|
|
|
}
|
|
|
|
if (count($messages) > 0) {
|
|
if ($f3->exists('SESSION.messages')) {
|
|
$f3->set('SESSION.messages', array_merge($f3->get('SESSION.messages'), $messages));
|
|
} else {
|
|
$f3->set('SESSION.messages', $messages);
|
|
}
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
|
|
}
|
|
|
|
public static function validateEmailLocalpart($localpart) {
|
|
|
|
global $f3;
|
|
|
|
$messages = array();
|
|
|
|
if(strlen($localpart) > 64) {
|
|
|
|
$messages[] = "Email account names (local-part) can not be longer than 64 characters.";
|
|
|
|
}
|
|
|
|
if (!preg_match('/^[[:lower:][:upper:][:digit:]\.\_\-]{1,64}$/', $localpart)) {
|
|
|
|
$messages[] = "Email account names (local-part) can only contain letters, numbers, and the special characters . _ -";
|
|
|
|
}
|
|
|
|
if (preg_match('/^[\.\_\-]/', $localpart)) {
|
|
|
|
$messages[] = "Email account names (local-part) may not begin with a Special Character.";
|
|
|
|
}
|
|
|
|
if (preg_match('/[\.\_\-]$/', $localpart)) {
|
|
|
|
$messages[] = "Email account names (local-part) may not end with a Special Character.";
|
|
|
|
}
|
|
|
|
if (preg_match('/[\.\_\-]{2,}/', $localpart)) {
|
|
|
|
$messages[] = "Email account names (local-part) may not have consecutive Special Characters.";
|
|
|
|
}
|
|
|
|
if (count($messages) > 0) {
|
|
if ($f3->exists('SESSION.messages')) {
|
|
$f3->set('SESSION.messages', array_merge($f3->get('SESSION.messages'), $messages));
|
|
} else {
|
|
$f3->set('SESSION.messages', $messages);
|
|
}
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
|
|
}
|
|
|
|
public static function validateEmailStatus($status) {
|
|
|
|
global $f3;
|
|
|
|
$messages = array();
|
|
|
|
if (is_int($status)) {
|
|
if ($status == 0 || $status == 1 || $status == 2) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
$messages[] = "Invalid Status setting.";
|
|
if ($f3->exists('SESSION.messages')) {
|
|
$f3->set('SESSION.messages', array_merge($f3->get('SESSION.messages'), $messages));
|
|
} else {
|
|
$f3->set('SESSION.messages', $messages);
|
|
}
|
|
return false;
|
|
|
|
}
|
|
|
|
public static function validateEmailQuota($quota) {
|
|
|
|
global $f3;
|
|
|
|
$messages = array();
|
|
|
|
if ($quota == "NULL" || (is_int($quota) && $quota > 0)) {
|
|
return true;
|
|
}
|
|
$messages[] = "Invalid Quota ($quota).";
|
|
if ($f3->exists('SESSION.messages')) {
|
|
$f3->set('SESSION.messages', array_merge($f3->get('SESSION.messages'), $messages));
|
|
} else {
|
|
$f3->set('SESSION.messages', $messages);
|
|
}
|
|
return false;
|
|
|
|
}
|
|
|
|
public static function validateEmailFiltering($filtering) {
|
|
|
|
global $f3;
|
|
|
|
$messages = array();
|
|
|
|
if ($filtering == 0 || $filtering == 1 || $filtering == 2) {
|
|
return true;
|
|
}
|
|
|
|
$messages[] = "Invalid Filtering setting.";
|
|
if ($f3->exists('SESSION.messages')) {
|
|
$f3->set('SESSION.messages', array_merge($f3->get('SESSION.messages'), $messages));
|
|
} else {
|
|
$f3->set('SESSION.messages', $messages);
|
|
}
|
|
return false;
|
|
|
|
}
|
|
|
|
public static function validateEmailRatelimit($ratelimit) {
|
|
|
|
global $f3;
|
|
|
|
$messages = array();
|
|
|
|
if ($ratelimit == "NULL" || $ratelimit > 0) {
|
|
return true;
|
|
}
|
|
$messages[] = "Invalid Rate Limit ($ratelimit).";
|
|
if ($f3->exists('SESSION.messages')) {
|
|
$f3->set('SESSION.messages', array_merge($f3->get('SESSION.messages'), $messages));
|
|
} else {
|
|
$f3->set('SESSION.messages', $messages);
|
|
}
|
|
return false;
|
|
|
|
}
|
|
|
|
public static function validateUsername($username) {
|
|
|
|
global $f3;
|
|
|
|
$messages = array();
|
|
|
|
if(strlen($username) < 3) {
|
|
|
|
$messages[] = "Usernames must be at least 3 characters long.";
|
|
|
|
}
|
|
|
|
if(strlen($username) > 16) {
|
|
|
|
$messages[] = "Usernames can not be longer than 16 characters.";
|
|
|
|
}
|
|
|
|
if (!preg_match('/^[[:lower:][:digit:]\.\_\-]{3,16}$/', $username)) {
|
|
|
|
$messages[] = "Usernames can only contain letters, numbers, and the special characters . _ -";
|
|
|
|
}
|
|
|
|
if (preg_match('/^[[:digit:]\.\_\-]/', $username)) {
|
|
|
|
$messages[] = "Usernames must begin with an alphabetic character.";
|
|
|
|
}
|
|
|
|
if (preg_match('/[\.\_\-]$/', $username)) {
|
|
|
|
$messages[] = "Usernames may not end with a Special Character.";
|
|
|
|
}
|
|
|
|
if (preg_match('/[\.\_\-]{2,}/', $username)) {
|
|
|
|
$messages[] = "Usernames may not have consecutive Special Characters.";
|
|
|
|
}
|
|
|
|
if (count($messages) > 0) {
|
|
if ($f3->exists('SESSION.messages')) {
|
|
$f3->set('SESSION.messages', array_merge($f3->get('SESSION.messages'), $messages));
|
|
} else {
|
|
$f3->set('SESSION.messages', $messages);
|
|
}
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
|
|
}
|
|
|
|
public static function verifyVhostDomainExists($domain) {
|
|
|
|
global $f3;
|
|
|
|
exec("/usr/local/bin/vhost-get.sh -d $domain -c", $output, $result_code);
|
|
if ($result_code == 0) {
|
|
return TRUE;
|
|
} else {
|
|
if (count($output) > 0) {
|
|
if ($output[0] != "ERROR: $domain not found") {
|
|
$f3->set('SESSION.messages', $output[0]);
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
public static function verifyCertificateExists($domain) {
|
|
|
|
global $f3;
|
|
|
|
exec("/usr/local/bin/letsencrypt-get.sh -d $domain -c", $output, $result_code);
|
|
if ($result_code == 0) {
|
|
return TRUE;
|
|
} else {
|
|
if (count($output) > 0) {
|
|
if ($output[0] != "ERROR: Certificate for $domain not found") {
|
|
$f3->set('SESSION.messages', $output[0]);
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
public static function verifyVmailDomainExists($domain) {
|
|
|
|
global $f3;
|
|
|
|
exec("/usr/local/bin/vmail-domains-get.sh -d $domain -c", $output, $result_code);
|
|
if ($result_code == 0) {
|
|
if (count($output) == 0) {
|
|
return FALSE;
|
|
} else {
|
|
// add check for domain row???
|
|
return TRUE;
|
|
}
|
|
} else {
|
|
$f3->set('SESSION.messages', "System error checking if email domain exists.");
|
|
return FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
public static function verifyDkimExists($domain) {
|
|
|
|
global $f3;
|
|
|
|
exec("/usr/local/bin/vmail-dkim-get.sh -d $domain -c", $output, $result_code);
|
|
if ($result_code == 0) {
|
|
return TRUE;
|
|
} else {
|
|
if (count($output) > 0) {
|
|
if ($output[0] != "ERROR: DKIM for $domain does not exist.") {
|
|
if (count($output) > 0) {
|
|
$f3->set('SESSION.messages', $output[0]);
|
|
}
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
public static function vGet($cmd, $return404 = TRUE) {
|
|
|
|
global $f3;
|
|
|
|
/* execute command */
|
|
exec("/usr/local/bin/$cmd", $output, $result_code);
|
|
/* check for sucessful response */
|
|
if ($result_code == 0) {
|
|
/* intialize array to return */
|
|
$tmp_array = array();
|
|
/* check for empty result (no data / not found) */
|
|
if (count($output) == 0 && $return404) {
|
|
/* return 404 unless this is disabled by calling function */
|
|
$f3->error(404);
|
|
} elseif (count($output) > 0) {
|
|
/* format array, first line contains headers / field names */
|
|
$headers = str_getcsv($output[0]);
|
|
/* remove header row from array */
|
|
array_shift($output);
|
|
/* cycle through each response line and convert cvs into array row */
|
|
foreach ($output as $k=>$v) {
|
|
$cvs_array = str_getcsv($v);
|
|
$tmp_array[$k] = array();
|
|
foreach ($cvs_array as $cvsk=>$cvsv) {
|
|
$tmp_array[$k][$headers[$cvsk]] = $cvsv;
|
|
}
|
|
}
|
|
} else {
|
|
/* empty response */
|
|
return false;
|
|
}
|
|
return $tmp_array;
|
|
} else {
|
|
/* command resulted in error, check for & set error messages and send 500 response */
|
|
if (count($output) > 0) {
|
|
foreach ($output as $k=>$output_message) {
|
|
$messages[] = "$output_message";
|
|
}
|
|
} else {
|
|
$messages[] = "Unknown error.";
|
|
}
|
|
$f3->set('SESSION.messages', $messages);
|
|
$f3->error(500);
|
|
}
|
|
|
|
}
|
|
|
|
}
|