put Api-Commands into namespaces

Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
This commit is contained in:
Michael Kaufmann
2018-12-18 09:46:36 +01:00
parent c7e5df95e7
commit 4c27efa4ae
30 changed files with 831 additions and 667 deletions

View File

@@ -1,502 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package API
* @since 0.10.0
*
*/
abstract class ApiCommand extends ApiParameter
{
/**
* debug flag
*
* @var boolean
*/
private $debug = false;
/**
* is admin flag
*
* @var boolean
*/
private $is_admin = false;
/**
* internal user data array
*
* @var array
*/
private $user_data = null;
/**
* logger interface
*
* @var FroxlorLogger
*/
private $logger = null;
/**
* mail interface
*
* @var PHPMailer
*/
private $mail = null;
/**
* language strings array
*
* @var array
*/
protected $lng = null;
/**
* froxlor version
*
* @var string
*/
protected $version = null;
/**
* froxlor dbversion
*
* @var int
*/
protected $dbversion = null;
/**
* froxlor version-branding
*
* @var string
*/
protected $branding = null;
/**
*
* @param array $header
* optional, passed via API
* @param array $params
* optional, array of parameters (var=>value) for the command
* @param array $userinfo
* optional, passed via WebInterface (instead of $header)
*
* @throws Exception
*/
public function __construct($header = null, $params = null, $userinfo = null)
{
global $lng, $version, $dbversion, $branding;
parent::__construct($params);
$this->version = $version;
$this->dbversion = $dbversion;
$this->branding = $branding;
if (! empty($header)) {
$this->readUserData($header);
} elseif (! empty($userinfo)) {
$this->user_data = $userinfo;
$this->is_admin = (isset($userinfo['adminsession']) && $userinfo['adminsession'] == 1 && $userinfo['adminid'] > 0) ? true : false;
} else {
throw new Exception("Invalid user data", 500);
}
$this->logger = FroxlorLogger::getInstanceOf($this->user_data);
// check whether the user is deactivated
if ($this->getUserDetail('deactivated') == 1) {
$this->logger()->logAction(LOG_ERROR, LOG_INFO, "[API] User '" . $this->getUserDetail('loginnname') . "' tried to use API but is deactivated");
throw new Exception("Account suspended", 406);
}
$this->initLang();
$this->initMail();
if ($this->debug) {
$this->logger()->logAction(LOG_ERROR, LOG_DEBUG, "[API] " . get_called_class() . ": " . json_encode($params, JSON_UNESCAPED_SLASHES));
}
}
/**
* initialize global $lng variable to have
* localized strings available for the ApiCommands
*/
private function initLang()
{
global $lng;
// query the whole table
$result_stmt = Database::query("SELECT * FROM `" . TABLE_PANEL_LANGUAGE . "`");
$langs = array();
// presort languages
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
$langs[$row['language']][] = $row;
}
// set default language before anything else to
// ensure that we can display messages
$language = Settings::Get('panel.standardlanguage');
if (isset($this->user_data['language']) && isset($langs[$this->user_data['language']])) {
// default: use language from session, #277
$language = $this->user_data['language'];
} elseif (isset($this->user_data['def_language'])) {
$language = $this->user_data['def_language'];
}
// include every english language file we can get
foreach ($langs['English'] as $value) {
include_once makeSecurePath(FROXLOR_INSTALL_DIR . '/' . $value['file']);
}
// now include the selected language if its not english
if ($language != 'English') {
if (isset($langs[$language])) {
foreach ($langs[$language] as $value) {
include_once makeSecurePath(FROXLOR_INSTALL_DIR . '/' . $value['file']);
}
} else {
if ($this->debug) {
$this->logger()->logAction(LOG_ERROR, LOG_DEBUG, "[API] unable to include user-language '" . $language . "'. Not found in database.", 404);
}
}
}
// last but not least include language references file
include_once makeSecurePath(FROXLOR_INSTALL_DIR . '/lng/lng_references.php');
// set array for ApiCommand
$this->lng = $lng;
}
/**
* initialize mail interface so an API wide mail-object is available
* @throws phpmailerException
*/
private function initMail()
{
/**
* Initialize the mailingsystem
*/
$this->mail = new PHPMailer(true);
$this->mail->CharSet = "UTF-8";
if (Settings::Get('system.mail_use_smtp')) {
$this->mail->isSMTP();
$this->mail->Host = Settings::Get('system.mail_smtp_host');
$this->mail->SMTPAuth = Settings::Get('system.mail_smtp_auth') == '1' ? true : false;
$this->mail->Username = Settings::Get('system.mail_smtp_user');
$this->mail->Password = Settings::Get('system.mail_smtp_passwd');
if (Settings::Get('system.mail_smtp_usetls')) {
$this->mail->SMTPSecure = 'tls';
} else {
$this->mail->SMTPAutoTLS = false;
}
$this->mail->Port = Settings::Get('system.mail_smtp_port');
}
if ( PHPMailer::validateAddress(Settings::Get('panel.adminmail')) !== false) {
// set return-to address and custom sender-name, see #76
$this->mail->setFrom(Settings::Get('panel.adminmail'), Settings::Get('panel.adminmail_defname'));
if (Settings::Get('panel.adminmail_return') != '') {
$this->mail->addReplyTo(Settings::Get('panel.adminmail_return'), Settings::Get('panel.adminmail_defname'));
}
}
}
/**
* returns an instance of the wanted ApiCommand (e.g.
* Customers, Domains, etc);
* this is used widely in the WebInterface
*
* @param array $userinfo
* array of user-data
* @param array $params
* array of parameters for the command
*
* @return ApiCommand
* @throws Exception
*/
public static function getLocal($userinfo = null, $params = null)
{
return new static(null, $params, $userinfo);
}
/**
* admin flag
*
* @return boolean
*/
protected function isAdmin()
{
return $this->is_admin;
}
/**
* return field from user-table
*
* @param string $detail
*
* @return string
*/
protected function getUserDetail($detail = null)
{
return (isset($this->user_data[$detail]) ? $this->user_data[$detail] : null);
}
/**
* return user-data array
*
* @return array
*/
protected function getUserData()
{
return $this->user_data;
}
/**
* return logger instance
*
* @return FroxlorLogger
*/
protected function logger()
{
return $this->logger;
}
/**
* return mailer instance
*
* @return PHPMailer
*/
protected function mailer()
{
return $this->mail;
}
/**
* call an api-command internally
*
* @param string $command
* @param array|null $params
*
* @return array
*/
protected function apiCall($command = null, $params = null)
{
$_command = explode(".", $command);
$module = $_command[0];
$function = $_command[1];
$json_result = $module::getLocal($this->getUserData(), $params)->{$function}();
return json_decode($json_result, true)['data'];
}
/**
* return api-compatible response in JSON format and send corresponding http-header
*
* @param int $status
* @param string $status_message
* @param mixed $data
*
* @return string json-encoded response message
*/
protected function response($status, $status_message, $data = null)
{
if (isset($_SERVER["SERVER_PROTOCOL"]) && ! empty($_SERVER["SERVER_PROTOCOL"])) {
$resheader = $_SERVER["SERVER_PROTOCOL"] . " " . $status;
if (! empty($status_message)) {
$resheader .= ' ' . str_replace("\n", " ", $status_message);
}
header($resheader);
}
$response = array();
$response['status'] = $status;
$response['status_message'] = $status_message;
$response['data'] = $data;
$json_response = json_encode($response, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
return $json_response;
}
/**
* returns an array of customers the current user can access
*
* @param string $customer_hide_option
* optional, when called as customer, some options might be hidden due to the panel.customer_hide_options ettings
*
* @throws Exception
* @return array
*/
protected function getAllowedCustomerIds($customer_hide_option = '')
{
$customer_ids = array();
if ($this->isAdmin()) {
// if we're an admin, list all ftp-users of all the admins customers
// or optionally for one specific customer identified by id or loginname
$customerid = $this->getParam('customerid', true, 0);
$loginname = $this->getParam('loginname', true, '');
if (! empty($customerid) || ! empty($loginname)) {
$_result = $this->apiCall('Customers.get', array(
'id' => $customerid,
'loginname' => $loginname
));
$custom_list_result = array(
$_result
);
} else {
$_custom_list_result = $this->apiCall('Customers.listing');
$custom_list_result = $_custom_list_result['list'];
}
foreach ($custom_list_result as $customer) {
$customer_ids[] = $customer['customerid'];
}
} else {
if (! empty($customer_hide_option) && Settings::IsInList('panel.customer_hide_options', $customer_hide_option)) {
throw new Exception("You cannot access this resource", 405);
}
$customer_ids = array(
$this->getUserDetail('customerid')
);
}
if (empty($customer_ids)) {
throw new Exception("Required resource unsatisfied.", 405);
}
return $customer_ids;
}
/**
* returns an array of customer data for customer, or by customer-id/loginname for admin/reseller
*
* @param int $customerid
* optional, required if loginname is empty
* @param string $loginname
* optional, required of customerid is empty
* @param string $customer_resource_check
* optional, when called as admin, check the resources of the target customer
*
* @throws Exception
* @return array
*/
protected function getCustomerData($customer_resource_check = '')
{
if ($this->isAdmin()) {
$customerid = $this->getParam('customerid', true, 0);
$loginname = $this->getParam('loginname', true, '');
$customer = $this->apiCall('Customers.get', array(
'id' => $customerid,
'loginname' => $loginname
));
// check whether the customer has enough resources
if (! empty($customer_resource_check) && $customer[$customer_resource_check . '_used'] >= $customer[$customer_resource_check] && $customer[$customer_resource_check] != '-1') {
throw new Exception("Customer has no more resources available", 406);
}
} else {
$customer = $this->getUserData();
}
return $customer;
}
/**
* increase/decrease a resource field for customers/admins
*
* @param string $table
* @param string $keyfield
* @param int $key
* @param string $operator
* @param string $resource
* @param string $extra
*/
protected static function updateResourceUsage($table = null, $keyfield = null, $key = null, $operator = '+', $resource = null, $extra = null, $step = 1)
{
$stmt = Database::prepare("
UPDATE `" . $table . "`
SET `" . $resource . "` = `" . $resource . "` " . $operator . " " . (int) $step . " " . $extra . "
WHERE `" . $keyfield . "` = :key
");
Database::pexecute($stmt, array(
'key' => $key
), true, true);
}
/**
* return email template content from database or global language file if not found in DB
*
* @param array $customerdata
* @param string $group
* @param string $varname
* @param array $replace_arr
* @param string $default
*
* @return string
*/
protected function getMailTemplate($customerdata = null, $group = null, $varname = null, $replace_arr = array(), $default = "")
{
// get template
$stmt = Database::prepare("
SELECT `value` FROM `" . TABLE_PANEL_TEMPLATES . "` WHERE `adminid`= :adminid
AND `language`= :lang AND `templategroup`= :group AND `varname`= :var
");
$result = Database::pexecute_first($stmt, array(
"adminid" => $customerdata['adminid'],
"lang" => $customerdata['def_language'],
"group" => $group,
"var" => $varname
), true, true);
$content = html_entity_decode(replace_variables((($result['value'] != '') ? $result['value'] : $default), $replace_arr));
return $content;
}
/**
* read user data from database by api-request-header fields
*
* @param array $header
* api-request header
*
* @throws Exception
* @return boolean
*/
private function readUserData($header = null)
{
$sel_stmt = Database::prepare("SELECT * FROM `api_keys` WHERE `apikey` = :ak AND `secret` = :as");
$result = Database::pexecute_first($sel_stmt, array(
'ak' => $header['apikey'],
'as' => $header['secret']
), true, true);
if ($result) {
// admin or customer?
if ($result['customerid'] == 0 && $result['adminid'] > 0) {
$this->is_admin = true;
$table = 'panel_admins';
$key = "adminid";
} elseif ($result['customerid'] > 0 && $result['adminid'] > 0) {
$this->is_admin = false;
$table = 'panel_customers';
$key = "customerid";
} else {
// neither adminid is > 0 nor customerid is > 0 - sorry man, no way
throw new Exception("Invalid API credentials", 400);
}
$sel_stmt = Database::prepare("SELECT * FROM `" . $table . "` WHERE `" . $key . "` = :id");
$this->user_data = Database::pexecute_first($sel_stmt, array(
'id' => ($this->is_admin ? $result['adminid'] : $result['customerid'])
), true, true);
if ($this->is_admin) {
$this->user_data['adminsession'] = 1;
}
return true;
}
throw new Exception("Invalid API credentials", 400);
}
}

View File

@@ -1,190 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package API
* @since 0.10.0
*
*/
abstract class ApiParameter
{
/**
* array of parameters passed to the command
*
* @var array
*/
private $cmd_params = null;
/**
*
* @param array $params
* optional, array of parameters (var=>value) for the command
*
* @throws Exception
*/
public function __construct($params = null)
{
if (! is_null($params)) {
$params = $this->trimArray($params);
}
$this->cmd_params = $params;
}
/**
* get specific parameter from the parameterlist;
* check for existence and != empty if needed.
* Maybe more in the future
*
* @param string $param
* parameter to get out of the request-parameter list
* @param bool $optional
* default: false
* @param mixed $default
* value which is returned if optional=true and param is not set
*
* @throws Exception
* @return mixed
*/
protected function getParam($param = null, $optional = false, $default = '')
{
// does it exist?
if (! isset($this->cmd_params[$param])) {
if ($optional === false) {
// get module + function for better error-messages
$inmod = $this->getModFunctionString();
throw new Exception('Requested parameter "' . $param . '" could not be found for "' . $inmod . '"', 404);
}
return $default;
}
// is it empty? - test really on string, as value 0 is being seen as empty by php
if ($this->cmd_params[$param] === "") {
if ($optional === false) {
// get module + function for better error-messages
$inmod = $this->getModFunctionString();
throw new Exception('Requested parameter "' . $param . '" is empty where it should not be for "' . $inmod . '"', 406);
}
return '';
}
// everything else is fine
return $this->cmd_params[$param];
}
/**
* getParam wrapper for boolean parameter
*
* @param string $param
* parameter to get out of the request-parameter list
* @param bool $optional
* default: false
* @param mixed $default
* value which is returned if optional=true and param is not set
*
* @return string
*/
protected function getBoolParam($param = null, $optional = false, $default = false)
{
$_default = '0';
if ($default) {
$_default = '1';
}
$param_value = $this->getParam($param, $optional, $_default);
if ($param_value && intval($param_value) != 0) {
return '1';
}
return '0';
}
/**
* get specific parameter which also has and unlimited-field
*
* @param string $param
* parameter to get out of the request-parameter list
* @param string $ul_field
* parameter to get out of the request-parameter list
* @param bool $optional
* default: false
* @param mixed $default
* value which is returned if optional=true and param is not set
*
* @return mixed
* @throws Exception
*/
protected function getUlParam($param = null, $ul_field = null, $optional = false, $default = 0)
{
$param_value = intval_ressource($this->getParam($param, $optional, $default));
$ul_field_value = $this->getBoolParam($ul_field, true, 0);
if ($ul_field_value != '0') {
$param_value = - 1;
}
return $param_value;
}
/**
* return list of all parameters
*
* @return array
*/
protected function getParamList()
{
return $this->cmd_params;
}
/**
* returns "module::function()" for better error-messages (missing parameter etc.)
* makes debugging a whole lot more comfortable
*
* @param int $level
* depth of backtrace, default 2
*
* @param int $max_level
* @param array|null $trace
*
* @return string
*/
private function getModFunctionString($level = 1, $max_level = 5, $trace = null)
{
// which class called us
$_class = get_called_class();
if (empty($trace)) {
// get backtrace
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
}
// check class and function
$class = $trace[$level]['class'];
$func = $trace[$level]['function'];
// is it the one we are looking for?
if ($class != $_class && $level <= $max_level) {
// check one level deeper
return $this->getModFunctionString(++ $level, $max_level, $trace);
}
return $class . ':' . $func;
}
/**
* run 'trim' function on an array recursively
*
* @param array $input
*
* @return array
*/
private function trimArray($input)
{
if (! is_array($input)) {
return trim($input);
}
return array_map(array(
$this,
'trimArray'
), $input);
}
}

View File

@@ -1,50 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package API
* @since 0.10.0
*
*/
if (! defined('FROXLOR_INSTALL_DIR')) {
define('FROXLOR_INSTALL_DIR', dirname(dirname(dirname(__DIR__))));
// ensure that default timezone is set
if (function_exists("date_default_timezone_set") && function_exists("date_default_timezone_get")) {
@date_default_timezone_set(@date_default_timezone_get());
}
$installed = true;
// check whether the userdata file exists
if (! @file_exists(FROXLOR_INSTALL_DIR . '/lib/userdata.inc.php')) {
$installed = false;
}
// check whether we can read the userdata file
if ($installed && ! @is_readable(FROXLOR_INSTALL_DIR . '/lib/userdata.inc.php')) {
$installed = false;
}
if ($installed) {
// include userdata for content-check
require FROXLOR_INSTALL_DIR . '/lib/userdata.inc.php';
if (! isset($sql) || ! is_array($sql)) {
$installed = false;
}
}
// do not try to do anything if we have no installed/configured froxlor
if (! $installed) {
header("Status: 404 Not found", 404);
header($_SERVER["SERVER_PROTOCOL"] . " 404 Not found", 404);
exit();
}
require_once FROXLOR_INSTALL_DIR . '/lib/tables.inc.php';
require_once FROXLOR_INSTALL_DIR . '/lib/functions.php';
}
$lng = array();

View File

@@ -1,118 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package API
* @since 0.10.0
*
*/
class FroxlorRPC
{
/**
* validate a given request
*
* @param array $request
*
* @throws Exception
* @return array
*/
public static function validateRequest($request)
{
// check header
if (! isset($request['header']) || empty($request['header'])) {
throw new Exception("Invalid request header", 400);
}
// check authorization
if (! isset($request['header']['apikey']) || empty($request['header']['apikey']) || ! isset($request['header']['secret']) || empty($request['header']['secret'])) {
throw new Exception("No authorization credentials given", 400);
}
self::validateAuth($request['header']['apikey'], $request['header']['secret']);
// check command
return self::validateBody($request);
}
/**
* validates the given api credentials
*
* @param string $key
* @param string $secret
*
* @throws Exception
* @return boolean
*/
private static function validateAuth($key, $secret)
{
$sel_stmt = Database::prepare("SELECT * FROM `api_keys` WHERE `apikey` = :ak AND `secret` = :as");
$result = Database::pexecute_first($sel_stmt, array(
'ak' => $key,
'as' => $secret
), true, true);
if ($result) {
if ($result['apikey'] == $key && $result['secret'] == $secret && ($result['valid_until'] == -1 || $result['valid_until'] >= time())) {
if (!empty($result['allowed_from'])) {
// @todo allow specification and validating of whole subnets later
$ip_list = explode(",", $result['allowed_from']);
$access_ip = inet_ntop(inet_pton($_SERVER['REMOTE_ADDR']));
if (in_array($access_ip, $ip_list)) {
return true;
}
} else {
return true;
}
}
}
throw new Exception("Invalid authorization credentials", 403);
}
/**
* validates the given command
*
* @param array $request
*
* @return array
* @throws Exception
*/
private static function validateBody($request)
{
// check body
if (! isset($request['body']) || empty($request['body'])) {
throw new Exception("Invalid request body", 400);
}
// check command exists
if (! isset($request['body']['command']) || empty($request['body']['command'])) {
throw new Exception("No command given", 400);
}
$command = explode(".", $request['body']['command']);
if (count($command) != 2) {
throw new Exception("Invalid command", 400);
}
// simply check for file-existance, as we do not want to use our autoloader because this way
// it will recognize non-api classes+methods as valid commands
$apiclass = FROXLOR_INSTALL_DIR . '/lib/classes/api/commands/class.' . $command[0] . '.php';
if (! file_exists($apiclass) || ! @method_exists($command[0], $command[1])) {
throw new Exception("Unknown command", 400);
}
return array(
'command' => array(
'class' => $command[0],
'method' => $command[1]
),
'params' => isset($request['body']['params']) ? $request['body']['params'] : null
);
}
}

View File

@@ -1,854 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package API
* @since 0.10.0
*
*/
class Admins extends ApiCommand implements ResourceEntity
{
/**
* lists all admin entries
*
* @access admin
* @throws Exception
* @return array count|list
*/
public function listing()
{
if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) {
$this->logger()->logAction(ADM_ACTION, LOG_NOTICE, "[API] list admins");
$result_stmt = Database::prepare("
SELECT *
FROM `" . TABLE_PANEL_ADMINS . "`
ORDER BY `loginname` ASC
");
Database::pexecute($result_stmt, null, true, true);
$result = array();
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
$result[] = $row;
}
return $this->response(200, "successfull", array(
'count' => count($result),
'list' => $result
));
}
throw new Exception("Not allowed to execute given command.", 403);
}
/**
* return an admin entry by either id or loginname
*
* @param int $id
* optional, the admin-id
* @param string $loginname
* optional, the loginname
*
* @access admin
* @throws Exception
* @return array
*/
public function get()
{
$id = $this->getParam('id', true, 0);
$ln_optional = ($id <= 0 ? false : true);
$loginname = $this->getParam('loginname', $ln_optional, '');
if ($this->isAdmin() && ($this->getUserDetail('change_serversettings') == 1 || ($this->getUserDetail('adminid') == $id || $this->getUserDetail('loginname') == $loginname))) {
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_ADMINS . "`
WHERE " . ($id > 0 ? "`adminid` = :idln" : "`loginname` = :idln"));
$params = array(
'idln' => ($id <= 0 ? $loginname : $id)
);
$result = Database::pexecute_first($result_stmt, $params, true, true);
if ($result) {
$this->logger()->logAction(ADM_ACTION, LOG_NOTICE, "[API] get admin '" . $result['loginname'] . "'");
return $this->response(200, "successfull", $result);
}
$key = ($id > 0 ? "id #" . $id : "loginname '" . $loginname . "'");
throw new Exception("Admin with " . $key . " could not be found", 404);
}
throw new Exception("Not allowed to execute given command.", 403);
}
/**
* create a new admin user
*
* @param string $name
* @param string $email
* @param string $new_loginname
* @param string $admin_password
* optional, default auto-generated
* @param string $def_language
* optional, default is system-default language
* @param string $custom_notes
* optional, default empty
* @param bool $custom_notes_show
* optional, default false
* @param int $diskspace
* optional, default 0
* @param bool $diskspace_ul
* optional, default false
* @param int $traffic
* optional, default 0
* @param bool $traffic_ul
* optional, default false
* @param int $customers
* optional, default 0
* @param bool $customers_ul
* optional, default false
* @param int $domains
* optional, default 0
* @param bool $domains_ul
* optional, default false
* @param int $subdomains
* optional, default 0
* @param bool $subdomains_ul
* optional, default false
* @param int $emails
* optional, default 0
* @param bool $emails_ul
* optional, default false
* @param int $email_accounts
* optional, default 0
* @param bool $email_accounts_ul
* optional, default false
* @param int $email_forwarders
* optional, default 0
* @param bool $email_forwarders_ul
* optional, default false
* @param int $email_quota
* optional, default 0
* @param bool $email_quota_ul
* optional, default false
* @param int $ftps
* optional, default 0
* @param bool $ftps_ul
* optional, default false
* @param int $tickets
* optional, default 0
* @param bool $tickets_ul
* optional, default false
* @param int $mysqls
* optional, default 0
* @param bool $mysqls_ul
* optional, default false
* @param bool $customers_see_all
* optional, default false
* @param bool $domains_see_all
* optional, default false
* @param bool $tickets_see_all
* optional, default false
* @param bool $caneditphpsettings
* optional, default false
* @param bool $change_serversettings
* optional, default false
* @param array $ipaddress
* optional, list of ip-address id's; default -1 (all IP's)
*
* @access admin
* @throws Exception
* @return array
*/
public function add()
{
if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) {
// required parameters
$name = $this->getParam('name');
$email = $this->getParam('email');
$loginname = $this->getParam('new_loginname');
// parameters
$def_language = $this->getParam('def_language', true, Settings::Get('panel.standardlanguage'));
$custom_notes = $this->getParam('custom_notes', true, '');
$custom_notes_show = $this->getBoolParam('custom_notes_show', true, 0);
$password = $this->getParam('admin_password', true, '');
$diskspace = $this->getUlParam('diskspace', 'diskspace_ul', true, 0);
$traffic = $this->getUlParam('traffic', 'traffic_ul', true, 0);
$customers = $this->getUlParam('customers', 'customers_ul', true, 0);
$domains = $this->getUlParam('domains', 'domains_ul', true, 0);
$subdomains = $this->getUlParam('subdomains', 'subdomains_ul', true, 0);
$emails = $this->getUlParam('emails', 'emails_ul', true, 0);
$email_accounts = $this->getUlParam('email_accounts', 'email_accounts_ul', true, 0);
$email_forwarders = $this->getUlParam('email_forwarders', 'email_forwarders_ul', true, 0);
$email_quota = $this->getUlParam('email_quota', 'email_quota_ul', true, 0);
$ftps = $this->getUlParam('ftps', 'ftps_ul', true, 0);
$tickets = $this->getUlParam('tickets', 'tickets_ul', true, 0);
$mysqls = $this->getUlParam('mysqls', 'mysqls_ul', true, 0);
$customers_see_all = $this->getBoolParam('customers_see_all', true, 0);
$domains_see_all = $this->getBoolParam('domains_see_all', true, 0);
$tickets_see_all = $this->getBoolParam('tickets_see_all', true, 0);
$caneditphpsettings = $this->getBoolParam('caneditphpsettings', true, 0);
$change_serversettings = $this->getBoolParam('change_serversettings', true, 0);
$ipaddress = $this->getParam('ipaddress', true, - 1);
// validation
$name = validate($name, 'name', '', '', array(), true);
$idna_convert = new idna_convert_wrapper();
$email = $idna_convert->encode(validate($email, 'email', '', '', array(), true));
$def_language = validate($def_language, 'default language', '', '', array(), true);
$custom_notes = validate(str_replace("\r\n", "\n", $custom_notes), 'custom_notes', '/^[^\0]*$/', '', array(), true);
if (Settings::Get('system.mail_quota_enabled') != '1') {
$email_quota = - 1;
}
if (Settings::Get('ticket.enabled') != '1') {
$tickets = - 1;
}
$password = validate($password, 'password', '', '', array(), true);
// only check if not empty,
// cause empty == generate password automatically
if ($password != '') {
$password = validatePassword($password, true);
}
$diskspace = $diskspace * 1024;
$traffic = $traffic * 1024 * 1024;
// Check if the account already exists
// do not check via api as we skip any permission checks for this task
$loginname_check_stmt = Database::prepare("
SELECT `loginname` FROM `" . TABLE_PANEL_CUSTOMERS . "` WHERE `loginname` = :login
");
$loginname_check = Database::pexecute_first($loginname_check_stmt, array(
'login' => $loginname
), true, true);
// Check if an admin with the loginname already exists
// do not check via api as we skip any permission checks for this task
$loginname_check_admin_stmt = Database::prepare("
SELECT `loginname` FROM `" . TABLE_PANEL_ADMINS . "` WHERE `loginname` = :login
");
$loginname_check_admin = Database::pexecute_first($loginname_check_admin_stmt, array(
'login' => $loginname
), true, true);
if (strtolower($loginname_check['loginname']) == strtolower($loginname) || strtolower($loginname_check_admin['loginname']) == strtolower($loginname)) {
standard_error('loginnameexists', $loginname, true);
} // Accounts which match systemaccounts are not allowed, filtering them
elseif (preg_match('/^' . preg_quote(Settings::Get('customer.accountprefix'), '/') . '([0-9]+)/', $loginname)) {
standard_error('loginnameissystemaccount', Settings::Get('customer.accountprefix'), true);
} elseif (! validateUsername($loginname)) {
standard_error('loginnameiswrong', $loginname, true);
} elseif (! validateEmail($email)) {
standard_error('emailiswrong', $email, true);
} else {
if ($customers_see_all != '1') {
$customers_see_all = '0';
}
if ($domains_see_all != '1') {
$domains_see_all = '0';
}
if ($caneditphpsettings != '1') {
$caneditphpsettings = '0';
}
if ($change_serversettings != '1') {
$change_serversettings = '0';
}
if ($tickets_see_all != '1') {
$tickets_see_all = '0';
}
if ($password == '') {
$password = generatePassword();
}
$_theme = Settings::Get('panel.default_theme');
$ins_data = array(
'loginname' => $loginname,
'password' => makeCryptPassword($password),
'name' => $name,
'email' => $email,
'lang' => $def_language,
'change_serversettings' => $change_serversettings,
'customers' => $customers,
'customers_see_all' => $customers_see_all,
'domains' => $domains,
'domains_see_all' => $domains_see_all,
'caneditphpsettings' => $caneditphpsettings,
'diskspace' => $diskspace,
'traffic' => $traffic,
'subdomains' => $subdomains,
'emails' => $emails,
'accounts' => $email_accounts,
'forwarders' => $email_forwarders,
'quota' => $email_quota,
'ftps' => $ftps,
'tickets' => $tickets,
'tickets_see_all' => $tickets_see_all,
'mysqls' => $mysqls,
'ip' => empty($ipaddress) ? "" : (is_array($ipaddress) && $ipaddress > 0 ? json_encode($ipaddress) : - 1),
'theme' => $_theme,
'custom_notes' => $custom_notes,
'custom_notes_show' => $custom_notes_show
);
$ins_stmt = Database::prepare("
INSERT INTO `" . TABLE_PANEL_ADMINS . "` SET
`loginname` = :loginname,
`password` = :password,
`name` = :name,
`email` = :email,
`def_language` = :lang,
`change_serversettings` = :change_serversettings,
`customers` = :customers,
`customers_see_all` = :customers_see_all,
`domains` = :domains,
`domains_see_all` = :domains_see_all,
`caneditphpsettings` = :caneditphpsettings,
`diskspace` = :diskspace,
`traffic` = :traffic,
`subdomains` = :subdomains,
`emails` = :emails,
`email_accounts` = :accounts,
`email_forwarders` = :forwarders,
`email_quota` = :quota,
`ftps` = :ftps,
`tickets` = :tickets,
`tickets_see_all` = :tickets_see_all,
`mysqls` = :mysqls,
`ip` = :ip,
`theme` = :theme,
`custom_notes` = :custom_notes,
`custom_notes_show` = :custom_notes_show
");
Database::pexecute($ins_stmt, $ins_data, true, true);
$adminid = Database::lastInsertId();
$ins_data['adminid'] = $adminid;
$this->logger()->logAction(ADM_ACTION, LOG_WARNING, "[API] added admin '" . $loginname . "'");
// get all admin-data for return-array
$result = $this->apiCall('Admins.get', array(
'id' => $adminid
));
return $this->response(200, "successfull", $result);
}
}
throw new Exception("Not allowed to execute given command.", 403);
}
/**
* update an admin user by given id or loginname
*
* @param int $id
* optional, the admin-id
* @param string $loginname
* optional, the loginname
* @param string $name
* optional
* @param string $email
* optional
* @param string $admin_password
* optional, default auto-generated
* @param string $def_language
* optional, default is system-default language
* @param string $custom_notes
* optional, default empty
* @param string $theme
* optional
* @param bool $deactivated
* optional, default false
* @param bool $custom_notes_show
* optional, default false
* @param int $diskspace
* optional, default 0
* @param bool $diskspace_ul
* optional, default false
* @param int $traffic
* optional, default 0
* @param bool $traffic_ul
* optional, default false
* @param int $customers
* optional, default 0
* @param bool $customers_ul
* optional, default false
* @param int $domains
* optional, default 0
* @param bool $domains_ul
* optional, default false
* @param int $subdomains
* optional, default 0
* @param bool $subdomains_ul
* optional, default false
* @param int $emails
* optional, default 0
* @param bool $emails_ul
* optional, default false
* @param int $email_accounts
* optional, default 0
* @param bool $email_accounts_ul
* optional, default false
* @param int $email_forwarders
* optional, default 0
* @param bool $email_forwarders_ul
* optional, default false
* @param int $email_quota
* optional, default 0
* @param bool $email_quota_ul
* optional, default false
* @param int $ftps
* optional, default 0
* @param bool $ftps_ul
* optional, default false
* @param int $tickets
* optional, default 0
* @param bool $tickets_ul
* optional, default false
* @param int $mysqls
* optional, default 0
* @param bool $mysqls_ul
* optional, default false
* @param bool $customers_see_all
* optional, default false
* @param bool $domains_see_all
* optional, default false
* @param bool $tickets_see_all
* optional, default false
* @param bool $caneditphpsettings
* optional, default false
* @param bool $change_serversettings
* optional, default false
* @param array $ipaddress
* optional, list of ip-address id's; default -1 (all IP's)
*
* @access admin
* @throws Exception
* @return array
*/
public function update()
{
if ($this->isAdmin()) {
$id = $this->getParam('id', true, 0);
$ln_optional = ($id <= 0 ? false : true);
$loginname = $this->getParam('loginname', $ln_optional, '');
$result = $this->apiCall('Admins.get', array(
'id' => $id,
'loginname' => $loginname
));
$id = $result['adminid'];
if ($this->getUserDetail('change_serversettings') == 1 || $result['adminid'] == $this->getUserDetail('adminid')) {
// parameters
$name = $this->getParam('name', true, $result['name']);
$idna_convert = new idna_convert_wrapper();
$email = $this->getParam('email', true, $idna_convert->decode($result['email']));
$password = $this->getParam('admin_password', true, '');
$def_language = $this->getParam('def_language', true, $result['def_language']);
$custom_notes = $this->getParam('custom_notes', true, $result['custom_notes']);
$custom_notes_show = $this->getBoolParam('custom_notes_show', true, $result['custom_notes_show']);
$theme = $this->getParam('theme', true, $result['theme']);
// you cannot edit some of the details of yourself
if ($result['adminid'] == $this->getUserDetail('adminid')) {
$deactivated = $result['deactivated'];
$customers = $result['customers'];
$domains = $result['domains'];
$subdomains = $result['subdomains'];
$emails = $result['emails'];
$email_accounts = $result['email_accounts'];
$email_forwarders = $result['email_forwarders'];
$email_quota = $result['email_quota'];
$ftps = $result['ftps'];
$tickets = $result['tickets'];
$mysqls = $result['mysqls'];
$tickets_see_all = $result['tickets_see_all'];
$customers_see_all = $result['customers_see_all'];
$domains_see_all = $result['domains_see_all'];
$caneditphpsettings = $result['caneditphpsettings'];
$change_serversettings = $result['change_serversettings'];
$diskspace = $result['diskspace'];
$traffic = $result['traffic'];
$ipaddress = ($result['ip'] != - 1 ? json_decode($result['ip'], true) : - 1);
} else {
$deactivated = $this->getBoolParam('deactivated', true, $result['deactivated']);
$dec_places = Settings::Get('panel.decimal_places');
$diskspace = $this->getUlParam('diskspace', 'diskspace_ul', true, round($result['diskspace'] / 1024, $dec_places));
$traffic = $this->getUlParam('traffic', 'traffic_ul', true, round($result['traffic'] / (1024 * 1024), $dec_places));
$customers = $this->getUlParam('customers', 'customers_ul', true, $result['customers']);
$domains = $this->getUlParam('domains', 'domains_ul', true, $result['domains']);
$subdomains = $this->getUlParam('subdomains', 'subdomains_ul', true, $result['subdomains']);
$emails = $this->getUlParam('emails', 'emails_ul', true, $result['emails']);
$email_accounts = $this->getUlParam('email_accounts', 'email_accounts_ul', true, $result['email_accounts']);
$email_forwarders = $this->getUlParam('email_forwarders', 'email_forwarders_ul', true, $result['email_forwarders']);
$email_quota = $this->getUlParam('email_quota', 'email_quota_ul', true, $result['email_quota']);
$ftps = $this->getUlParam('ftps', 'ftps_ul', true, $result['ftps']);
$tickets = $this->getUlParam('tickets', 'tickets_ul', true, $result['tickets']);
$mysqls = $this->getUlParam('mysqls', 'mysqls_ul', true, $result['mysqls']);
$customers_see_all = $this->getBoolParam('customers_see_all', true, $result['customers_see_all']);
$domains_see_all = $this->getBoolParam('domains_see_all', true, $result['domains_see_all']);
$tickets_see_all = $this->getBoolParam('tickets_see_all', true, $result['tickets_see_all']);
$caneditphpsettings = $this->getBoolParam('caneditphpsettings', true, $result['caneditphpsettings']);
$change_serversettings = $this->getBoolParam('change_serversettings', true, $result['change_serversettings']);
$ipaddress = $this->getParam('ipaddress', true, ($result['ip'] != - 1 ? json_decode($result['ip'], true) : - 1));
$diskspace = $diskspace * 1024;
$traffic = $traffic * 1024 * 1024;
}
// validation
$name = validate($name, 'name', '', '', array(), true);
$idna_convert = new idna_convert_wrapper();
$email = $idna_convert->encode(validate($email, 'email', '', '', array(), true));
$def_language = validate($def_language, 'default language', '', '', array(), true);
$custom_notes = validate(str_replace("\r\n", "\n", $custom_notes), 'custom_notes', '/^[^\0]*$/', '', array(), true);
$theme = validate($theme, 'theme', '', '', array(), true);
$password = validate($password, 'password', '', '', array(), true);
if (Settings::Get('system.mail_quota_enabled') != '1') {
$email_quota = - 1;
}
if (Settings::Get('ticket.enabled') != '1') {
$tickets = - 1;
}
if (empty($theme)) {
$theme = Settings::Get('panel.default_theme');
}
if (! validateEmail($email)) {
standard_error('emailiswrong', $email, true);
} else {
if ($deactivated != '1') {
$deactivated = '0';
}
if ($customers_see_all != '1') {
$customers_see_all = '0';
}
if ($domains_see_all != '1') {
$domains_see_all = '0';
}
if ($caneditphpsettings != '1') {
$caneditphpsettings = '0';
}
if ($change_serversettings != '1') {
$change_serversettings = '0';
}
if ($tickets_see_all != '1') {
$tickets_see_all = '0';
}
if ($password != '') {
$password = validatePassword($password, true);
$password = makeCryptPassword($password);
} else {
$password = $result['password'];
}
// check if a resource was set to something lower
// than actually used by the admin/reseller
$res_warning = "";
if ($customers != $result['customers'] && $customers != - 1 && $customers < $result['customers_used']) {
$res_warning .= sprintf($this->lng['error']['setlessthanalreadyused'], 'customers');
}
if ($domains != $result['domains'] && $domains != - 1 && $domains < $result['domains_used']) {
$res_warning .= sprintf($this->lng['error']['setlessthanalreadyused'], 'domains');
}
if ($diskspace != $result['diskspace'] && ($diskspace / 1024) != - 1 && $diskspace < $result['diskspace_used']) {
$res_warning .= sprintf($this->lng['error']['setlessthanalreadyused'], 'diskspace');
}
if ($traffic != $result['traffic'] && ($traffic / 1024 / 1024) != - 1 && $traffic < $result['traffic_used']) {
$res_warning .= sprintf($this->lng['error']['setlessthanalreadyused'], 'traffic');
}
if ($emails != $result['emails'] && $emails != - 1 && $emails < $result['emails_used']) {
$res_warning .= sprintf($this->lng['error']['setlessthanalreadyused'], 'emails');
}
if ($email_accounts != $result['email_accounts'] && $email_accounts != - 1 && $email_accounts < $result['email_accounts_used']) {
$res_warning .= sprintf($this->lng['error']['setlessthanalreadyused'], 'email accounts');
}
if ($email_forwarders != $result['email_forwarders'] && $email_forwarders != - 1 && $email_forwarders < $result['email_forwarders_used']) {
$res_warning .= sprintf($this->lng['error']['setlessthanalreadyused'], 'email forwarders');
}
if ($email_quota != $result['email_quota'] && $email_quota != - 1 && $email_quota < $result['email_quota_used']) {
$res_warning .= sprintf($this->lng['error']['setlessthanalreadyused'], 'email quota');
}
if ($ftps != $result['ftps'] && $ftps != - 1 && $ftps < $result['ftps_used']) {
$res_warning .= sprintf($this->lng['error']['setlessthanalreadyused'], 'ftps');
}
if ($tickets != $result['tickets'] && $tickets != - 1 && $tickets < $result['tickets_used']) {
$res_warning .= sprintf($this->lng['error']['setlessthanalreadyused'], 'tickets');
}
if ($mysqls != $result['mysqls'] && $mysqls != - 1 && $mysqls < $result['mysqls_used']) {
$res_warning .= sprintf($this->lng['error']['setlessthanalreadyused'], 'mysqls');
}
if (! empty($res_warning)) {
throw new Exception($res_warning, 406);
}
$upd_data = array(
'password' => $password,
'name' => $name,
'email' => $email,
'lang' => $def_language,
'change_serversettings' => $change_serversettings,
'customers' => $customers,
'customers_see_all' => $customers_see_all,
'domains' => $domains,
'domains_see_all' => $domains_see_all,
'caneditphpsettings' => $caneditphpsettings,
'diskspace' => $diskspace,
'traffic' => $traffic,
'subdomains' => $subdomains,
'emails' => $emails,
'accounts' => $email_accounts,
'forwarders' => $email_forwarders,
'quota' => $email_quota,
'ftps' => $ftps,
'tickets' => $tickets,
'tickets_see_all' => $tickets_see_all,
'mysqls' => $mysqls,
'ip' => empty($ipaddress) ? "" : (is_array($ipaddress) && $ipaddress > 0 ? json_encode($ipaddress) : - 1),
'deactivated' => $deactivated,
'custom_notes' => $custom_notes,
'custom_notes_show' => $custom_notes_show,
'theme' => $theme,
'adminid' => $id
);
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_ADMINS . "` SET
`password` = :password,
`name` = :name,
`email` = :email,
`def_language` = :lang,
`change_serversettings` = :change_serversettings,
`customers` = :customers,
`customers_see_all` = :customers_see_all,
`domains` = :domains,
`domains_see_all` = :domains_see_all,
`caneditphpsettings` = :caneditphpsettings,
`diskspace` = :diskspace,
`traffic` = :traffic,
`subdomains` = :subdomains,
`emails` = :emails,
`email_accounts` = :accounts,
`email_forwarders` = :forwarders,
`email_quota` = :quota,
`ftps` = :ftps,
`tickets` = :tickets,
`tickets_see_all` = :tickets_see_all,
`mysqls` = :mysqls,
`ip` = :ip,
`deactivated` = :deactivated,
`custom_notes` = :custom_notes,
`custom_notes_show` = :custom_notes_show,
`theme` = :theme
WHERE `adminid` = :adminid
");
Database::pexecute($upd_stmt, $upd_data, true, true);
$this->logger()->logAction(ADM_ACTION, LOG_INFO, "[API] edited admin '" . $result['loginname'] . "'");
// get all admin-data for return-array
$result = $this->apiCall('Admins.get', array(
'id' => $result['adminid']
));
return $this->response(200, "successfull", $result);
}
}
}
throw new Exception("Not allowed to execute given command.", 403);
}
/**
* delete a admin entry by either id or loginname
*
* @param int $id
* optional, the admin-id
* @param string $loginname
* optional, the loginname
*
* @access admin
* @throws Exception
* @return array
*/
public function delete()
{
if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) {
$id = $this->getParam('id', true, 0);
$ln_optional = ($id <= 0 ? false : true);
$loginname = $this->getParam('loginname', $ln_optional, '');
$result = $this->apiCall('Admins.get', array(
'id' => $id,
'loginname' => $loginname
));
$id = $result['adminid'];
// don't be stupid
if ($id == $this->getUserDetail('adminid')) {
standard_error('youcantdeleteyourself', '', true);
}
// delete admin
$del_stmt = Database::prepare("
DELETE FROM `" . TABLE_PANEL_ADMINS . "` WHERE `adminid` = :adminid
");
Database::pexecute($del_stmt, array(
'adminid' => $id
), true, true);
// delete the traffic-usage
$del_stmt = Database::prepare("
DELETE FROM `" . TABLE_PANEL_TRAFFIC_ADMINS . "` WHERE `adminid` = :adminid
");
Database::pexecute($del_stmt, array(
'adminid' => $id
), true, true);
// delete the diskspace usage
$del_stmt = Database::prepare("
DELETE FROM `" . TABLE_PANEL_DISKSPACE_ADMINS . "` WHERE `adminid` = :adminid
");
Database::pexecute($del_stmt, array(
'adminid' => $id
), true, true);
// set admin-id of the old admin's customer to current admins
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET
`adminid` = :userid WHERE `adminid` = :adminid
");
Database::pexecute($upd_stmt, array(
'userid' => $this->getUserDetail('adminid'),
'adminid' => $id
), true, true);
// set admin-id of the old admin's domains to current admins
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_DOMAINS . "` SET
`adminid` = :userid WHERE `adminid` = :adminid
");
Database::pexecute($upd_stmt, array(
'userid' => $this->getUserDetail('adminid'),
'adminid' => $id
), true, true);
// delete old admin's api keys if exists (no customer keys)
$upd_stmt = Database::prepare("
DELETE FROM `" . TABLE_API_KEYS . "` WHERE
`adminid` = :adminid AND `customerid` = '0'
");
Database::pexecute($upd_stmt, array(
'adminid' => $id
), true, true);
// set admin-id of the old admin's api-keys to current admins
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_API_KEYS . "` SET
`adminid` = :userid WHERE `adminid` = :adminid
");
Database::pexecute($upd_stmt, array(
'userid' => $this->getUserDetail('adminid'),
'adminid' => $id
), true, true);
$this->logger()->logAction(ADM_ACTION, LOG_WARNING, "[API] deleted admin '" . $result['loginname'] . "'");
updateCounters();
return $this->response(200, "successfull", $result);
}
throw new Exception("Not allowed to execute given command.", 403);
}
/**
* unlock a locked admin by either id or loginname
*
* @param int $id
* optional, the admin-id
* @param string $loginname
* optional, the loginname
*
* @access admin
* @throws Exception
* @return array
*/
public function unlock()
{
if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) {
$id = $this->getParam('id', true, 0);
$ln_optional = ($id <= 0 ? false : true);
$loginname = $this->getParam('loginname', $ln_optional, '');
$result = $this->apiCall('Admins.get', array(
'id' => $id,
'loginname' => $loginname
));
$id = $result['adminid'];
$result_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_ADMINS . "` SET
`loginfail_count` = '0'
WHERE `adminid`= :id
");
Database::pexecute($result_stmt, array(
'id' => $id
), true, true);
// set the new value for result-array
$result['loginfail_count'] = 0;
$this->logger()->logAction(ADM_ACTION, LOG_WARNING, "[API] unlocked admin '" . $result['loginname'] . "'");
return $this->response(200, "successfull", $result);
}
throw new Exception("Not allowed to execute given command.", 403);
}
/**
* increase resource-usage
*
* @param int $customerid
* @param string $resource
* @param string $extra
* optional, default empty
*/
public static function increaseUsage($adminid = 0, $resource = null, $extra = '')
{
self::updateResourceUsage(TABLE_PANEL_ADMINS, 'adminid', $adminid, '+', $resource, $extra);
}
/**
* decrease resource-usage
*
* @param int $customerid
* @param string $resource
* @param string $extra
* optional, default empty
*/
public static function decreaseUsage($adminid = 0, $resource = null, $extra = '')
{
self::updateResourceUsage(TABLE_PANEL_ADMINS, 'adminid', $adminid, '-', $resource, $extra);
}
}

View File

@@ -1,343 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package API
* @since 0.10.0
*
*/
class Certificates extends ApiCommand implements ResourceEntity
{
/**
* add new ssl-certificate entry for given domain by either id or domainname
*
* @param int $id
* optional, the domain-id
* @param string $domainname
* optional, the domainname
* @param string $ssl_cert_file
* @param string $ssl_key_file
* @param string $ssl_ca_file
* optional
* @param string $ssl_cert_chainfile
* optional
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function add()
{
$domainid = $this->getParam('domainid', true, 0);
$dn_optional = ($domainid <= 0 ? false : true);
$domainname = $this->getParam('domainname', $dn_optional, '');
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'domains')) {
throw new Exception("You cannot access this resource", 405);
}
$domain = $this->apiCall('SubDomains.get', array(
'id' => $domainid,
'domainname' => $domainname
));
$domainid = $domain['id'];
// parameters
$ssl_cert_file = $this->getParam('ssl_cert_file');
$ssl_key_file = $this->getParam('ssl_key_file');
$ssl_ca_file = $this->getParam('ssl_ca_file', true, '');
$ssl_cert_chainfile = $this->getParam('ssl_cert_chainfile', true, '');
// validate whether the domain does not already have an entry
$result = $this->apiCall('Certificates.get', array(
'id' => $domainid
));
if (empty($result)) {
$this->addOrUpdateCertificate($domain['id'], $ssl_cert_file, $ssl_key_file, $ssl_ca_file, $ssl_cert_chainfile, true);
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_INFO, "[API] added ssl-certificate for '" . $domain['domain'] . "'");
$result = $this->apiCall('Certificates.get', array(
'id' => $domain['id']
));
return $this->response(200, "successfull", $result);
}
throw new Exception("Domain '" . $domain['domain'] . "' already has a certificate. Did you mean to call update?", 406);
}
/**
* return ssl-certificate entry for given domain by either id or domainname
*
* @param int $id
* optional, the domain-id
* @param string $domainname
* optional, the domainname
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function get()
{
$id = $this->getParam('id', true, 0);
$dn_optional = ($id <= 0 ? false : true);
$domainname = $this->getParam('domainname', $dn_optional, '');
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'domains')) {
throw new Exception("You cannot access this resource", 405);
}
$domain = $this->apiCall('SubDomains.get', array(
'id' => $id,
'domainname' => $domainname
));
$domainid = $domain['id'];
$stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` WHERE `domainid`= :domainid");
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_INFO, "[API] get ssl-certificate for '" . $domain['domain'] . "'");
$result = Database::pexecute_first($stmt, array(
"domainid" => $domainid
));
return $this->response(200, "successfull", $result);
}
/**
* update ssl-certificate entry for given domain by either id or domainname
*
* @param int $id
* optional, the domain-id
* @param string $domainname
* optional, the domainname
* @param string $ssl_cert_file
* @param string $ssl_key_file
* @param string $ssl_ca_file
* optional
* @param string $ssl_cert_chainfile
* optional
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function update()
{
$id = $this->getParam('id', true, 0);
$dn_optional = ($id <= 0 ? false : true);
$domainname = $this->getParam('domainname', $dn_optional, '');
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'domains')) {
throw new Exception("You cannot access this resource", 405);
}
$domain = $this->apiCall('SubDomains.get', array(
'id' => $id,
'domainname' => $domainname
));
// parameters
$ssl_cert_file = $this->getParam('ssl_cert_file');
$ssl_key_file = $this->getParam('ssl_key_file');
$ssl_ca_file = $this->getParam('ssl_ca_file', true, '');
$ssl_cert_chainfile = $this->getParam('ssl_cert_chainfile', true, '');
$this->addOrUpdateCertificate($domain['id'], $ssl_cert_file, $ssl_key_file, $ssl_ca_file, $ssl_cert_chainfile, false);
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_INFO, "[API] updated ssl-certificate for '" . $domain['domain'] . "'");
$result = $this->apiCall('Certificates.get', array(
'id' => $domain['id']
));
return $this->response(200, "successfull", $result);
}
/**
* lists all certificate entries
*
* @access admin, customer
* @throws Exception
* @return array count|list
*/
public function listing()
{
// select all my (accessable) certificates
$certs_stmt_query = "SELECT s.*, d.domain, d.letsencrypt, c.customerid, c.loginname
FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` s
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON `d`.`id` = `s`.`domainid`
LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` c ON `c`.`customerid` = `d`.`customerid`
WHERE ";
$qry_params = array();
if ($this->isAdmin() && $this->getUserDetail('customers_see_all') == '0') {
// admin with only customer-specific permissions
$certs_stmt_query .= "d.adminid = :adminid ";
$qry_params['adminid'] = $this->getUserDetail('adminid');
} elseif ($this->isAdmin() == false) {
// customer-area
$certs_stmt_query .= "d.customerid = :cid ";
$qry_params['cid'] = $this->getUserDetail('customerid');
} else {
$certs_stmt_query .= "1 ";
}
$certs_stmt = Database::prepare($certs_stmt_query);
Database::pexecute($certs_stmt, $qry_params, true, true);
$result = array();
while ($cert = $certs_stmt->fetch(PDO::FETCH_ASSOC)) {
// respect froxlor-hostname
if ($cert['domainid'] == 0) {
$cert['domain'] = Settings::Get('system.hostname');
$cert['letsencrypt'] = Settings::Get('system.le_froxlor_enabled');
$cert['loginname'] = 'froxlor.panel';
}
$result[] = $cert;
}
return $this->response(200, "successfull", array(
'count' => count($result),
'list' => $result
));
}
/**
* delete certificates entry by id
*
* @param int $id
*
* @return array
* @throws Exception
*/
public function delete()
{
$id = $this->getParam('id');
if ($this->isAdmin() == false) {
$chk_stmt = Database::prepare("
SELECT d.domain FROM `" . TABLE_PANEL_DOMAINS . "` d
LEFT JOIN `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` s ON s.domainid = d.id
WHERE s.`id` = :id AND d.`customerid` = :cid
");
$chk = Database::pexecute_first($chk_stmt, array(
'id' => $id,
'cid' => $this->getUserDetail('customerid')
));
} elseif ($this->isAdmin()) {
$chk_stmt = Database::prepare("
SELECT d.domain FROM `" . TABLE_PANEL_DOMAINS . "` d
LEFT JOIN `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` s ON s.domainid = d.id
WHERE s.`id` = :id" . ($this->getUserDetail('customers_see_all') == '0' ? " AND d.`adminid` = :aid" : ""));
$params = array(
'id' => $id
);
if ($this->getUserDetail('customers_see_all') == '0') {
$params['aid'] = $this->getUserDetail('adminid');
}
$chk = Database::pexecute_first($chk_stmt, $params);
}
if ($chk !== false) {
// additional access check by trying to get the certificate
$result = $this->apiCall('Certificates.get', array(
'domainname' => $chk['domain']
));
$del_stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` WHERE id = :id");
Database::pexecute($del_stmt, array(
'id' => $id
));
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_INFO, "[API] removed ssl-certificate for '" . $chk['domain'] . "'");
return $this->response(200, "successfull", $result);
}
}
/**
* insert or update certificates entry
*
* @param int $domainid
* @param string $ssl_cert_file
* @param string $ssl_key_file
* @param string $ssl_ca_file
* @param string $ssl_cert_chainfile
* @param boolean $do_insert
* optional default false
*
* @return boolean
* @throws Exception
*/
private function addOrUpdateCertificate($domainid = 0, $ssl_cert_file = '', $ssl_key_file = '', $ssl_ca_file = '', $ssl_cert_chainfile = '', $do_insert = false)
{
if ($ssl_cert_file != '' && $ssl_key_file == '') {
standard_error('sslcertificateismissingprivatekey', '', true);
}
$do_verify = true;
// no cert-file given -> forget everything
if ($ssl_cert_file == '') {
$ssl_key_file = '';
$ssl_ca_file = '';
$ssl_cert_chainfile = '';
$do_verify = false;
}
// verify certificate content
if ($do_verify) {
// array openssl_x509_parse ( mixed $x509cert [, bool $shortnames = true ] )
// openssl_x509_parse() returns information about the supplied x509cert, including fields such as
// subject name, issuer name, purposes, valid from and valid to dates etc.
$cert_content = openssl_x509_parse($ssl_cert_file);
if (is_array($cert_content) && isset($cert_content['subject']) && isset($cert_content['subject']['CN'])) {
// bool openssl_x509_check_private_key ( mixed $cert , mixed $key )
// Checks whether the given key is the private key that corresponds to cert.
if (openssl_x509_check_private_key($ssl_cert_file, $ssl_key_file) === false) {
standard_error('sslcertificateinvalidcertkeypair', '', true);
}
// check optional stuff
if ($ssl_ca_file != '') {
$ca_content = openssl_x509_parse($ssl_ca_file);
if (! is_array($ca_content)) {
// invalid
standard_error('sslcertificateinvalidca', '', true);
}
}
if ($ssl_cert_chainfile != '') {
$chain_content = openssl_x509_parse($ssl_cert_chainfile);
if (! is_array($chain_content)) {
// invalid
standard_error('sslcertificateinvalidchain', '', true);
}
}
} else {
standard_error('sslcertificateinvalidcert', '', true);
}
}
// Add/Update database entry
$qrystart = "UPDATE ";
$qrywhere = "WHERE ";
if ($do_insert) {
$qrystart = "INSERT INTO ";
$qrywhere = ", ";
}
$stmt = Database::prepare($qrystart . " `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` SET
`ssl_cert_file` = :ssl_cert_file,
`ssl_key_file` = :ssl_key_file,
`ssl_ca_file` = :ssl_ca_file,
`ssl_cert_chainfile` = :ssl_cert_chainfile
" . $qrywhere . " `domainid`= :domainid
");
$params = array(
"ssl_cert_file" => $ssl_cert_file,
"ssl_key_file" => $ssl_key_file,
"ssl_ca_file" => $ssl_ca_file,
"ssl_cert_chainfile" => $ssl_cert_chainfile,
"domainid" => $domainid
);
Database::pexecute($stmt, $params, true, true);
// insert task to re-generate webserver-configs (#1260)
inserttask('1');
return true;
}
}

View File

@@ -1,158 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package API
* @since 0.10.0
*
*/
class Cronjobs extends ApiCommand implements ResourceEntity
{
/**
* You cannot add new cronjobs yet.
*/
public function add()
{
throw new Exception('You cannot add new cronjobs yet.', 303);
}
/**
* return a cronjob entry by id
*
* @param int $id
* cronjob-id
*
* @access admin
* @throws Exception
* @return array
*/
public function get()
{
if ($this->isAdmin()) {
$id = $this->getParam('id');
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_CRONRUNS . "` WHERE `id` = :id
");
$result = Database::pexecute_first($result_stmt, array(
'id' => $id
), true, true);
if ($result) {
return $this->response(200, "successfull", $result);
}
throw new Exception("cronjob with id #" . $id . " could not be found", 404);
}
throw new Exception("Not allowed to execute given command.", 403);
}
/**
* update a cronjob entry by given id
*
* @param int $id
* @param bool $isactive
* optional whether the cronjob is active or not
* @param int $interval_value
* optional number of seconds/minutes/hours/etc. for the interval
* @param string $interval_interval
* optional interval for the cronjob (MINUTE, HOUR, DAY, WEEK or MONTH)
*
* @access admin
* @throws Exception
* @return array
*/
public function update()
{
if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) {
// required parameter
$id = $this->getParam('id');
$result = $this->apiCall('Cronjobs.get', array(
'id' => $id
));
// split interval
$cur_int = explode(" ", $result['interval']);
// parameter
$isactive = $this->getBoolParam('isactive', true, $result['isactive']);
$interval_value = $this->getParam('interval_value', true, $cur_int[0]);
$interval_interval = $this->getParam('interval_interval', true, $cur_int[1]);
// validation
if ($isactive != 1) {
$isactive = 0;
}
$interval_value = validate($interval_value, 'interval_value', '/^([0-9]+)$/Di', 'stringisempty', array(), true);
$interval_interval = validate($interval_interval, 'interval_interval', '', '', array(), true);
// put together interval value
$interval = $interval_value . ' ' . strtoupper($interval_interval);
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_CRONRUNS . "`
SET `isactive` = :isactive, `interval` = :int
WHERE `id` = :id
");
Database::pexecute($upd_stmt, array(
'isactive' => $isactive,
'int' => $interval,
'id' => $id
), true, true);
// insert task to re-generate the cron.d-file
inserttask('99');
$this->logger()->logAction(ADM_ACTION, LOG_INFO, "[API] cronjob with description '" . $result['module'] . '/' . $result['cronfile'] . "' has been updated by '" . $this->getUserDetail('loginname') . "'");
$result = $this->apiCall('Cronjobs.get', array(
'id' => $id
));
return $this->response(200, "successfull", $result);
}
throw new Exception("Not allowed to execute given command.", 403);
}
/**
* lists all cronjob entries
*
* @access admin
* @throws Exception
* @return array count|list
*/
public function listing()
{
if ($this->isAdmin()) {
$this->logger()->logAction(ADM_ACTION, LOG_NOTICE, "[API] list cronjobs");
$result_stmt = Database::prepare("
SELECT `c`.* FROM `" . TABLE_PANEL_CRONRUNS . "` `c` ORDER BY `module` ASC, `cronfile` ASC
");
Database::pexecute($result_stmt);
$result = array();
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
$result[] = $row;
}
return $this->response(200, "successfull", array(
'count' => count($result),
'list' => $result
));
}
throw new Exception("Not allowed to execute given command.", 403);
}
/**
* You cannot delete system cronjobs.
*/
public function delete()
{
throw new Exception('You cannot delete system cronjobs.', 303);
}
}

View File

@@ -1,202 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package API
* @since 0.10.0
*
*/
class CustomerBackups extends ApiCommand implements ResourceEntity
{
/**
* check whether backup is enabled systemwide and if accessable for customer (hide_options)
*
* @throws Exception
*/
private function validateAccess()
{
if (Settings::Get('system.backupenabled') != 1) {
throw new Exception("You cannot access this resource", 405);
}
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras')) {
throw new Exception("You cannot access this resource", 405);
}
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras.backup')) {
throw new Exception("You cannot access this resource", 405);
}
}
/**
* add a new customer backup job
*
* @param string $path
* path to store the backup to
* @param bool $backup_dbs
* optional whether to backup databases, default is 0 (false)
* @param bool $backup_mail
* optional whether to backup mail-data, default is 0 (false)
* @param bool $backup_web
* optional whether to backup web-data, default is 0 (false)
* @param int $customerid
* required when called as admin, not needed when called as customer
*
* @access admin, customer
* @return array
* @throws Exception
*/
public function add()
{
$this->validateAccess();
// required parameter
$path = $this->getParam('path');
// parameter
$backup_dbs = $this->getBoolParam('backup_dbs', true, 0);
$backup_mail = $this->getBoolParam('backup_mail', true, 0);
$backup_web = $this->getBoolParam('backup_web', true, 0);
// get customer data
$customer = $this->getCustomerData();
// validation
$path = makeCorrectDir(validate($path, 'path', '', '', array(), true));
$userpath = $path;
$path = makeCorrectDir($customer['documentroot'] . '/' . $path);
// path cannot be the customers docroot
if ($path == makeCorrectDir($customer['documentroot'])) {
standard_error('backupfoldercannotbedocroot', '', true);
}
if ($backup_dbs != '1') {
$backup_dbs = '0';
}
if ($backup_mail != '1') {
$backup_mail = '0';
}
if ($backup_web != '1') {
$backup_web = '0';
}
$task_data = array(
'customerid' => $customer['customerid'],
'uid' => $customer['guid'],
'gid' => $customer['guid'],
'loginname' => $customer['loginname'],
'destdir' => $path,
'backup_dbs' => $backup_dbs,
'backup_mail' => $backup_mail,
'backup_web' => $backup_web
);
// schedule backup job
inserttask('20', $task_data);
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_NOTICE, "[API] added customer-backup job for '" . $customer['loginname'] . "'. Target directory: " . $userpath);
return $this->response(200, "successfull", $task_data);
}
/**
* You cannot get a planned backup.
* Try CustomerBackups.listing()
*/
public function get()
{
throw new Exception('You cannot get a planned backup. Try CustomerBackups.listing()', 303);
}
/**
* You cannot update a planned backup.
* You need to delete it and re-add it.
*/
public function update()
{
throw new Exception('You cannot update a planned backup. You need to delete it and re-add it.', 303);
}
/**
* list all planned backup-jobs, if called from an admin, list all planned backup-jobs of all customers you are allowed to view, or specify id or loginname for one specific customer
*
* @param int $customerid
* optional, admin-only, select backup-jobs of a specific customer by id
* @param string $loginname
* optional, admin-only, select backup-jobs of a specific customer by loginname
*
* @access admin, customer
* @throws Exception
* @return array count|list
*/
public function listing()
{
$this->validateAccess();
$customer_ids = $this->getAllowedCustomerIds('extras.backup');
// check whether there is a backup-job for this customer
$sel_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_TASKS . "` WHERE `type` = '20'");
Database::pexecute($sel_stmt);
$result = array();
while ($entry = $sel_stmt->fetch(PDO::FETCH_ASSOC)) {
$entry['data'] = json_decode($entry['data'], true);
if (in_array($entry['data']['customerid'], $customer_ids)) {
$result[] = $entry;
}
}
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_NOTICE, "[API] list customer-backups");
return $this->response(200, "successfull", array(
'count' => count($result),
'list' => $result
));
}
/**
* delete a planned backup-jobs by id, if called from an admin you need to specify the customerid/loginname
*
* @param int $backup_job_entry
* id of backup job
* @param int $customerid
* optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, required when called as admin (if $customerid is not specified)
*
* @access admin, customer
* @throws Exception
* @return bool
*/
public function delete()
{
// get planned backups
$result = $this->apiCall('CustomerBackups.listing', $this->getParamList());
$entry = $this->getParam('backup_job_entry');
$customer_ids = $this->getAllowedCustomerIds('extras.backup');
if ($result['count'] > 0 && $entry > 0) {
// prepare statement
$del_stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_TASKS . "` WHERE `id` = :tid");
// check for the correct job
foreach ($result['list'] as $backupjob) {
if ($backupjob['id'] == $entry && in_array($backupjob['data']['customerid'], $customer_ids)) {
Database::pexecute($del_stmt, array(
'tid' => $entry
));
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_NOTICE, "[API] deleted planned customer-backup #" . $entry);
return $this->response(200, "successfull", true);
}
}
}
throw new Exception('Backup job with id #' . $entry . ' could not be found', 404);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,377 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package API
* @since 0.10.0
*
*/
class DirOptions extends ApiCommand implements ResourceEntity
{
/**
* add options for a given directory
*
* @param int $customerid
* optional, admin-only, the customer-id
* @param string $loginname
* optional, admin-only, the loginname
* @param string $path
* path relative to the customer's home-Directory
* @param bool $options_indexes
* optional, activate directory-listing for this path, default 0 (false)
* @param bool $options_cgi
* optional, allow Perl/CGI execution, default 0 (false)
* @param string $error404path
* optional, custom 404 error string/file
* @param string $error403path
* optional, custom 403 error string/file
* @param string $error500path
* optional, custom 500 error string/file
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function add()
{
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras')) {
throw new Exception("You cannot access this resource", 405);
}
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras.pathoptions')) {
throw new Exception("You cannot access this resource", 405);
}
// get needed customer info to reduce the email-address-counter by one
$customer = $this->getCustomerData();
// required parameters
$path = $this->getParam('path');
// parameters
$options_indexes = $this->getBoolParam('options_indexes', true, 0);
$options_cgi = $this->getBoolParam('options_cgi', true, 0);
$error404path = $this->getParam('error404path', true, '');
$error403path = $this->getParam('error403path', true, '');
$error500path = $this->getParam('error500path', true, '');
// validation
$path = makeCorrectDir(validate($path, 'path', '', '', array(), true));
$userpath = $path;
$path = makeCorrectDir($customer['documentroot'] . '/' . $path);
if (! empty($error404path)) {
$error404path = correctErrorDocument($error404path, true);
}
if (! empty($error403path)) {
$error403path = correctErrorDocument($error403path, true);
}
if (! empty($error500path)) {
$error500path = correctErrorDocument($error500path, true);
}
// check for duplicate path
$path_dupe_check_stmt = Database::prepare("
SELECT `id`, `path` FROM `" . TABLE_PANEL_HTACCESS . "`
WHERE `path`= :path AND `customerid`= :customerid
");
$path_dupe_check = Database::pexecute_first($path_dupe_check_stmt, array(
"path" => $path,
"customerid" => $customer['customerid']
), true, true);
// duplicate check
if ($path_dupe_check['path'] == $path) {
standard_error('errordocpathdupe', $userpath, true);
}
// insert the entry
$stmt = Database::prepare('
INSERT INTO `' . TABLE_PANEL_HTACCESS . '` SET
`customerid` = :customerid,
`path` = :path,
`options_indexes` = :options_indexes,
`error404path` = :error404path,
`error403path` = :error403path,
`error500path` = :error500path,
`options_cgi` = :options_cgi
');
$params = array(
"customerid" => $customer['customerid'],
"path" => $path,
"options_indexes" => $options_indexes,
"error403path" => $error403path,
"error404path" => $error404path,
"error500path" => $error500path,
"options_cgi" => $options_cgi
);
Database::pexecute($stmt, $params, true, true);
$id = Database::lastInsertId();
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_INFO, "[API] added directory-option for '" . $userpath . "'");
inserttask('1');
$result = $this->apiCall('DirOptions.get', array(
'id' => $id
));
return $this->response(200, "successfull", $result);
}
/**
* return a directory-protection entry by id
*
* @param int $id
* id of dir-protection entry
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function get()
{
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras')) {
throw new Exception("You cannot access this resource", 405);
}
$id = $this->getParam('id', true, 0);
$params = array();
if ($this->isAdmin()) {
if ($this->getUserDetail('customers_see_all') == false) {
// if it's a reseller or an admin who cannot see all customers, we need to check
// whether the database belongs to one of his customers
$_custom_list_result = $this->apiCall('Customers.listing');
$custom_list_result = $_custom_list_result['list'];
$customer_ids = array();
foreach ($custom_list_result as $customer) {
$customer_ids[] = $customer['customerid'];
}
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_HTACCESS . "`
WHERE `customerid` IN (" . implode(", ", $customer_ids) . ")
AND `id` = :id
");
} else {
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_HTACCESS . "`
WHERE `id` = :id
");
}
} else {
if (Settings::IsInList('panel.customer_hide_options', 'extras.pathoptions')) {
throw new Exception("You cannot access this resource", 405);
}
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_HTACCESS . "`
WHERE `customerid` = :customerid
AND `id` = :id
");
$params['customerid'] = $this->getUserDetail('customerid');
}
$params['id'] = $id;
$result = Database::pexecute_first($result_stmt, $params, true, true);
if ($result) {
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_NOTICE, "[API] get directory options for '" . $result['path'] . "'");
return $this->response(200, "successfull", $result);
}
$key = "id #" . $id;
throw new Exception("Directory option with " . $key . " could not be found", 404);
}
/**
* update options for a given directory by id
*
* @param int $id
* id of dir-protection entry
* @param int $customerid
* optional, admin-only, the customer-id
* @param string $loginname
* optional, admin-only, the loginname
* @param bool $options_indexes
* optional, activate directory-listing for this path, default 0 (false)
* @param bool $options_cgi
* optional, allow Perl/CGI execution, default 0 (false)
* @param string $error404path
* optional, custom 404 error string/file
* @param string $error403path
* optional, custom 403 error string/file
* @param string $error500path
* optional, custom 500 error string/file
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function update()
{
$id = $this->getParam('id', true, 0);
// validation
$result = $this->apiCall('DirOptions.get', array(
'id' => $id
));
// get needed customer info to reduce the email-address-counter by one
$customer = $this->getCustomerData();
// parameters
$options_indexes = $this->getBoolParam('options_indexes', true, $result['options_indexes']);
$options_cgi = $this->getBoolParam('options_cgi', true, $result['options_cgi']);
$error404path = $this->getParam('error404path', true, $result['error404path']);
$error403path = $this->getParam('error403path', true, $result['error403path']);
$error500path = $this->getParam('error500path', true, $result['error500path']);
if (! empty($error404path)) {
$error404path = correctErrorDocument($error404path, true);
}
if (! empty($error403path)) {
$error403path = correctErrorDocument($error403path, true);
}
if (! empty($error500path)) {
$error500path = correctErrorDocument($error500path, true);
}
if (($options_indexes != $result['options_indexes']) || ($error404path != $result['error404path']) || ($error403path != $result['error403path']) || ($error500path != $result['error500path']) || ($options_cgi != $result['options_cgi'])) {
inserttask('1');
$stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_HTACCESS . "`
SET `options_indexes` = :options_indexes,
`error404path` = :error404path,
`error403path` = :error403path,
`error500path` = :error500path,
`options_cgi` = :options_cgi
WHERE `customerid` = :customerid
AND `id` = :id
");
$params = array(
"customerid" => $customer['customerid'],
"options_indexes" => $options_indexes,
"error403path" => $error403path,
"error404path" => $error404path,
"error500path" => $error500path,
"options_cgi" => $options_cgi,
"id" => $id
);
Database::pexecute($stmt, $params, true, true);
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_INFO, "[API] edited directory options for '" . str_replace($customer['documentroot'], '/', $result['path']) . "'");
}
$result = $this->apiCall('DirOptions.get', array(
'id' => $id
));
return $this->response(200, "successfull", $result);
}
/**
* list all directory-options, if called from an admin, list all directory-options of all customers you are allowed to view, or specify id or loginname for one specific customer
*
* @param int $customerid
* optional, admin-only, select directory-protections of a specific customer by id
* @param string $loginname
* optional, admin-only, select directory-protections of a specific customer by loginname
*
* @access admin, customer
* @throws Exception
* @return array count|list
*/
public function listing()
{
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras')) {
throw new Exception("You cannot access this resource", 405);
}
$customer_ids = $this->getAllowedCustomerIds('extras.pathoptions');
$result = array();
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_HTACCESS . "`
WHERE `customerid` IN (" . implode(', ', $customer_ids) . ")
");
Database::pexecute($result_stmt, null, true, true);
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
$result[] = $row;
}
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_NOTICE, "[API] list directory-options");
return $this->response(200, "successfull", array(
'count' => count($result),
'list' => $result
));
}
/**
* delete a directory-options by id
*
* @param int $id
* id of dir-protection entry
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function delete()
{
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras')) {
throw new Exception("You cannot access this resource", 405);
}
$id = $this->getParam('id');
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras.pathoptions')) {
throw new Exception("You cannot access this resource", 405);
}
// get directory-option
$result = $this->apiCall('DirOptions.get', array(
'id' => $id
));
if ($this->isAdmin()) {
// get customer-data
$customer_data = $this->apiCall('Customers.get', array(
'id' => $result['customerid']
));
} else {
$customer_data = $this->getUserData();
}
// do we have to remove the symlink and folder in suexecpath?
if ((int) Settings::Get('perl.suexecworkaround') == 1) {
$loginname = $customer_data['loginname'];
$suexecpath = makeCorrectDir(Settings::Get('perl.suexecpath') . '/' . $loginname . '/' . md5($result['path']) . '/');
$perlsymlink = makeCorrectFile($result['path'] . '/cgi-bin');
// remove symlink
if (file_exists($perlsymlink)) {
safe_exec('rm -f ' . escapeshellarg($perlsymlink));
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_DEBUG, "[API] deleted suexecworkaround symlink '" . $perlsymlink . "'");
}
// remove folder in suexec-path
if (file_exists($suexecpath)) {
safe_exec('rm -rf ' . escapeshellarg($suexecpath));
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_DEBUG, "[API] deleted suexecworkaround path '" . $suexecpath . "'");
}
}
$stmt = Database::prepare("
DELETE FROM `" . TABLE_PANEL_HTACCESS . "`
WHERE `customerid`= :customerid
AND `id`= :id
");
Database::pexecute($stmt, array(
"customerid" => $customer_data['customerid'],
"id" => $id
));
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_INFO, "[API] deleted directory-option for '" . str_replace($customer_data['documentroot'], '/', $result['path']) . "'");
inserttask('1');
return $this->response(200, "successfull", $result);
}
}

View File

@@ -1,359 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package API
* @since 0.10.0
*
*/
class DirProtections extends ApiCommand implements ResourceEntity
{
/**
* add htaccess protection to a given directory
*
* @param int $customerid
* optional, admin-only, the customer-id
* @param string $loginname
* optional, admin-only, the loginname
* @param string $path
* @param string $username
* @param string $directory_password
* @param string $directory_authname
* optional name/description for the protection
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function add()
{
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras')) {
throw new Exception("You cannot access this resource", 405);
}
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras.directoryprotection')) {
throw new Exception("You cannot access this resource", 405);
}
// get needed customer info to reduce the email-address-counter by one
$customer = $this->getCustomerData();
// required parameters
$path = $this->getParam('path');
$username = $this->getParam('username');
$password = $this->getParam('directory_password');
// parameters
$authname = $this->getParam('directory_authname', true, '');
// validation
$path = makeCorrectDir(validate($path, 'path', '', '', array(), true));
$path = makeCorrectDir($customer['documentroot'] . '/' . $path);
$username = validate($username, 'username', '/^[a-zA-Z0-9][a-zA-Z0-9\-_]+\$?$/', '', array(), true);
$authname = validate($authname, 'directory_authname', '/^[a-zA-Z0-9][a-zA-Z0-9\-_ ]+\$?$/', '', array(), true);
validate($password, 'password', '', '', array(), true);
// check for duplicate usernames for the path
$username_path_check_stmt = Database::prepare("
SELECT `id`, `username`, `path` FROM `" . TABLE_PANEL_HTPASSWDS . "`
WHERE `username`= :username AND `path`= :path AND `customerid`= :customerid
");
$params = array(
"username" => $username,
"path" => $path,
"customerid" => $customer['customerid']
);
$username_path_check = Database::pexecute_first($username_path_check_stmt, $params, true, true);
// check whether we can used salted passwords
if (CRYPT_STD_DES == 1) {
$saltfordescrypt = substr(md5(uniqid(microtime(), 1)), 4, 2);
$password_enc = crypt($password, $saltfordescrypt);
} else {
$password_enc = crypt($password);
}
// duplicate check
if ($username_path_check['username'] == $username && $username_path_check['path'] == $path) {
standard_error('userpathcombinationdupe', '', true);
} elseif ($password == $username) {
standard_error('passwordshouldnotbeusername', '', true);
}
// insert the entry
$stmt = Database::prepare("
INSERT INTO `" . TABLE_PANEL_HTPASSWDS . "` SET
`customerid` = :customerid,
`username` = :username,
`password` = :password,
`path` = :path,
`authname` = :authname
");
$params = array(
"customerid" => $customer['customerid'],
"username" => $username,
"password" => $password_enc,
"path" => $path,
"authname" => $authname
);
Database::pexecute($stmt, $params, true, true);
$id = Database::lastInsertId();
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_INFO, "[API] added directory-protection for '" . $username . " (" . $path . ")'");
inserttask('1');
$result = $this->apiCall('DirProtections.get', array(
'id' => $id
));
return $this->response(200, "successfull", $result);
}
/**
* return a directory-protection entry by either id or username
*
* @param int $id
* optional, the directory-protection-id
* @param string $username
* optional, the username
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function get()
{
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras')) {
throw new Exception("You cannot access this resource", 405);
}
$id = $this->getParam('id', true, 0);
$un_optional = ($id <= 0 ? false : true);
$username = $this->getParam('username', $un_optional, '');
$params = array();
if ($this->isAdmin()) {
if ($this->getUserDetail('customers_see_all') == false) {
// if it's a reseller or an admin who cannot see all customers, we need to check
// whether the database belongs to one of his customers
$_custom_list_result = $this->apiCall('Customers.listing');
$custom_list_result = $_custom_list_result['list'];
$customer_ids = array();
foreach ($custom_list_result as $customer) {
$customer_ids[] = $customer['customerid'];
}
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_HTPASSWDS . "`
WHERE `customerid` IN (" . implode(", ", $customer_ids) . ")
AND (`id` = :idun OR `username` = :idun)
");
} else {
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_HTPASSWDS . "`
WHERE (`id` = :idun OR `username` = :idun)
");
}
} else {
if (Settings::IsInList('panel.customer_hide_options', 'extras.directoryprotection')) {
throw new Exception("You cannot access this resource", 405);
}
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_HTPASSWDS . "`
WHERE `customerid` = :customerid
AND (`id` = :idun OR `username` = :idun)
");
$params['customerid'] = $this->getUserDetail('customerid');
}
$params['idun'] = ($id <= 0 ? $username : $id);
$result = Database::pexecute_first($result_stmt, $params, true, true);
if ($result) {
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_NOTICE, "[API] get directory protection for '" . $result['path'] . "'");
return $this->response(200, "successfull", $result);
}
$key = ($id > 0 ? "id #" . $id : "username '" . $username . "'");
throw new Exception("Directory protection with " . $key . " could not be found", 404);
}
/**
* update htaccess protection of a given directory
*
* @param int $id
* optional the directory-protection-id
* @param string $username
* optional, the username
* @param int $customerid
* optional, admin-only, the customer-id
* @param string $loginname
* optional, admin-only, the loginname
* @param string $directory_password
* optional, leave empty for no change
* @param string $directory_authname
* optional name/description for the protection
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function update()
{
$id = $this->getParam('id', true, 0);
$un_optional = ($id <= 0 ? false : true);
$username = $this->getParam('username', $un_optional, '');
// validation
$result = $this->apiCall('DirProtections.get', array(
'id' => $id,
'username' => $username
));
$id = $result['id'];
// parameters
$password = $this->getParam('directory_password', true, '');
$authname = $this->getParam('directory_authname', true, $result['authname']);
// get needed customer info
$customer = $this->getCustomerData();
// validation
$authname = validate($authname, 'directory_authname', '/^[a-zA-Z0-9][a-zA-Z0-9\-_ ]+\$?$/', '', array(), true);
validate($password, 'password', '', '', array(), true);
$upd_query = "";
$upd_params = array(
"id" => $result['id'],
"cid" => $customer['customerid']
);
if (! empty($password)) {
if ($password == $result['username']) {
standard_error('passwordshouldnotbeusername', '', true);
}
if (CRYPT_STD_DES == 1) {
$saltfordescrypt = substr(md5(uniqid(microtime(), 1)), 4, 2);
$password_enc = crypt($password, $saltfordescrypt);
} else {
$password_enc = crypt($password);
}
$upd_query .= "`password`= :password_enc";
$upd_params['password_enc'] = $password_enc;
}
if ($authname != $result['authname']) {
if (! empty($upd_query)) {
$upd_query .= ", ";
}
$upd_query .= "`authname` = :authname";
$upd_params['authname'] = $authname;
}
// build update query
if (! empty($upd_query)) {
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_HTPASSWDS . "` SET " . $upd_query . " WHERE `id` = :id AND `customerid`= :cid
");
Database::pexecute($upd_stmt, $upd_params, true, true);
inserttask('1');
}
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_INFO, "[API] updated directory-protection '" . $result['username'] . " (" . $result['path'] . ")'");
$result = $this->apiCall('DirProtections.get', array(
'id' => $result['id']
));
return $this->response(200, "successfull", $result);
}
/**
* list all directory-protections, if called from an admin, list all directory-protections of all customers you are allowed to view, or specify id or loginname for one specific customer
*
* @param int $customerid
* optional, admin-only, select directory-protections of a specific customer by id
* @param string $loginname
* optional, admin-only, select directory-protections of a specific customer by loginname
*
* @access admin, customer
* @throws Exception
* @return array count|list
*/
public function listing()
{
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras')) {
throw new Exception("You cannot access this resource", 405);
}
$customer_ids = $this->getAllowedCustomerIds('extras.directoryprotection');
$result = array();
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_HTPASSWDS . "`
WHERE `customerid` IN (" . implode(', ', $customer_ids) . ")
");
Database::pexecute($result_stmt, null, true, true);
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
$result[] = $row;
}
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_NOTICE, "[API] list directory-protections");
return $this->response(200, "successfull", array(
'count' => count($result),
'list' => $result
));
}
/**
* delete a directory-protection by either id or username
*
* @param int $id
* optional, the directory-protection-id
* @param string $username
* optional, the username
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function delete()
{
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras')) {
throw new Exception("You cannot access this resource", 405);
}
$id = $this->getParam('id', true, 0);
$un_optional = ($id <= 0 ? false : true);
$username = $this->getParam('username', $un_optional, '');
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras.directoryprotection')) {
throw new Exception("You cannot access this resource", 405);
}
// get directory protection
$result = $this->apiCall('DirProtections.get', array(
'id' => $id,
'username' => $username
));
$id = $result['id'];
if ($this->isAdmin()) {
// get customer-data
$customer_data = $this->apiCall('Customers.get', array(
'id' => $result['customerid']
));
} else {
$customer_data = $this->getUserData();
}
$stmt = Database::prepare("
DELETE FROM `" . TABLE_PANEL_HTPASSWDS . "` WHERE `customerid`= :customerid AND `id`= :id
");
Database::pexecute($stmt, array(
"customerid" => $customer_data['customerid'],
"id" => $id
));
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_INFO, "[API] deleted htpasswd for '" . $result['username'] . " (" . $result['path'] . ")'");
inserttask('1');
return $this->response(200, "successfull", $result);
}
}

View File

@@ -1,396 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package API
* @since 0.10.0
*
*/
class DomainZones extends ApiCommand implements ResourceEntity
{
/**
* add a new dns zone for a given domain by id or domainname
*
* @param int $id
* optional domain id
* @param string $domainname
* optional domain name
* @param string $record
* optional, default empty
* @param string $type
* optional, zone-entry type (A, AAAA, TXT, etc.), default 'A'
* @param int $prio
* optional, priority, default empty
* @param string $content
* optional, default empty
* @param int $ttl
* optional, default 18000
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function add()
{
if (Settings::Get('system.dnsenabled') != '1') {
throw new Exception("DNS server not enabled on this system", 405);
}
$id = $this->getParam('id', true, 0);
$dn_optional = ($id <= 0 ? false : true);
$domainname = $this->getParam('domainname', $dn_optional, '');
// get requested domain
$result = $this->apiCall('SubDomains.get', array(
'id' => $id,
'domainname' => $domainname
));
$id = $result['id'];
// parameters
$record = $this->getParam('record', true, null);
$type = $this->getParam('type', true, 'A');
$prio = $this->getParam('prio', true, null);
$content = $this->getParam('content', true, null);
$ttl = $this->getParam('ttl', true, 18000);
if ($result['parentdomainid'] != '0') {
throw new Exception("DNS zones can only be generated for the main domain, not for subdomains", 406);
}
if ($result['subisbinddomain'] != '1') {
standard_error('dns_domain_nodns', '', true);
}
$idna_convert = new idna_convert_wrapper();
$domain = $idna_convert->encode($result['domain']);
// select all entries
$sel_stmt = Database::prepare("SELECT * FROM `" . TABLE_DOMAIN_DNS . "` WHERE domain_id = :did");
Database::pexecute($sel_stmt, array(
'did' => $id
), true, true);
$dom_entries = $sel_stmt->fetchAll(PDO::FETCH_ASSOC);
// validation
$errors = array();
if (empty($record)) {
$record = "@";
}
$record = trim(strtolower($record));
if ($record != '@' && $record != '*') {
// validate record
if (strpos($record, '--') !== false) {
$errors[] = $this->lng['error']['domain_nopunycode'];
} else {
// check for wildcard-record
$add_wildcard_again = false;
if (substr($record, 0, 2) == '*.') {
$record = substr($record, 2);
$add_wildcard_again = true;
}
// convert entry
$record = $idna_convert->encode($record);
if ($add_wildcard_again) {
$record = '*.' . $record;
}
if (strlen($record) > 63) {
$errors[] = $this->lng['error']['dns_record_toolong'];
}
}
}
// TODO regex validate content for invalid characters
if ($ttl <= 0) {
$ttl = 18000;
}
$content = trim($content);
if (empty($content)) {
$errors[] = $this->lng['error']['dns_content_empty'];
}
// types
if ($type == 'A' && filter_var($content, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false) {
$errors[] = $this->lng['error']['dns_arec_noipv4'];
} elseif ($type == 'AAAA' && filter_var($content, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false) {
$errors[] = $this->lng['error']['dns_aaaarec_noipv6'];
} elseif ($type == 'MX') {
if ($prio === null || $prio < 0) {
$errors[] = $this->lng['error']['dns_mx_prioempty'];
}
// check for trailing dot
if (substr($content, - 1) == '.') {
// remove it for checks
$content = substr($content, 0, - 1);
}
if (! validateDomain($content)) {
$errors[] = $this->lng['error']['dns_mx_needdom'];
} else {
// check whether there is a CNAME-record for the same resource
foreach ($dom_entries as $existing_entries) {
$fqdn = $existing_entries['record'] . '.' . $domain;
if ($existing_entries['type'] == 'CNAME' && $fqdn == $content) {
$errors[] = $this->lng['error']['dns_mx_noalias'];
break;
}
}
}
// append trailing dot (again)
$content .= '.';
} elseif ($type == 'CNAME') {
// check for trailing dot
if (substr($content, - 1) == '.') {
// remove it for checks
$content = substr($content, 0, - 1);
} else {
// add domain name
$content .= '.' . $domain;
}
if (! validateDomain($content, true)) {
$errors[] = $this->lng['error']['dns_cname_invaliddom'];
} else {
// check whether there are RR-records for the same resource
foreach ($dom_entries as $existing_entries) {
if (($existing_entries['type'] == 'A' || $existing_entries['type'] == 'AAAA' || $existing_entries['type'] == 'MX' || $existing_entries['type'] == 'NS') && $existing_entries['record'] == $record) {
$errors[] = $this->lng['error']['dns_cname_nomorerr'];
break;
}
}
}
// append trailing dot (again)
$content .= '.';
} elseif ($type == 'NS') {
// check for trailing dot
if (substr($content, - 1) == '.') {
// remove it for checks
$content = substr($content, 0, - 1);
}
if (! validateDomain($content)) {
$errors[] = $this->lng['error']['dns_ns_invaliddom'];
}
// append trailing dot (again)
$content .= '.';
} elseif ($type == 'TXT' && ! empty($content)) {
// check that TXT content is enclosed in " "
$content = encloseTXTContent($content);
} elseif ($type == 'SRV') {
if ($prio === null || $prio < 0) {
$errors[] = $this->lng['error']['dns_srv_prioempty'];
}
// check only last part of content, as it can look like:
// _service._proto.name. TTL class SRV priority weight port target.
$_split_content = explode(" ", $content);
// SRV content must be [weight] [port] [target]
if (count($_split_content) != 3) {
$errors[] = $this->lng['error']['dns_srv_invalidcontent'];
}
$target = trim($_split_content[count($_split_content) - 1]);
if ($target != '.') {
// check for trailing dot
if (substr($target, - 1) == '.') {
// remove it for checks
$target = substr($target, 0, - 1);
}
}
if ($target != '.' && ! validateDomain($target, true)) {
$errors[] = $this->lng['error']['dns_srv_needdom'];
} else {
// check whether there is a CNAME-record for the same resource
foreach ($dom_entries as $existing_entries) {
$fqdn = $existing_entries['record'] . '.' . $domain;
if ($existing_entries['type'] == 'CNAME' && $fqdn == $target) {
$errors[] = $this->lng['error']['dns_srv_noalias'];
break;
}
}
}
// append trailing dot if there's none
if (substr($content, - 1) != '.') {
$content .= '.';
}
}
$new_entry = array(
'record' => $record,
'type' => $type,
'prio' => (int) $prio,
'content' => $content,
'ttl' => (int) $ttl,
'domain_id' => (int) $id
);
ksort($new_entry);
// check for duplicate
foreach ($dom_entries as $existing_entry) {
// compare json-encoded string of array
$check_entry = $existing_entry;
// new entry has no ID yet
unset($check_entry['id']);
// sort by key
ksort($check_entry);
// format integer fields to real integer (as they are read as string from the DB)
$check_entry['prio'] = (int) $check_entry['prio'];
$check_entry['ttl'] = (int) $check_entry['ttl'];
$check_entry['domain_id'] = (int) $check_entry['domain_id'];
// encode both
$check_entry = json_encode($check_entry);
$new = json_encode($new_entry);
// compare
if ($check_entry === $new) {
$errors[] = $this->lng['error']['dns_duplicate_entry'];
unset($check_entry);
break;
}
}
if (empty($errors)) {
$ins_stmt = Database::prepare("
INSERT INTO `" . TABLE_DOMAIN_DNS . "` SET
`record` = :record,
`type` = :type,
`prio` = :prio,
`content` = :content,
`ttl` = :ttl,
`domain_id` = :domain_id
");
Database::pexecute($ins_stmt, $new_entry, true, true);
$new_entry_id = Database::lastInsertId();
// add temporary to the entries-array (no reread of DB necessary)
$new_entry['id'] = $new_entry_id;
$dom_entries[] = $new_entry;
// re-generate bind configs
inserttask('4');
$result = $this->apiCall('DomainZones.get', array(
'id' => $id
));
return $this->response(200, "successfull", $result);
}
// return $errors
throw new Exception(implode("\n", $errors));
}
/**
* return a domain-dns entry by either id or domainname
*
* @param int $id
* optional, the domain id
* @param string $domainname
* optional, the domain name
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function get()
{
if (Settings::Get('system.dnsenabled') != '1') {
throw new Exception("DNS server not enabled on this system", 405);
}
$id = $this->getParam('id', true, 0);
$dn_optional = ($id <= 0 ? false : true);
$domainname = $this->getParam('domainname', $dn_optional, '');
// get requested domain
$result = $this->apiCall('SubDomains.get', array(
'id' => $id,
'domainname' => $domainname
));
$id = $result['id'];
if ($result['parentdomainid'] != '0') {
throw new Exception("DNS zones can only be generated for the main domain, not for subdomains", 406);
}
if ($result['subisbinddomain'] != '1') {
standard_error('dns_domain_nodns', '', true);
}
$zone = createDomainZone($id);
$zonefile = (string) $zone;
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_NOTICE, "[API] get dns-zone for '" . $result['domain'] . "'");
return $this->response(200, "successfull", explode("\n", $zonefile));
}
/**
* You cannot update a dns zone entry.
* You need to delete it and re-add it.
*/
public function update()
{
throw new Exception('You cannot update a dns zone entry. You need to delete it and re-add it.', 303);
}
/**
* You cannot list dns zones.
* To get all domains use Domains.listing() or SubDomains.listing()
*/
public function listing()
{
throw new Exception('You cannot list dns zones. To get all domains use Domains.listing() or SubDomains.listing()', 303);
}
/**
* deletes a domain-dns entry by id
*
* @param int $entry_id
* @param int $id
* optional, the domain id
* @param string $domainname
* optional, the domain name
*
* @access admin, customer
* @throws Exception
* @return bool
*/
public function delete()
{
if (Settings::Get('system.dnsenabled') != '1') {
throw new Exception("DNS server not enabled on this system", 405);
}
$entry_id = $this->getParam('entry_id');
$id = $this->getParam('id', true, 0);
$dn_optional = ($id <= 0 ? false : true);
$domainname = $this->getParam('domainname', $dn_optional, '');
// get requested domain
$result = $this->apiCall('SubDomains.get', array(
'id' => $id,
'domainname' => $domainname
));
$id = $result['id'];
$del_stmt = Database::prepare("DELETE FROM `" . TABLE_DOMAIN_DNS . "` WHERE `id` = :id AND `domain_id` = :did");
Database::pexecute($del_stmt, array(
'id' => $entry_id,
'did' => $id
), true, true);
if ($del_stmt->rowCount() > 0) {
// re-generate bind configs
inserttask('4');
return $this->response(200, "successfull", true);
}
return $this->response(304, "successfull", true);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,486 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package API
* @since 0.10.0
*
*/
class EmailAccounts extends ApiCommand implements ResourceEntity
{
/**
* add a new email account for a given email-address either by id or emailaddr
*
* @param int $id
* optional email-address-id of email-address to add the account for
* @param string $emailaddr
* optional email-address to add the account for
* @param int $customerid
* optional, admin-only, the customer-id
* @param string $loginname
* optional, admin-only, the loginname
* @param string $email_password
* password for the account
* @param string $alternative_email
* optional email address to send account information to, default is the account that is being created
* @param int $email_quota
* optional quota if enabled in MB, default 0
* @param bool $sendinfomail
* optional, sends the welcome message to the new account (needed for creation, without the user won't be able to login before any mail is received), default 1 (true)
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function add()
{
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) {
throw new Exception("You cannot access this resource", 405);
}
if ($this->getUserDetail('email_accounts_used') < $this->getUserDetail('email_accounts') || $this->getUserDetail('email_accounts') == '-1') {
// parameter
$id = $this->getParam('id', true, 0);
$ea_optional = ($id <= 0 ? false : true);
$emailaddr = $this->getParam('emailaddr', $ea_optional, '');
$email_password = $this->getParam('email_password');
$alternative_email = $this->getParam('alternative_email', true, '');
$quota = $this->getParam('email_quota', true, 0);
$sendinfomail = $this->getBoolParam('sendinfomail', true, 1);
// validation
$quota = validate($quota, 'email_quota', '/^\d+$/', 'vmailquotawrong', array(), true);
// get needed customer info to reduce the email-account-counter by one
$customer = $this->getCustomerData('email_accounts');
// check for imap||pop3 == 1, see #1298
if ($customer['imap'] != '1' && $customer['pop3'] != '1') {
standard_error('notallowedtouseaccounts', '', true);
}
// get email address
$result = $this->apiCall('Emails.get', array(
'id' => $id,
'emailaddr' => $emailaddr
));
$id = $result['id'];
$email_full = $result['email_full'];
$idna_convert = new idna_convert_wrapper();
$username = $idna_convert->decode($email_full);
$password = validate($email_password, 'password', '', '', array(), true);
$password = validatePassword($password, true);
if ($result['popaccountid'] != 0) {
throw new Exception("Email address '" . $email_full . "' has already an account assigned.", 406);
}
if (checkMailAccDeletionState($email_full)) {
standard_error(array(
'mailaccistobedeleted'
), $email_full, true);
}
// alternative email address to send info to
if (Settings::Get('panel.sendalternativemail') == 1) {
$alternative_email = $idna_convert->encode(validate($alternative_email, 'alternative_email', '', '', array(), true));
if (! validateEmail($alternative_email)) {
standard_error('emailiswrong', $alternative_email, true);
}
} else {
$alternative_email = '';
}
// validate quota if enabled
if (Settings::Get('system.mail_quota_enabled') == 1) {
if ($customer['email_quota'] != '-1' && ($quota == 0 || ($quota + $customer['email_quota_used']) > $customer['email_quota'])) {
standard_error('allocatetoomuchquota', $quota, true);
}
} else {
// disable
$quota = 0;
}
if ($password == $email_full) {
standard_error('passwordshouldnotbeusername', '', true);
}
// encrypt the password
$cryptPassword = makeCryptPassword($password);
$email_user = substr($email_full, 0, strrpos($email_full, "@"));
$email_domain = substr($email_full, strrpos($email_full, "@") + 1);
$maildirname = trim(Settings::Get('system.vmail_maildirname'));
// Add trailing slash to Maildir if needed
$maildirpath = $maildirname;
if (! empty($maildirname) && substr($maildirname, - 1) != "/") {
$maildirpath .= "/";
}
// insert data
$stmt = Database::prepare("INSERT INTO `" . TABLE_MAIL_USERS . "` SET
`customerid` = :cid,
`email` = :email,
`username` = :username," . (Settings::Get('system.mailpwcleartext') == '1' ? '`password` = :password, ' : '') . "
`password_enc` = :password_enc,
`homedir` = :homedir,
`maildir` = :maildir,
`uid` = :uid,
`gid` = :gid,
`domainid` = :domainid,
`postfix` = 'y',
`quota` = :quota,
`imap` = :imap,
`pop3` = :pop3
");
$params = array(
"cid" => $customer['customerid'],
"email" => $email_full,
"username" => $username,
"password_enc" => $cryptPassword,
"homedir" => Settings::Get('system.vmail_homedir'),
"maildir" => $customer['loginname'] . '/' . $email_domain . "/" . $email_user . "/" . $maildirpath,
"uid" => Settings::Get('system.vmail_uid'),
"gid" => Settings::Get('system.vmail_gid'),
"domainid" => $result['domainid'],
"quota" => $quota,
"imap" => $customer['imap'],
"pop3" => $customer['pop3']
);
if (Settings::Get('system.mailpwcleartext') == '1') {
$params["password"] = $password;
}
Database::pexecute($stmt, $params, true, true);
$popaccountid = Database::lastInsertId();
// add email address to its destination field
$result['destination'] .= ' ' . $email_full;
$stmt = Database::prepare("
UPDATE `" . TABLE_MAIL_VIRTUAL . "` SET `destination` = :destination, `popaccountid` = :popaccountid
WHERE `customerid`= :cid AND `id`= :id
");
$params = array(
"destination" => makeCorrectDestination($result['destination']),
"popaccountid" => $popaccountid,
"cid" => $customer['customerid'],
"id" => $id
);
Database::pexecute($stmt, $params, true, true);
// update customer usage
Customers::increaseUsage($customer['customerid'], 'email_accounts_used');
Customers::increaseUsage($customer['customerid'], 'email_quota_used', '', $quota);
// update admin usage
Admins::increaseUsage($customer['adminid'], 'email_accounts_used');
Admins::increaseUsage($customer['adminid'], 'email_quota_used', '', $quota);
if ($sendinfomail) {
// replacer array for mail to create account on server
$replace_arr = array(
'EMAIL' => $email_full,
'USERNAME' => $username,
'PASSWORD' => $password
);
// get the customers admin
$stmt = Database::prepare("SELECT `name`, `email` FROM `" . TABLE_PANEL_ADMINS . "` WHERE `adminid`= :adminid");
$admin = Database::pexecute_first($stmt, array(
"adminid" => $customer['adminid']
));
// get template for mail subject
$mail_subject = $this->getMailTemplate($customer, 'mails', 'pop_success_subject', $replace_arr, $this->lng['mails']['pop_success']['subject']);
// get template for mail body
$mail_body = $this->getMailTemplate($customer, 'mails', 'pop_success_mailbody', $replace_arr, $this->lng['mails']['pop_success']['mailbody']);
$_mailerror = false;
$mailerr_msg = "";
try {
$this->mailer()->setFrom($admin['email'], getCorrectUserSalutation($admin));
$this->mailer()->Subject = $mail_subject;
$this->mailer()->AltBody = $mail_body;
$this->mailer()->msgHTML(str_replace("\n", "<br />", $mail_body));
$this->mailer()->addAddress($email_full);
$this->mailer()->send();
} catch (phpmailerException $e) {
$mailerr_msg = $e->errorMessage();
$_mailerror = true;
} catch (Exception $e) {
$mailerr_msg = $e->getMessage();
$_mailerror = true;
}
if ($_mailerror) {
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_ERR, "[API] Error sending mail: " . $mailerr_msg);
standard_error('errorsendingmail', $email_full, true);
}
$this->mailer()->clearAddresses();
// customer wants to send the e-mail to an alternative email address too
if (Settings::Get('panel.sendalternativemail') == 1) {
// get template for mail subject
$mail_subject = $this->getMailTemplate($customer, 'mails', 'pop_success_alternative_subject', $replace_arr, $this->lng['mails']['pop_success_alternative']['subject']);
// get template for mail body
$mail_body = $this->getMailTemplate($customer, 'mails', 'pop_success_alternative_mailbody', $replace_arr, $this->lng['mails']['pop_success_alternative']['mailbody']);
$_mailerror = false;
try {
$this->mailer()->setFrom($admin['email'], getCorrectUserSalutation($admin));
$this->mailer()->Subject = $mail_subject;
$this->mailer()->AltBody = $mail_body;
$this->mailer()->msgHTML(str_replace("\n", "<br />", $mail_body));
$this->mailer()->addAddress($idna_convert->encode($alternative_email), getCorrectUserSalutation($customer));
$this->mailer()->send();
} catch (phpmailerException $e) {
$mailerr_msg = $e->errorMessage();
$_mailerror = true;
} catch (Exception $e) {
$mailerr_msg = $e->getMessage();
$_mailerror = true;
}
if ($_mailerror) {
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_ERR, "[API] Error sending mail: " . $mailerr_msg);
standard_error(array(
'errorsendingmail'
), $alternative_email, true);
}
$this->mailer()->clearAddresses();
}
}
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_INFO, "[API] added email account for '" . $result['email_full'] . "'");
$result = $this->apiCall('Emails.get', array(
'emailaddr' => $result['email_full']
));
return $this->response(200, "successfull", $result);
}
throw new Exception("No more resources available", 406);
}
/**
* You cannot directly get an email account.
* You need to call Emails.get()
*/
public function get()
{
throw new Exception('You cannot directly get an email account. You need to call Emails.get()', 303);
}
/**
* update email-account entry for given email-address by either id or email-address
*
* @param int $id
* optional, the email-address-id
* @param string $emailaddr
* optional, the email-address to update
* @param int $customerid
* optional, admin-only, the customer-id
* @param string $loginname
* optional, admin-only, the loginname
* @param int $email_quota
* optional, update quota
* @param string $email_password
* optional, update password
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function update()
{
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) {
throw new Exception("You cannot access this resource", 405);
}
// parameter
$id = $this->getParam('id', true, 0);
$ea_optional = ($id <= 0 ? false : true);
$emailaddr = $this->getParam('emailaddr', $ea_optional, '');
// validation
$result = $this->apiCall('Emails.get', array(
'id' => $id,
'emailaddr' => $emailaddr
));
$id = $result['id'];
if (empty($result['popaccountid']) || $result['popaccountid'] == 0) {
throw new Exception("Email address '" . $result['email_full'] . "' has no account assigned.", 406);
}
$password = $this->getParam('email_password', true, '');
$quota = $this->getParam('email_quota', true, $result['quota']);
// get needed customer info to reduce the email-account-counter by one
$customer = $this->getCustomerData();
// validation
$quota = validate($quota, 'email_quota', '/^\d+$/', 'vmailquotawrong', array(), true);
$upd_query = "";
$upd_params = array(
"id" => $result['popaccountid'],
"cid" => $customer['customerid']
);
if (! empty($password)) {
if ($password == $result['email_full']) {
standard_error('passwordshouldnotbeusername', '', true);
}
$password = validatePassword($password, true);
$cryptPassword = makeCryptPassword($password);
$upd_query .= (Settings::Get('system.mailpwcleartext') == '1' ? "`password` = :password, " : '') . "`password_enc`= :password_enc";
$upd_params['password_enc'] = $cryptPassword;
if (Settings::Get('system.mailpwcleartext') == '1') {
$upd_params['password'] = $password;
}
}
if (Settings::Get('system.mail_quota_enabled') == 1) {
if ($quota != $result['quota']) {
if ($customer['email_quota'] != '-1' && ($quota == 0 || ($quota + $customer['email_quota_used'] - $result['quota']) > $customer['email_quota'])) {
standard_error('allocatetoomuchquota', $quota, true);
}
if (! empty($upd_query)) {
$upd_query .= ", ";
}
$upd_query .= "`quota` = :quota";
$upd_params['quota'] = $quota;
}
} else {
// disable
$quota = 0;
}
// build update query
if (! empty($upd_query)) {
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_MAIL_USERS . "` SET " . $upd_query . " WHERE `id` = :id AND `customerid`= :cid
");
Database::pexecute($upd_stmt, $upd_params, true, true);
}
if ($customer['email_quota'] != '-1') {
Customers::increaseUsage($customer['customerid'], 'email_quota_used', '', ($quota - $result['quota']));
Admins::increaseUsage($customer['adminid'], 'email_quota_used', '', ($quota - $result['quota']));
}
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_INFO, "[API] updated email account '" . $result['email_full'] . "'");
$result = $this->apiCall('Emails.get', array(
'emailaddr' => $result['email_full']
));
return $this->response(200, "successfull", $result);
}
/**
* You cannot directly list email forwarders.
* You need to call Emails.listing()
*/
public function listing()
{
throw new Exception('You cannot directly list email forwarders. You need to call Emails.listing()', 303);
}
/**
* delete email-account entry for given email-address by either id or email-address
*
* @param int $id
* optional, the email-address-id
* @param string $emailaddr
* optional, the email-address to delete the account for
* @param int $customerid
* optional, admin-only, the customer-id
* @param string $loginname
* optional, admin-only, the loginname
* @param bool $delete_userfiles
* optional, default false
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function delete()
{
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) {
throw new Exception("You cannot access this resource", 405);
}
// parameter
$id = $this->getParam('id', true, 0);
$ea_optional = ($id <= 0 ? false : true);
$emailaddr = $this->getParam('emailaddr', $ea_optional, '');
$delete_userfiles = $this->getBoolParam('delete_userfiles', true, 0);
// validation
$result = $this->apiCall('Emails.get', array(
'id' => $id,
'emailaddr' => $emailaddr
));
$id = $result['id'];
if (empty($result['popaccountid']) || $result['popaccountid'] == 0) {
throw new Exception("Email address '" . $result['email_full'] . "' has no account assigned.", 406);
}
// get needed customer info to reduce the email-account-counter by one
$customer = $this->getCustomerData();
// delete entry
$stmt = Database::prepare("
DELETE FROM `" . TABLE_MAIL_USERS . "` WHERE `customerid`= :cid AND `id`= :id
");
Database::pexecute($stmt, array(
"cid" => $customer['customerid'],
"id" => $result['popaccountid']
), true, true);
// update mail-virtual entry
$result['destination'] = str_replace($result['email_full'], '', $result['destination']);
$stmt = Database::prepare("
UPDATE `" . TABLE_MAIL_VIRTUAL . "` SET `destination` = :dest, `popaccountid` = '0' WHERE `customerid`= :cid AND `id`= :id
");
$params = array(
"dest" => makeCorrectDestination($result['destination']),
"cid" => $customer['customerid'],
"id" => $id
);
Database::pexecute($stmt, $params, true, true);
$result['popaccountid'] = 0;
if (Settings::Get('system.mail_quota_enabled') == '1' && $customer['email_quota'] != '-1') {
$quota = (int) $result['quota'];
} else {
$quota = 0;
}
if ($delete_userfiles) {
inserttask('7', $customer['loginname'], $result['email_full']);
}
// decrease usage for customer
Customers::decreaseUsage($customer['customerid'], 'email_accounts_used');
Customers::decreaseUsage($customer['customerid'], 'email_quota_used', '', $quota);
// decrease admin usage
Admins::decreaseUsage($customer['adminid'], 'email_accounts_used');
Admins::decreaseUsage($customer['adminid'], 'email_quota_used', '', $quota);
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_INFO, "[API] deleted email account for '" . $result['email_full'] . "'");
return $this->response(200, "successfull", $result);
}
}

View File

@@ -1,210 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package API
* @since 0.10.0
*
*/
class EmailForwarders extends ApiCommand implements ResourceEntity
{
/**
* add new email-forwarder entry for given email-address by either id or email-address
*
* @param int $id
* optional, the email-address-id
* @param string $emailaddr
* optional, the email-address to add the forwarder for
* @param int $customerid
* optional, admin-only, the customer-id
* @param string $loginname
* optional, admin-only, the loginname
* @param string $destination
* email-address to add as forwarder
*
* @access admin,customer
* @throws Exception
* @return array
*/
public function add()
{
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) {
throw new Exception("You cannot access this resource", 405);
}
if ($this->getUserDetail('email_forwarders_used') < $this->getUserDetail('email_forwarders') || $this->getUserDetail('email_forwarders') == '-1') {
// parameter
$id = $this->getParam('id', true, 0);
$ea_optional = ($id <= 0 ? false : true);
$emailaddr = $this->getParam('emailaddr', $ea_optional, '');
$destination = $this->getParam('destination');
// validation
$idna_convert = new idna_convert_wrapper();
$destination = $idna_convert->encode($destination);
$result = $this->apiCall('Emails.get', array(
'id' => $id,
'emailaddr' => $emailaddr
));
$id = $result['id'];
// current destination array
$result['destination_array'] = explode(' ', $result['destination']);
// prepare destination
$destination = trim($destination);
if (! validateEmail($destination)) {
standard_error('destinationiswrong', $destination, true);
} elseif ($destination == $result['email']) {
standard_error('destinationalreadyexistasmail', $destination, true);
} elseif (in_array($destination, $result['destination_array'])) {
standard_error('destinationalreadyexist', $destination, true);
}
// get needed customer info to reduce the email-forwarder-counter by one
$customer = $this->getCustomerData('email_forwarders');
// add destination to address
$result['destination'] .= ' ' . $destination;
$stmt = Database::prepare("
UPDATE `" . TABLE_MAIL_VIRTUAL . "` SET `destination` = :dest
WHERE `customerid`= :cid AND `id`= :id
");
$params = array(
"dest" => makeCorrectDestination($result['destination']),
"cid" => $customer['customerid'],
"id" => $id
);
Database::pexecute($stmt, $params, true, true);
// update customer usage
Customers::increaseUsage($customer['customerid'], 'email_forwarders_used');
// update admin usage
Admins::increaseUsage($customer['adminid'], 'email_forwarders_used');
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_INFO, "[API] added email forwarder for '" . $result['email_full'] . "'");
$result = $this->apiCall('Emails.get', array(
'emailaddr' => $result['email_full']
));
return $this->response(200, "successfull", $result);
}
throw new Exception("No more resources available", 406);
}
/**
* You cannot directly get an email forwarder.
* You need to call Emails.get()
*/
public function get()
{
throw new Exception('You cannot directly get an email forwarder. You need to call Emails.get()', 303);
}
/**
* You cannot update an email forwarder.
* You need to delete the entry and create a new one.
*/
public function update()
{
throw new Exception('You cannot update an email forwarder. You need to delete the entry and create a new one.', 303);
}
/**
* You cannot directly list email forwarders.
* You need to call Emails.listing()
*/
public function listing()
{
throw new Exception('You cannot directly list email forwarders. You need to call Emails.listing()', 303);
}
/**
* delete email-forwarder entry for given email-address by either id or email-address and forwarder-id
*
* @param int $id
* optional, the email-address-id
* @param string $emailaddr
* optional, the email-address to delete the forwarder from
* @param int $customerid
* optional, admin-only, the customer-id
* @param string $loginname
* optional, admin-only, the loginname
* @param int $forwarderid
* id of the forwarder to delete
*
* @access admin,customer
* @throws Exception
* @return array
*/
public function delete()
{
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) {
throw new Exception("You cannot access this resource", 405);
}
// parameter
$id = $this->getParam('id', true, 0);
$ea_optional = ($id <= 0 ? false : true);
$emailaddr = $this->getParam('emailaddr', $ea_optional, '');
$forwarderid = $this->getParam('forwarderid');
// validation
$result = $this->apiCall('Emails.get', array(
'id' => $id,
'emailaddr' => $emailaddr
));
$id = $result['id'];
$result['destination'] = explode(' ', $result['destination']);
if (isset($result['destination'][$forwarderid]) && $result['email'] != $result['destination'][$forwarderid]) {
// get needed customer info to reduce the email-forwarder-counter by one
$customer = $this->getCustomerData();
// unset it from array
unset($result['destination'][$forwarderid]);
// rebuild destination-string
$result['destination'] = implode(' ', $result['destination']);
// update in DB
$stmt = Database::prepare("
UPDATE `" . TABLE_MAIL_VIRTUAL . "` SET `destination` = :dest
WHERE `customerid`= :cid AND `id`= :id
");
$params = array(
"dest" => makeCorrectDestination($result['destination']),
"cid" => $customer['customerid'],
"id" => $id
);
Database::pexecute($stmt, $params, true, true);
// update customer usage
Customers::decreaseUsage($customer['customerid'], 'email_forwarders_used');
// update admin usage
Admins::decreaseUsage($customer['adminid'], 'email_forwarders_used');
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_INFO, "[API] deleted email forwarder for '" . $result['email_full'] . "'");
$result = $this->apiCall('Emails.get', array(
'emailaddr' => $result['email_full']
));
return $this->response(200, "successfull", $result);
}
throw new Exception("Unknown forwarder id", 404);
}
}

View File

@@ -1,385 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package API
* @since 0.10.0
*
*/
class Emails extends ApiCommand implements ResourceEntity
{
/**
* add a new email address
*
* @param string $email_part
* name of the address before @
* @param string $domain
* domain-name for the email-address
* @param boolean $iscatchall
* optional, make this address a catchall address, default: no
* @param int $customerid
* optional, admin-only, the customer-id
* @param string $loginname
* optional, admin-only, the loginname
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function add()
{
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) {
throw new Exception("You cannot access this resource", 405);
}
if ($this->getUserDetail('emails_used') < $this->getUserDetail('emails') || $this->getUserDetail('emails') == '-1') {
// required parameters
$email_part = $this->getParam('email_part');
$domain = $this->getParam('domain');
// parameters
$iscatchall = $this->getBoolParam('iscatchall', true, 0);
// validation
if (substr($domain, 0, 4) != 'xn--') {
$idna_convert = new idna_convert_wrapper();
$domain = $idna_convert->encode(validate($domain, 'domain', '', '', array(), true));
}
// check domain and whether it's an email-enabled domain
$domain_check = $this->apiCall('SubDomains.get', array(
'domainname' => $domain
));
if ($domain_check['isemaildomain'] == 0) {
standard_error('maindomainnonexist', $domain, true);
}
if (Settings::Get('catchall.catchall_enabled') != '1') {
$iscatchall = 0;
}
// check for catchall-flag
if ($iscatchall) {
$iscatchall = '1';
$email = '@' . $domain;
} else {
$iscatchall = '0';
$email = $email_part . '@' . $domain;
}
// full email value
$email_full = $email_part . '@' . $domain;
// validate it
if (! validateEmail($email_full)) {
standard_error('emailiswrong', $email_full, true);
}
// get needed customer info to reduce the email-address-counter by one
$customer = $this->getCustomerData('emails');
// duplicate check
$stmt = Database::prepare("
SELECT `id`, `email`, `email_full`, `iscatchall`, `destination`, `customerid` FROM `" . TABLE_MAIL_VIRTUAL . "`
WHERE (`email` = :email OR `email_full` = :emailfull )
AND `customerid`= :cid
");
$params = array(
"email" => $email,
"emailfull" => $email_full,
"cid" => $customer['customerid']
);
$email_check = Database::pexecute_first($stmt, $params, true, true);
if (strtolower($email_check['email_full']) == strtolower($email_full)) {
standard_error('emailexistalready', $email_full, true);
} elseif ($email_check['email'] == $email) {
standard_error('youhavealreadyacatchallforthisdomain', '', true);
}
$stmt = Database::prepare("
INSERT INTO `" . TABLE_MAIL_VIRTUAL . "` SET
`customerid` = :cid,
`email` = :email,
`email_full` = :email_full,
`iscatchall` = :iscatchall,
`domainid` = :domainid
");
$params = array(
"cid" => $customer['customerid'],
"email" => $email,
"email_full" => $email_full,
"iscatchall" => $iscatchall,
"domainid" => $domain_check['id']
);
Database::pexecute($stmt, $params, true, true);
// update customer usage
Customers::increaseUsage($customer['customerid'], 'emails_used');
// update admin usage
Admins::increaseUsage($customer['adminid'], 'emails_used');
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_INFO, "[API] added email address '" . $email_full . "'");
$result = $this->apiCall('Emails.get', array(
'emailaddr' => $email_full
));
return $this->response(200, "successfull", $result);
}
throw new Exception("No more resources available", 406);
}
/**
* return a email-address entry by either id or email-address
*
* @param int $id
* optional, the email-address-id
* @param string $emailaddr
* optional, the email-address
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function get()
{
$id = $this->getParam('id', true, 0);
$ea_optional = ($id <= 0 ? false : true);
$emailaddr = $this->getParam('emailaddr', $ea_optional, '');
$params = array();
$customer_ids = $this->getAllowedCustomerIds('email');
$params['idea'] = ($id <= 0 ? $emailaddr : $id);
$result_stmt = Database::prepare("SELECT v.`id`, v.`email`, v.`email_full`, v.`iscatchall`, v.`destination`, v.`customerid`, v.`popaccountid`, v.`domainid`, u.`quota`
FROM `" . TABLE_MAIL_VIRTUAL . "` v
LEFT JOIN `" . TABLE_MAIL_USERS . "` u ON v.`popaccountid` = u.`id`
WHERE v.`customerid` IN (" . implode(", ", $customer_ids) . ")
AND (v.`id`= :idea OR (v.`email` = :idea OR v.`email_full` = :idea))
");
$result = Database::pexecute_first($result_stmt, $params, true, true);
if ($result) {
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_NOTICE, "[API] get email address '" . $result['email_full'] . "'");
return $this->response(200, "successfull", $result);
}
$key = ($id > 0 ? "id #" . $id : "emailaddr '" . $emailaddr . "'");
throw new Exception("Email address with " . $key . " could not be found", 404);
}
/**
* toggle catchall flag of given email address either by id or email-address
*
* @param int $id
* optional, the email-address-id
* @param string $emailaddr
* optional, the email-address
* @param int $customerid
* optional, admin-only, the customer-id
* @param string $loginname
* optional, admin-only, the loginname
* @param boolean $iscatchall
* optional
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function update()
{
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) {
throw new Exception("You cannot access this resource", 405);
}
// if enabling catchall is not allowed by settings, we do not need
// to run update()
if (Settings::Get('catchall.catchall_enabled') != '1') {
standard_error(array(
'operationnotpermitted',
'featureisdisabled'
), 'catchall', true);
}
$id = $this->getParam('id', true, 0);
$ea_optional = ($id <= 0 ? false : true);
$emailaddr = $this->getParam('emailaddr', $ea_optional, '');
$result = $this->apiCall('Emails.get', array(
'id' => $id,
'emailaddr' => $emailaddr
));
$id = $result['id'];
// parameters
$iscatchall = $this->getBoolParam('iscatchall', true, $result['iscatchall']);
// get needed customer info to reduce the email-address-counter by one
$customer = $this->getCustomerData();
// check for catchall-flag
if ($iscatchall) {
$iscatchall = '1';
$email_parts = explode('@', $result['email_full']);
$email = '@' . $email_parts[1];
} else {
$iscatchall = '0';
$email = $result['email_full'];
}
$stmt = Database::prepare("
UPDATE `" . TABLE_MAIL_VIRTUAL . "`
SET `email` = :email , `iscatchall` = :caflag
WHERE `customerid`= :cid AND `id`= :id
");
$params = array(
"email" => $email,
"caflag" => $iscatchall,
"cid" => $customer['customerid'],
"id" => $id
);
Database::pexecute($stmt, $params, true, true);
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_INFO, "[API] toggled catchall-flag for email address '" . $result['email_full'] . "'");
$result = $this->apiCall('Emails.get', array(
'emailaddr' => $result['email_full']
));
return $this->response(200, "successfull", $result);
}
/**
* list all email addresses, if called from an admin, list all email addresses of all customers you are allowed to view, or specify id or loginname for one specific customer
*
* @param int $customerid
* optional, admin-only, select email addresses of a specific customer by id
* @param string $loginname
* optional, admin-only, select email addresses of a specific customer by loginname
*
* @access admin, customer
* @throws Exception
* @return array count|list
*/
public function listing()
{
$customer_ids = $this->getAllowedCustomerIds('email');
$result = array();
$result_stmt = Database::prepare("
SELECT m.`id`, m.`domainid`, m.`email`, m.`email_full`, m.`iscatchall`, u.`quota`, m.`destination`, m.`popaccountid`, d.`domain`, u.`mboxsize`
FROM `" . TABLE_MAIL_VIRTUAL . "` m
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON (m.`domainid` = d.`id`)
LEFT JOIN `" . TABLE_MAIL_USERS . "` u ON (m.`popaccountid` = u.`id`)
WHERE m.`customerid` IN (" . implode(", ", $customer_ids) . ")
");
Database::pexecute($result_stmt, null, true, true);
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
$result[] = $row;
}
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_NOTICE, "[API] list email-addresses");
return $this->response(200, "successfull", array(
'count' => count($result),
'list' => $result
));
}
/**
* delete an email address by either id or username
*
* @param int $id
* optional, the email-address-id
* @param string $emailaddr
* optional, the email-address
* @param int $customerid
* optional, admin-only, the customer-id
* @param string $loginname
* optional, admin-only, the loginname
* @param boolean $delete_userfiles
* optional, delete email data from filesystem, default: 0 (false)
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function delete()
{
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) {
throw new Exception("You cannot access this resource", 405);
}
$id = $this->getParam('id', true, 0);
$ea_optional = ($id <= 0 ? false : true);
$emailaddr = $this->getParam('emailaddr', $ea_optional, '');
$result = $this->apiCall('Emails.get', array(
'id' => $id,
'emailaddr' => $emailaddr
));
$id = $result['id'];
// parameters
$delete_userfiles = $this->getBoolParam('delete_userfiles', true, 0);
// get needed customer info to reduce the email-address-counter by one
$customer = $this->getCustomerData();
// check for forwarders
$number_forwarders = 0;
if ($result['destination'] != '') {
$result['destination'] = explode(' ', $result['destination']);
$number_forwarders = count($result['destination']);
}
// check whether this address is an account
if ($result['popaccountid'] != 0) {
// Free the Quota used by the email account
if (Settings::Get('system.mail_quota_enabled') == 1) {
$stmt = Database::prepare("SELECT `quota` FROM `" . TABLE_MAIL_USERS . "` WHERE `customerid`= :customerid AND `id`= :id");
$res_quota = Database::pexecute_first($stmt, array(
"customerid" => $customer['customerid'],
"id" => $result['popaccountid']
), true, true);
Customers::decreaseUsage($customer['customerid'], 'email_quota_used', '', $res_quota['quota']);
Admins::decreaseUsage($customer['customerid'], 'email_quota_used', '', $res_quota['quota']);
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_INFO, "[API] deleted quota entries for email address '" . $result['email_full'] . "'");
}
// delete account
$stmt = Database::prepare("DELETE FROM `" . TABLE_MAIL_USERS . "` WHERE `customerid`= :customerid AND `id`= :id");
Database::pexecute($stmt, array(
"customerid" => $customer['customerid'],
"id" => $result['popaccountid']
), true, true);
Customers::decreaseUsage($customer['customerid'], 'email_accounts_used');
Admins::decreaseUsage($customer['customerid'], 'email_accounts_used');
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_INFO, "[API] deleted email account '" . $result['email_full'] . "'");
$number_forwarders --;
}
// decrease forwarder counter
Customers::decreaseUsage($customer['customerid'], 'email_forwarders_used', '', $number_forwarders);
Admins::decreaseUsage($customer['customerid'], 'email_forwarders_used', '', $number_forwarders);
if ($delete_userfiles) {
inserttask('7', $customer['loginname'], $result['email_full']);
}
// delete address
$stmt = Database::prepare("DELETE FROM `" . TABLE_MAIL_VIRTUAL . "` WHERE `customerid`= :customerid AND `id`= :id");
Database::pexecute($stmt, array(
"customerid" => $customer['customerid'],
"id" => $id
), true, true);
Customers::decreaseUsage($customer['customerid'], 'emails_used');
Admins::decreaseUsage($customer['customerid'], 'emails_used');
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_INFO, "[API] deleted email address '" . $result['email_full'] . "'");
return $this->response(200, "successfull", $result);
}
}

View File

@@ -1,369 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package API
* @since 0.10.0
*
*/
class FpmDaemons extends ApiCommand implements ResourceEntity
{
/**
* lists all fpm-daemon entries
*
* @access admin
* @throws Exception
* @return array count|list
*/
public function listing()
{
if ($this->isAdmin()) {
$this->logger()->logAction(ADM_ACTION, LOG_NOTICE, "[API] list fpm-daemons");
$result = Database::query("
SELECT * FROM `" . TABLE_PANEL_FPMDAEMONS . "` ORDER BY `description` ASC
");
$fpmdaemons = array();
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
$query_params = array(
'id' => $row['id']
);
$query = "SELECT * FROM `" . TABLE_PANEL_PHPCONFIGS . "` WHERE `fpmsettingid` = :id";
$configresult_stmt = Database::prepare($query);
Database::pexecute($configresult_stmt, $query_params, true, true);
$configs = array();
if (Database::num_rows() > 0) {
while ($row2 = $configresult_stmt->fetch(PDO::FETCH_ASSOC)) {
$configs[] = $row2['description'];
}
}
if (empty($configs)) {
$configs[] = $this->lng['admin']['phpsettings']['notused'];
}
$row['configs'] = $configs;
$fpmdaemons[] = $row;
}
return $this->response(200, "successfull", array(
'count' => count($fpmdaemons),
'list' => $fpmdaemons
));
}
throw new Exception("Not allowed to execute given command.", 403);
}
/**
* return a fpm-daemon entry by id
*
* @param int $id
* fpm-daemon-id
*
* @access admin
* @throws Exception
* @return array
*/
public function get()
{
if ($this->isAdmin()) {
$id = $this->getParam('id');
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_FPMDAEMONS . "` WHERE `id` = :id
");
$result = Database::pexecute_first($result_stmt, array(
'id' => $id
), true, true);
if ($result) {
return $this->response(200, "successfull", $result);
}
throw new Exception("fpm-daemon with id #" . $id . " could not be found", 404);
}
throw new Exception("Not allowed to execute given command.", 403);
}
/**
* create a new fpm-daemon entry
*
* @param string $description
* @param string $reload_cmd
* @param string $config_dir
* @param string $pm
* optional, process-manager, one of 'static', 'dynamic' or 'ondemand', default 'static'
* @param int $max_children
* optional, default 0
* @param int $start_servers
* optional, default 0
* @param int $min_spare_servers
* optional, default 0
* @param int $max_spare_servers
* optional, default 0
* @param int $max_requests
* optional, default 0
* @param int $idle_timeout
* optional, default 0
* @param string $limit_extensions
* optional, limit execution to the following extensions, default '.php'
*
* @access admin
* @throws Exception
* @return array
*/
public function add()
{
if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) {
// required parameter
$description = $this->getParam('description');
$reload_cmd = $this->getParam('reload_cmd');
$config_dir = $this->getParam('config_dir');
// parameters
$pmanager = $this->getParam('pm', true, 'static');
$max_children = $this->getParam('max_children', true, 0);
$start_servers = $this->getParam('start_servers', true, 0);
$min_spare_servers = $this->getParam('min_spare_servers', true, 0);
$max_spare_servers = $this->getParam('max_spare_servers', true, 0);
$max_requests = $this->getParam('max_requests', true, 0);
$idle_timeout = $this->getParam('idle_timeout', true, 0);
$limit_extensions = $this->getParam('limit_extensions', true, '.php');
// validation
$description = validate($description, 'description', '', '', array(), true);
$reload_cmd = validate($reload_cmd, 'reload_cmd', '', '', array(), true);
$config_dir = validate($config_dir, 'config_dir', '', '', array(), true);
if (! in_array($pmanager, array(
'static',
'dynamic',
'ondemand'
))) {
throw new ErrorException("Unknown process manager", 406);
}
if (empty($limit_extensions)) {
$limit_extensions = '.php';
}
$limit_extensions = validate($limit_extensions, 'limit_extensions', '/^(\.[a-z]([a-z0-9]+)\ ?)+$/', '', array(), true);
if (strlen($description) == 0 || strlen($description) > 50) {
standard_error('descriptioninvalid', '', true);
}
$ins_stmt = Database::prepare("
INSERT INTO `" . TABLE_PANEL_FPMDAEMONS . "` SET
`description` = :desc,
`reload_cmd` = :reload_cmd,
`config_dir` = :config_dir,
`pm` = :pm,
`max_children` = :max_children,
`start_servers` = :start_servers,
`min_spare_servers` = :min_spare_servers,
`max_spare_servers` = :max_spare_servers,
`max_requests` = :max_requests,
`idle_timeout` = :idle_timeout,
`limit_extensions` = :limit_extensions
");
$ins_data = array(
'desc' => $description,
'reload_cmd' => $reload_cmd,
'config_dir' => makeCorrectDir($config_dir),
'pm' => $pmanager,
'max_children' => $max_children,
'start_servers' => $start_servers,
'min_spare_servers' => $min_spare_servers,
'max_spare_servers' => $max_spare_servers,
'max_requests' => $max_requests,
'idle_timeout' => $idle_timeout,
'limit_extensions' => $limit_extensions
);
Database::pexecute($ins_stmt, $ins_data);
$id = Database::lastInsertId();
inserttask('1');
$this->logger()->logAction(ADM_ACTION, LOG_INFO, "[API] fpm-daemon with description '" . $description . "' has been created by '" . $this->getUserDetail('loginname') . "'");
$result = $this->apiCall('FpmDaemons.get', array(
'id' => $id
));
return $this->response(200, "successfull", $result);
}
throw new Exception("Not allowed to execute given command.", 403);
}
/**
* update a fpm-daemon entry by given id
*
* @param int $id
* fpm-daemon id
* @param string $description
* optional
* @param string $reload_cmd
* optional
* @param string $config_dir
* optional
* @param string $pm
* optional, process-manager, one of 'static', 'dynamic' or 'ondemand', default 'static'
* @param int $max_children
* optional, default 0
* @param int $start_servers
* optional, default 0
* @param int $min_spare_servers
* optional, default 0
* @param int $max_spare_servers
* optional, default 0
* @param int $max_requests
* optional, default 0
* @param int $idle_timeout
* optional, default 0
* @param string $limit_extensions
* optional, limit execution to the following extensions, default '.php'
*
* @access admin
* @throws Exception
* @return array
*/
public function update()
{
if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) {
// required parameter
$id = $this->getParam('id');
$result = $this->apiCall('FpmDaemons.get', array(
'id' => $id
));
// parameters
$description = $this->getParam('description', true, $result['description']);
$reload_cmd = $this->getParam('reload_cmd', true, $result['reload_cmd']);
$config_dir = $this->getParam('config_dir', true, $result['config_dir']);
$pmanager = $this->getParam('pm', true, $result['pm']);
$max_children = $this->getParam('max_children', true, $result['max_children']);
$start_servers = $this->getParam('start_servers', true, $result['start_servers']);
$min_spare_servers = $this->getParam('min_spare_servers', true, $result['min_spare_servers']);
$max_spare_servers = $this->getParam('max_spare_servers', true, $result['max_spare_servers']);
$max_requests = $this->getParam('max_requests', true, $result['max_requests']);
$idle_timeout = $this->getParam('idle_timeout', true, $result['idle_timeout']);
$limit_extensions = $this->getParam('limit_extensions', true, $result['limit_extensions']);
// validation
$description = validate($description, 'description', '', '', array(), true);
$reload_cmd = validate($reload_cmd, 'reload_cmd', '', '', array(), true);
$config_dir = validate($config_dir, 'config_dir', '', '', array(), true);
if (! in_array($pmanager, array(
'static',
'dynamic',
'ondemand'
))) {
throw new ErrorException("Unknown process manager", 406);
}
if (empty($limit_extensions)) {
$limit_extensions = '.php';
}
$limit_extensions = validate($limit_extensions, 'limit_extensions', '/^(\.[a-z]([a-z0-9]+)\ ?)+$/', '', array(), true);
if (strlen($description) == 0 || strlen($description) > 50) {
standard_error('descriptioninvalid', '', true);
}
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_FPMDAEMONS . "` SET
`description` = :desc,
`reload_cmd` = :reload_cmd,
`config_dir` = :config_dir,
`pm` = :pm,
`max_children` = :max_children,
`start_servers` = :start_servers,
`min_spare_servers` = :min_spare_servers,
`max_spare_servers` = :max_spare_servers,
`max_requests` = :max_requests,
`idle_timeout` = :idle_timeout,
`limit_extensions` = :limit_extensions
WHERE `id` = :id
");
$upd_data = array(
'desc' => $description,
'reload_cmd' => $reload_cmd,
'config_dir' => makeCorrectDir($config_dir),
'pm' => $pmanager,
'max_children' => $max_children,
'start_servers' => $start_servers,
'min_spare_servers' => $min_spare_servers,
'max_spare_servers' => $max_spare_servers,
'max_requests' => $max_requests,
'idle_timeout' => $idle_timeout,
'limit_extensions' => $limit_extensions,
'id' => $id
);
Database::pexecute($upd_stmt, $upd_data, true, true);
inserttask('1');
$this->logger()->logAction(ADM_ACTION, LOG_INFO, "[API] fpm-daemon with description '" . $description . "' has been updated by '" . $this->getUserDetail('loginname') . "'");
$result = $this->apiCall('FpmDaemons.get', array(
'id' => $id
));
return $this->response(200, "successfull", $result);
}
throw new Exception("Not allowed to execute given command.", 403);
}
/**
* delete a fpm-daemon entry by id
*
* @param int $id
* fpm-daemon-id
*
* @access admin
* @throws Exception
* @return array
*/
public function delete()
{
if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) {
$id = $this->getParam('id');
if ($id == 1) {
standard_error('cannotdeletedefaultphpconfig', '', true);
}
$result = $this->apiCall('FpmDaemons.get', array(
'id' => $id
));
// set default fpm daemon config for all php-config that use this config that is to be deleted
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_PHPCONFIGS . "` SET
`fpmsettingid` = '1' WHERE `fpmsettingid` = :id
");
Database::pexecute($upd_stmt, array(
'id' => $id
), true, true);
$del_stmt = Database::prepare("
DELETE FROM `" . TABLE_PANEL_FPMDAEMONS . "` WHERE `id` = :id
");
Database::pexecute($del_stmt, array(
'id' => $id
), true, true);
inserttask('1');
$this->logger()->logAction(ADM_ACTION, LOG_INFO, "[API] fpm-daemon setting '" . $result['description'] . "' has been deleted by '" . $this->getUserDetail('loginname') . "'");
return $this->response(200, "successfull", $result);
}
throw new Exception("Not allowed to execute given command.", 403);
}
}

View File

@@ -1,428 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package API
* @since 0.10.0
*
*/
class Froxlor extends ApiCommand
{
/**
* checks whether there is a newer version of froxlor available
*
* @access admin
* @throws Exception
* @return string
*/
public function checkUpdate()
{
define('UPDATE_URI', "https://version.froxlor.org/Froxlor/api/" . $this->version);
if ($this->isAdmin() && $this->getUserDetail('change_serversettings')) {
if (function_exists('curl_version')) {
// log our actions
$this->logger()->logAction(ADM_ACTION, LOG_NOTICE, "[API] checking for updates");
// check for new version
$latestversion = HttpClient::urlGet(UPDATE_URI);
$latestversion = explode('|', $latestversion);
if (is_array($latestversion) && count($latestversion) >= 1) {
$_version = $latestversion[0];
$_message = isset($latestversion[1]) ? $latestversion[1] : '';
$_link = isset($latestversion[2]) ? $latestversion[2] : '';
// add the branding so debian guys are not gettings confused
// about their version-number
$version_label = $_version . $this->branding;
$version_link = $_link;
$message_addinfo = $_message;
// not numeric -> error-message
if (! preg_match('/^((\d+\\.)(\d+\\.)(\d+\\.)?(\d+)?(\-(svn|dev|rc)(\d+))?)$/', $_version)) {
// check for customized version to not output
// "There is a newer version of froxlor" besides the error-message
$isnewerversion = - 1;
} elseif (version_compare2($this->version, $_version) == - 1) {
// there is a newer version - yay
$isnewerversion = 1;
} else {
// nothing new
$isnewerversion = 0;
}
// anzeige über version-status mit ggfls. formular
// zum update schritt #1 -> download
if ($isnewerversion == 1) {
$text = 'There is a newer version available: "' . $_version . '" (Your current version is: ' . $this->version . ')';
return $this->response(200, "successfull", array(
'isnewerversion' => $isnewerversion,
'version' => $_version,
'message' => $text,
'link' => $version_link,
'additional_info' => $message_addinfo
));
} elseif ($isnewerversion == 0) {
// all good
return $this->response(200, "successfull", array(
'isnewerversion' => $isnewerversion,
'version' => $version_label,
'message' => "",
'link' => $version_link,
'additional_info' => $message_addinfo
));
} else {
standard_error('customized_version', '', true);
}
}
}
return $this->response(300, "successfull", array(
'isnewerversion' => 0,
'version' => $this->version.$this->branding,
'message' => 'Version-check not available due to missing php-curl extension',
'link' => UPDATE_URI.'/pretty',
'additional_info' => ""
));
}
throw new Exception("Not allowed to execute given command.", 403);
}
/**
* import settings
*
* @param string $json_str
* content of exported froxlor-settings json file
*
* @access admin
* @throws Exception
* @return bool
*/
public function importSettings()
{
if ($this->isAdmin() && $this->getUserDetail('change_serversettings')) {
$json_str = $this->getParam('json_str');
$this->logger()->logAction(ADM_ACTION, LOG_NOTICE, "User " . $this->getUserDetail('loginname') . " imported settings");
try {
SImExporter::import($json_str);
inserttask('1');
inserttask('10');
// Using nameserver, insert a task which rebuilds the server config
inserttask('4');
// cron.d file
inserttask('99');
return $this->response(200, "successfull", true);
} catch (Exception $e) {
throw new Exception($e->getMessage(), 406);
}
}
throw new Exception("Not allowed to execute given command.", 403);
}
/**
* export settings
*
* @access admin
* @throws Exception
* @return string json-string
*/
public function exportSettings()
{
if ($this->isAdmin() && $this->getUserDetail('change_serversettings')) {
$this->logger()->logAction(ADM_ACTION, LOG_NOTICE, "User " . $this->getUserDetail('loginname') . " exported settings");
$json_export = SImExporter::export();
return $this->response(200, "successfull", $json_export);
}
throw new Exception("Not allowed to execute given command.", 403);
}
/**
* return a list of all settings
*
* @access admin
* @throws Exception
* @return array count|list
*/
public function listSettings()
{
if ($this->isAdmin() && $this->getUserDetail('change_serversettings')) {
$sel_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_SETTINGS . "` ORDER BY settinggroup ASC, varname ASC
");
Database::pexecute($sel_stmt, null, true, true);
$result = array();
while ($row = $sel_stmt->fetch(PDO::FETCH_ASSOC)) {
$result[] = array(
'key' => $row['settinggroup'] . '.' . $row['varname'],
'value' => $row['value']
);
}
return $this->response(200, "successfull", array(
'count' => count($result),
'list' => $result
));
}
throw new Exception("Not allowed to execute given command.", 403);
}
/**
* return a setting by settinggroup.varname couple
*
* @param string $key
* settinggroup.varname couple
*
* @access admin
* @throws Exception
* @return string
*/
public function getSetting()
{
if ($this->isAdmin() && $this->getUserDetail('change_serversettings')) {
$setting = $this->getParam('key');
return $this->response(200, "successfull", Settings::Get($setting));
}
throw new Exception("Not allowed to execute given command.", 403);
}
/**
* updates a setting
*
* @param string $key
* settinggroup.varname couple
* @param string $value
* optional the new value, default is ''
*
* @access admin
* @throws Exception
* @return string
*/
public function updateSetting()
{
// currently not implemented as it required validation too so no wrong settings are being stored via API
throw new Exception("Not available yet.", 501);
if ($this->isAdmin() && $this->getUserDetail('change_serversettings')) {
$setting = $this->getParam('key');
$value = $this->getParam('value', true, '');
$oldvalue = Settings::Get($setting);
if (is_null($oldvalue)) {
throw new Exception("Setting '" . $setting . "' could not be found");
}
$this->logger()->logAction(ADM_ACTION, LOG_WARNING, "[API] Changing setting '" . $setting . "' from '" . $oldvalue . "' to '" . $value . "'");
return $this->response(200, "successfull", Settings::Set($setting, $value, true));
}
throw new Exception("Not allowed to execute given command.", 403);
}
/**
* returns a list of all available api functions
*
* @param string $module
* optional, return list of functions for a specific module
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function listFunctions()
{
$module = $this->getParam('module', true, '');
$functions = array();
if ($module != null) {
// check existence
$this->requireModules($module);
// now get all static functions
$reflection = new \ReflectionClass($module);
$_functions = $reflection->getMethods(\ReflectionMethod::IS_PUBLIC);
foreach ($_functions as $func) {
if ($func->class == $module && $func->isPublic()) {
array_push($functions, array_merge(array(
'module' => $module,
'function' => $func->name
), $this->getParamListFromDoc($module, $func->name)));
}
}
} else {
// check all the modules
$path = FROXLOR_INSTALL_DIR . '/lib/classes/api/commands/';
// valid directory?
if (is_dir($path)) {
// create RecursiveIteratorIterator
$its = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path));
// check every file
foreach ($its as $it) {
// does it match the Filename pattern?
$matches = array();
if (preg_match("/^class\.(.+)\.php$/i", $it->getFilename(), $matches)) {
// check for existence
try {
// set the module to be in our namespace
$mod = $matches[1];
$this->requireModules($mod);
} catch (Exception $e) {
// @todo log?
continue;
}
// now get all static functions
$reflection = new \ReflectionClass($mod);
$_functions = $reflection->getMethods(\ReflectionMethod::IS_PUBLIC);
foreach ($_functions as $func) {
if ($func->class == $mod && $func->isPublic() && ! $func->isStatic()) {
array_push($functions, array_merge(array(
'module' => $matches[1],
'function' => $func->name
), $this->getParamListFromDoc($matches[1], $func->name)));
}
}
}
}
} else {
// yikes - no valid directory to check
throw new Exception("Cannot search directory '" . $path . "'. No such directory.", 500);
}
}
// return the list
return $this->response(200, "successfull", $functions);
}
/**
* generate an api-response to list all parameters and the return-value of
* a given module.function-combination
*
* @param string $module
* @param string $function
*
* @throws Exception
* @return array|bool
*/
private function getParamListFromDoc($module = null, $function = null)
{
try {
// set the module
$cls = new \ReflectionMethod($module, $function);
$comment = $cls->getDocComment();
if ($comment == false) {
return array(
'head' => 'There is no comment-block for "' . $module . '.' . $function . '"'
);
}
$clines = explode("\n", $comment);
$result = array();
$result['params'] = array();
$param_desc = false;
$r = array();
foreach ($clines as $c) {
$c = trim($c);
// check param-section
if (strpos($c, '@param')) {
preg_match('/^\*\s\@param\s(.+)\s(\$\w+)(\s.*)?/', $c, $r);
// cut $ off the parameter-name as it is not wanted in the api-request
$result['params'][] = array(
'parameter' => substr($r[2], 1),
'type' => $r[1],
'desc' => (isset($r[3]) ? trim($r['3']) : '')
);
$param_desc = true;
} // check access-section
elseif (strpos($c, '@access')) {
preg_match('/^\*\s\@access\s(.*)/', $c, $r);
if (! isset($r[0]) || empty($r[0])) {
$r[1] = 'This function has no restrictions';
}
$result['access'] = array(
'groups' => (isset($r[1]) ? trim($r[1]) : '')
);
} // check return-section
elseif (strpos($c, '@return')) {
preg_match('/^\*\s\@return\s(\w+)(\s.*)?/', $c, $r);
if (! isset($r[0]) || empty($r[0])) {
$r[1] = 'null';
$r[2] = 'This function has no return value given';
}
$result['return'] = array(
'type' => $r[1],
'desc' => (isset($r[2]) ? trim($r[2]) : '')
);
} // check throws-section
elseif (! empty($c) && strpos($c, '@throws') === false) {
if (substr($c, 0, 3) == "/**") {
continue;
}
if (substr($c, 0, 2) == "*/") {
continue;
}
if (substr($c, 0, 1) == "*") {
$c = trim(substr($c, 1));
if (empty($c)) {
continue;
}
if ($param_desc) {
$result['params'][count($result['params']) - 1]['desc'] .= $c;
} else {
if (! isset($result['head']) || empty($result['head'])) {
$result['head'] = $c . " ";
} else {
$result['head'] .= $c . " ";
}
}
}
}
}
$result['head'] = trim($result['head']);
return $result;
} catch (\ReflectionException $e) {
return array();
}
}
/**
* this functions is used to check the availability
* of a given list of modules.
* If either one of
* them are not found, throw an Exception
*
* @param string|array $modules
*
* @throws Exception
*/
private function requireModules($modules = null)
{
if ($modules != null) {
// no array -> create one
if (! is_array($modules)) {
$modules = array(
$modules
);
}
// check all the modules
foreach ($modules as $module) {
try {
// can we use the class?
if (class_exists($module)) {
continue;
} else {
throw new Exception('The required class "' . $module . '" could not be found but the module-file exists', 404);
}
} catch (Exception $e) {
// The autoloader will throw an Exception
// that the required class could not be found
// but we want a nicer error-message for this here
throw new Exception('The required module "' . $module . '" could not be found', 404);
}
}
}
}
}

View File

@@ -1,550 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package API
* @since 0.10.0
*
*/
class Ftps extends ApiCommand implements ResourceEntity
{
/**
* add a new ftp-user
*
* @param string $ftp_password
* password for the created database and database-user
* @param string $path
* destination path relative to the customers-homedir
* @param string $ftp_description
* optional, description for ftp-user
* @param bool $sendinfomail
* optional, send created resource-information to customer, default: false
* @param string $shell
* optional, default /bin/false (not changeable when deactivated)
* @param string $ftp_username
* optional if customer.ftpatdomain is allowed, specify an username
* @param string $ftp_domain
* optional if customer.ftpatdomain is allowed, specify a domain (customer must be owner)
* @param int $customerid
* required when called as admin, not needed when called as customer
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function add()
{
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'ftp')) {
throw new Exception("You cannot access this resource", 405);
}
if ($this->getUserDetail('ftps_used') < $this->getUserDetail('ftps') || $this->getUserDetail('ftps') == '-1') {
// required paramters
$path = $this->getParam('path');
$password = $this->getParam('ftp_password');
// parameters
$description = $this->getParam('ftp_description', true, '');
$sendinfomail = $this->getBoolParam('sendinfomail', true, 0);
$shell = $this->getParam('shell', true, '/bin/false');
$ftpusername = $this->getParam('ftp_username', true, '');
$ftpdomain = $this->getParam('ftp_domain', true, '');
// validation
$password = validate($password, 'password', '', '', array(), true);
$password = validatePassword($password, true);
$description = validate(trim($description), 'description', '', '', array(), true);
if (Settings::Get('system.allow_customer_shell') == '1') {
$shell = validate(trim($shell), 'shell', '', '', array(), true);
} else {
$shell = "/bin/false";
}
if (Settings::Get('customer.ftpatdomain') == '1') {
$ftpusername = validate(trim($ftpusername), 'username', '/^[a-zA-Z0-9][a-zA-Z0-9\-_]+\$?$/', '', array(), true);
if (substr($ftpdomain, 0, 4) != 'xn--') {
$idna_convert = new idna_convert_wrapper();
$ftpdomain = $idna_convert->encode(validate($ftpdomain, 'domain', '', '', array(), true));
}
}
$params = array();
// get needed customer info to reduce the ftp-user-counter by one
$customer = $this->getCustomerData('ftps');
if ($sendinfomail != 1) {
$sendinfomail = 0;
}
if (Settings::Get('customer.ftpatdomain') == '1') {
if ($ftpusername == '') {
standard_error(array(
'stringisempty',
'username'
), '', true);
}
$ftpdomain_check_stmt = Database::prepare("SELECT `id`, `domain`, `customerid` FROM `" . TABLE_PANEL_DOMAINS . "`
WHERE `domain` = :domain
AND `customerid` = :customerid");
$ftpdomain_check = Database::pexecute_first($ftpdomain_check_stmt, array(
"domain" => $ftpdomain,
"customerid" => $customer['customerid']
), true, true);
if ($ftpdomain_check && $ftpdomain_check['domain'] != $ftpdomain) {
standard_error('maindomainnonexist', $ftpdomain, true);
}
$username = $ftpusername . "@" . $ftpdomain;
} else {
$username = $customer['loginname'] . Settings::Get('customer.ftpprefix') . (intval($customer['ftp_lastaccountnumber']) + 1);
}
$username_check_stmt = Database::prepare("
SELECT * FROM `" . TABLE_FTP_USERS . "` WHERE `username` = :username
");
$username_check = Database::pexecute_first($username_check_stmt, array(
"username" => $username
), true, true);
if (! empty($username_check) && $username_check['username'] = $username) {
standard_error('usernamealreadyexists', $username, true);
} elseif ($username == $password) {
standard_error('passwordshouldnotbeusername', '', true);
} else {
$path = makeCorrectDir($customer['documentroot'] . '/' . $path);
$cryptPassword = makeCryptPassword($password);
$stmt = Database::prepare("INSERT INTO `" . TABLE_FTP_USERS . "`
(`customerid`, `username`, `description`, `password`, `homedir`, `login_enabled`, `uid`, `gid`, `shell`)
VALUES (:customerid, :username, :description, :password, :homedir, 'y', :guid, :guid, :shell)");
$params = array(
"customerid" => $customer['customerid'],
"username" => $username,
"description" => $description,
"password" => $cryptPassword,
"homedir" => $path,
"guid" => $customer['guid'],
"shell" => $shell
);
Database::pexecute($stmt, $params, true, true);
$result_stmt = Database::prepare("
SELECT `bytes_in_used` FROM `" . TABLE_FTP_QUOTATALLIES . "` WHERE `name` = :name
");
Database::pexecute($result_stmt, array(
"name" => $customer['loginname']
), true, true);
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
$stmt = Database::prepare("INSERT INTO `" . TABLE_FTP_QUOTATALLIES . "`
(`name`, `quota_type`, `bytes_in_used`, `bytes_out_used`, `bytes_xfer_used`, `files_in_used`, `files_out_used`, `files_xfer_used`)
VALUES (:name, 'user', :bytes_in_used, '0', '0', '0', '0', '0')
");
Database::pexecute($stmt, array(
"name" => $username,
"bytes_in_used" => $row['bytes_in_used']
), true, true);
}
$stmt = Database::prepare("
UPDATE `" . TABLE_FTP_GROUPS . "`
SET `members` = CONCAT_WS(',',`members`, :username)
WHERE `customerid`= :customerid AND `gid`= :guid
");
$params = array(
"username" => $username,
"customerid" => $customer['customerid'],
"guid" => $customer['guid']
);
Database::pexecute($stmt, $params, true, true);
// update customer usage
Customers::increaseUsage($customer['customerid'], 'ftps_used');
Customers::increaseUsage($customer['customerid'], 'ftp_lastaccountnumber');
// update admin usage
Admins::increaseUsage($customer['adminid'], 'ftps_used');
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_INFO, "[API] added ftp-account '" . $username . " (" . $path . ")'");
inserttask(5);
if ($sendinfomail == 1) {
$replace_arr = array(
'SALUTATION' => getCorrectUserSalutation($customer),
'CUST_NAME' => getCorrectUserSalutation($customer), // < keep this for compatibility
'USR_NAME' => $username,
'USR_PASS' => $password,
'USR_PATH' => makeCorrectDir(str_replace($customer['documentroot'], "/", $path))
);
// get template for mail subject
$mail_subject = $this->getMailTemplate($customer, 'mails', 'new_ftpaccount_by_customer_subject', $replace_arr, $this->lng['mails']['new_ftpaccount_by_customer']['subject']);
// get template for mail body
$mail_body = $this->getMailTemplate($customer, 'mails', 'new_ftpaccount_by_customer_mailbody', $replace_arr, $this->lng['mails']['new_ftpaccount_by_customer']['mailbody']);
$_mailerror = false;
$mailerr_msg = "";
try {
$this->mailer()->Subject = $mail_subject;
$this->mailer()->AltBody = $mail_body;
$this->mailer()->msgHTML(str_replace("\n", "<br />", $mail_body));
$this->mailer()->addAddress($customer['email'], getCorrectUserSalutation($customer));
$this->mailer()->send();
} catch (phpmailerException $e) {
$mailerr_msg = $e->errorMessage();
$_mailerror = true;
} catch (Exception $e) {
$mailerr_msg = $e->getMessage();
$_mailerror = true;
}
if ($_mailerror) {
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_ERR, "[API] Error sending mail: " . $mailerr_msg);
standard_error('errorsendingmail', $customer['email'], true);
}
$this->mailer()->clearAddresses();
}
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_WARNING, "[API] added ftp-user '" . $username . "'");
$result = $this->apiCall('Ftps.get', array(
'username' => $username
));
return $this->response(200, "successfull", $result);
}
}
throw new Exception("No more resources available", 406);
}
/**
* return a ftp-user entry by either id or username
*
* @param int $id
* optional, the customer-id
* @param string $username
* optional, the username
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function get()
{
$id = $this->getParam('id', true, 0);
$un_optional = ($id <= 0 ? false : true);
$username = $this->getParam('username', $un_optional, '');
$params = array();
if ($this->isAdmin()) {
if ($this->getUserDetail('customers_see_all') == false) {
// if it's a reseller or an admin who cannot see all customers, we need to check
// whether the database belongs to one of his customers
$_custom_list_result = $this->apiCall('Customers.listing');
$custom_list_result = $_custom_list_result['list'];
$customer_ids = array();
foreach ($custom_list_result as $customer) {
$customer_ids[] = $customer['customerid'];
}
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_FTP_USERS . "`
WHERE `customerid` IN (".implode(", ", $customer_ids).")
AND (`id` = :idun OR `username` = :idun)
");
} else {
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_FTP_USERS . "`
WHERE (`id` = :idun OR `username` = :idun)
");
}
} else {
if (Settings::IsInList('panel.customer_hide_options', 'ftp')) {
throw new Exception("You cannot access this resource", 405);
}
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_FTP_USERS . "`
WHERE `customerid` = :customerid
AND (`id` = :idun OR `username` = :idun)
");
$params['customerid'] = $this->getUserDetail('customerid');
}
$params['idun'] = ($id <= 0 ? $username : $id);
$result = Database::pexecute_first($result_stmt, $params, true, true);
if ($result) {
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_NOTICE, "[API] get ftp-user '" . $result['username'] . "'");
return $this->response(200, "successfull", $result);
}
$key = ($id > 0 ? "id #" . $id : "username '" . $username . "'");
throw new Exception("FTP user with " . $key . " could not be found", 404);
}
/**
* update a given ftp-user by id or username
*
* @param int $id
* optional, the customer-id
* @param string $username
* optional, the username
* @param string $ftp_password
* password for the created database and database-user
* @param string $path
* destination path relative to the customers-homedir
* @param string $ftp_description
* optional, description for ftp-user
* @param string $shell
* optional, default /bin/false (not changeable when deactivated)
* @param int $customerid
* required when called as admin, not needed when called as customer
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function update()
{
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'ftp')) {
throw new Exception("You cannot access this resource", 405);
}
$id = $this->getParam('id', true, 0);
$un_optional = ($id <= 0 ? false : true);
$username = $this->getParam('username', $un_optional, '');
$result = $this->apiCall('Ftps.get', array(
'id' => $id,
'username' => $username
));
$id = $result['id'];
// parameters
$path = $this->getParam('path', true, '');
$password = $this->getParam('ftp_password', true, '');
$description = $this->getParam('ftp_description', true, $result['description']);
$shell = $this->getParam('shell', true, $result['shell']);
// validation
$password = validate($password, 'password', '', '', array(), true);
$description = validate(trim($description), 'description', '', '', array(), true);
if (Settings::Get('system.allow_customer_shell') == '1') {
$shell = validate(trim($shell), 'shell', '', '', array(), true);
} else {
$shell = "/bin/false";
}
// get needed customer info to reduce the ftp-user-counter by one
$customer = $this->getCustomerData();
// password update?
if ($password != '') {
// validate password
$password = validatePassword($password, true);
if ($password == $result['username']) {
standard_error('passwordshouldnotbeusername', '', true);
}
$cryptPassword = makeCryptPassword($password);
$stmt = Database::prepare("UPDATE `" . TABLE_FTP_USERS . "`
SET `password` = :password
WHERE `customerid` = :customerid
AND `id` = :id
");
Database::pexecute($stmt, array(
"customerid" => $customer['customerid'],
"id" => $id,
"password" => $cryptPassword
), true, true);
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_INFO, "[API] updated ftp-account password for '" . $result['username'] . "'");
}
// path update?
if ($path != '') {
$path = makeCorrectDir($customer['documentroot'] . '/' . $path);
if ($path != $result['homedir']) {
$stmt = Database::prepare("UPDATE `" . TABLE_FTP_USERS . "`
SET `homedir` = :homedir
WHERE `customerid` = :customerid
AND `id` = :id
");
Database::pexecute($stmt, array(
"homedir" => $path,
"customerid" => $customer['customerid'],
"id" => $id
), true, true);
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_INFO, "[API] updated ftp-account homdir for '" . $result['username'] . "'");
}
}
// it's the task for "new ftp" but that will
// create all directories and correct their permissions
inserttask(5);
$stmt = Database::prepare("
UPDATE `" . TABLE_FTP_USERS . "`
SET `description` = :desc, `shell` = :shell
WHERE `customerid` = :customerid
AND `id` = :id
");
Database::pexecute($stmt, array(
"desc" => $description,
"shell" => $shell,
"customerid" => $customer['customerid'],
"id" => $id
), true, true);
$result = $this->apiCall('Ftps.get', array(
'username' => $result['username']
));
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_NOTICE, "[API] updated ftp-user '" . $result['username'] . "'");
return $this->response(200, "successfull", $result);
}
/**
* list all ftp-users, if called from an admin, list all ftp-users of all customers you are allowed to view, or specify id or loginname for one specific customer
*
* @param int $customerid
* optional, admin-only, select ftp-users of a specific customer by id
* @param string $loginname
* optional, admin-only, select ftp-users of a specific customer by loginname
*
* @access admin, customer
* @throws Exception
* @return array count|list
*/
public function listing()
{
$customer_ids = $this->getAllowedCustomerIds('ftp');
$result = array();
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_FTP_USERS . "`
WHERE `customerid` IN (".implode(", ", $customer_ids).")
");
Database::pexecute($result_stmt, null, true, true);
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
$result[] = $row;
}
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_NOTICE, "[API] list ftp-users");
return $this->response(200, "successfull", array(
'count' => count($result),
'list' => $result
));
}
/**
* delete a ftp-user by either id or username
*
* @param int $id
* optional, the ftp-user-id
* @param string $username
* optional, the username
* @param bool $delete_userfiles
* optional, default false
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function delete()
{
$id = $this->getParam('id', true, 0);
$un_optional = ($id <= 0 ? false : true);
$username = $this->getParam('username', $un_optional, '');
$delete_userfiles = $this->getBoolParam('delete_userfiles', true, 0);
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'ftp')) {
throw new Exception("You cannot access this resource", 405);
}
// get ftp-user
$result = $this->apiCall('Ftps.get', array(
'id' => $id,
'username' => $username
));
$id = $result['id'];
if ($this->isAdmin()) {
// get customer-data
$customer_data = $this->apiCall('Customers.get', array(
'id' => $result['customerid']
));
} else {
$customer_data = $this->getUserData();
}
// add usage of this ftp-user to main-ftp user of customer if different
if ($result['username'] != $customer_data['loginname']) {
$stmt = Database::prepare("UPDATE `" . TABLE_FTP_USERS . "`
SET `up_count` = `up_count` + :up_count,
`up_bytes` = `up_bytes` + :up_bytes,
`down_count` = `down_count` + :down_count,
`down_bytes` = `down_bytes` + :down_bytes
WHERE `username` = :username
");
$params = array(
"up_count" => $result['up_count'],
"up_bytes" => $result['up_bytes'],
"down_count" => $result['down_count'],
"down_bytes" => $result['down_bytes'],
"username" => $customer_data['loginname']
);
Database::pexecute($stmt, $params, true, true);
}
// remove all quotatallies
$stmt = Database::prepare("DELETE FROM `" . TABLE_FTP_QUOTATALLIES . "` WHERE `name` = :name");
Database::pexecute($stmt, array(
"name" => $result['username']
), true, true);
// remove user itself
$stmt = Database::prepare("
DELETE FROM `" . TABLE_FTP_USERS . "` WHERE `customerid` = :customerid AND `id` = :id
");
Database::pexecute($stmt, array(
"customerid" => $customer_data['customerid'],
"id" => $id
), true, true);
// update ftp-groups
$stmt = Database::prepare("
UPDATE `" . TABLE_FTP_GROUPS . "` SET
`members` = REPLACE(`members`, :username,'')
WHERE `customerid` = :customerid
");
Database::pexecute($stmt, array(
"username" => "," . $result['username'],
"customerid" => $customer_data['customerid']
), true, true);
// refs #293
if ($delete_userfiles == 1) {
inserttask('8', $customer_data['loginname'], $result['homedir']);
} else {
if (Settings::Get('system.nssextrausers') == 1) {
// this is used so that the libnss-extrausers cron is fired
inserttask(5);
}
}
// decrease ftp-user usage for customer
$resetaccnumber = ($customer_data['ftps_used'] == '1') ? " , `ftp_lastaccountnumber`='0'" : '';
Customers::decreaseUsage($customer_data['customerid'], 'ftps_used', $resetaccnumber);
// update admin usage
Admins::decreaseUsage(($this->isAdmin() ? $customer_data['adminid'] : $this->getUserDetail('adminid')), 'ftps_used');
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_WARNING, "[API] deleted ftp-user '" . $result['username'] . "'");
return $this->response(200, "successfull", $result);
}
}

View File

@@ -1,36 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package API
* @since 0.10.0
*
*/
class HostingPlans extends ApiCommand implements ResourceEntity
{
public function add()
{}
public function get()
{}
public function update()
{}
public function listing()
{}
public function delete()
{}
}

View File

@@ -1,516 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package API
* @since 0.10.0
*
*/
class IpsAndPorts extends ApiCommand implements ResourceEntity
{
/**
* lists all ip/port entries
*
* @access admin
* @throws Exception
* @return array count|list
*/
public function listing()
{
if ($this->isAdmin() && ($this->getUserDetail('change_serversettings') || ! empty($this->getUserDetail('ip')))) {
$this->logger()->logAction(ADM_ACTION, LOG_NOTICE, "[API] list ips and ports");
$ip_where = "";
if (! empty($this->getUserDetail('ip')) && $this->getUserDetail('ip') != - 1) {
$ip_where = "WHERE `id` IN (" . implode(", ", json_decode($this->getUserDetail('ip'), true)) . ")";
}
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_IPSANDPORTS . "` " . $ip_where . " ORDER BY `ip` ASC, `port` ASC
");
Database::pexecute($result_stmt, null, true, true);
$result = array();
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
$result[] = $row;
}
return $this->response(200, "successfull", array(
'count' => count($result),
'list' => $result
));
}
throw new Exception("Not allowed to execute given command.", 403);
}
/**
* return an ip/port entry by id
*
* @param int $id
* ip-port-id
*
* @access admin
* @throws Exception
* @return array
*/
public function get()
{
if ($this->isAdmin() && ($this->getUserDetail('change_serversettings') || ! empty($this->getUserDetail('ip')))) {
$id = $this->getParam('id');
if (! empty($this->getUserDetail('ip')) && $this->getUserDetail('ip') != - 1) {
$allowed_ips = json_decode($this->getUserDetail('ip'), true);
if (! in_array($id, $allowed_ips)) {
throw new Exception("You cannot access this resource", 405);
}
}
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_IPSANDPORTS . "` WHERE `id` = :id
");
$result = Database::pexecute_first($result_stmt, array(
'id' => $id
), true, true);
if ($result) {
$this->logger()->logAction(ADM_ACTION, LOG_NOTICE, "[API] get ip " . $result['ip'] . " " . $result['port']);
return $this->response(200, "successfull", $result);
}
throw new Exception("IP/port with id #" . $id . " could not be found", 404);
}
throw new Exception("Not allowed to execute given command.", 403);
}
/**
* create a new ip/port entry
*
* @param string $ip
* @param int $port
* optional, default 80
* @param bool $listen_statement
* optional, default 0 (false)
* @param bool $namevirtualhost_statement
* optional, default 0 (false)
* @param bool $vhostcontainer
* optional, default 0 (false)
* @param string $specialsettings
* optional, default empty
* @param bool $vhostcontainer_servername_statement
* optional, default 0 (false)
* @param string $default_vhostconf_domain
* optional, defatul empty
* @param string $docroot
* optional, default empty (point to froxlor)
* @param bool $ssl
* optional, default 0 (false)
* @param string $ssl_cert_file
* optional, requires $ssl = 1, default empty
* @param string $ssl_key_file
* optional, requires $ssl = 1, default empty
* @param string $ssl_ca_file
* optional, requires $ssl = 1, default empty
* @param string $ssl_cert_chainfile
* optional, requires $ssl = 1, default empty
*
* @access admin
* @throws Exception
* @return array
*/
public function add()
{
if ($this->isAdmin() && $this->getUserDetail('change_serversettings')) {
$ip = validate_ip2($this->getParam('ip'), false, 'invalidip', false, false, false, true);
$port = validate($this->getParam('port', true, 80), 'port', '/^(([1-9])|([1-9][0-9])|([1-9][0-9][0-9])|([1-9][0-9][0-9][0-9])|([1-5][0-9][0-9][0-9][0-9])|(6[0-4][0-9][0-9][0-9])|(65[0-4][0-9][0-9])|(655[0-2][0-9])|(6553[0-5]))$/Di', array(
'stringisempty',
'myport'
), array(), true);
$listen_statement = ! empty($this->getBoolParam('listen_statement', true, 0)) ? 1 : 0;
$namevirtualhost_statement = ! empty($this->getBoolParam('namevirtualhost_statement', true, 0)) ? 1 : 0;
$vhostcontainer = ! empty($this->getBoolParam('vhostcontainer', true, 0)) ? 1 : 0;
$specialsettings = validate(str_replace("\r\n", "\n", $this->getParam('specialsettings', true, '')), 'specialsettings', '/^[^\0]*$/', '', array(), true);
$vhostcontainer_servername_statement = ! empty($this->getBoolParam('vhostcontainer_servername_statement', true, 1)) ? 1 : 0;
$default_vhostconf_domain = validate(str_replace("\r\n", "\n", $this->getParam('default_vhostconf_domain', true, '')), 'default_vhostconf_domain', '/^[^\0]*$/', '', array(), true);
$docroot = validate($this->getParam('docroot', true, ''), 'docroot', '', '', array(), true);
if ((int) Settings::Get('system.use_ssl') == 1) {
$ssl = ! empty($this->getBoolParam('ssl', true, 0)) ? intval($this->getBoolParam('ssl', true, 0)) : 0;
$ssl_cert_file = validate($this->getParam('ssl_cert_file', $ssl, ''), 'ssl_cert_file', '', '', array(), true);
$ssl_key_file = validate($this->getParam('ssl_key_file', $ssl, ''), 'ssl_key_file', '', '', array(), true);
$ssl_ca_file = validate($this->getParam('ssl_ca_file', true, ''), 'ssl_ca_file', '', '', array(), true);
$ssl_cert_chainfile = validate($this->getParam('ssl_cert_chainfile', true, ''), 'ssl_cert_chainfile', '', '', array(), true);
} else {
$ssl = 0;
$ssl_cert_file = '';
$ssl_key_file = '';
$ssl_ca_file = '';
$ssl_cert_chainfile = '';
}
if ($listen_statement != '1') {
$listen_statement = '0';
}
if ($namevirtualhost_statement != '1') {
$namevirtualhost_statement = '0';
}
if ($vhostcontainer != '1') {
$vhostcontainer = '0';
}
if ($vhostcontainer_servername_statement != '1') {
$vhostcontainer_servername_statement = '0';
}
if ($ssl != '1') {
$ssl = '0';
}
if ($ssl_cert_file != '') {
$ssl_cert_file = makeCorrectFile($ssl_cert_file);
}
if ($ssl_key_file != '') {
$ssl_key_file = makeCorrectFile($ssl_key_file);
}
if ($ssl_ca_file != '') {
$ssl_ca_file = makeCorrectFile($ssl_ca_file);
}
if ($ssl_cert_chainfile != '') {
$ssl_cert_chainfile = makeCorrectFile($ssl_cert_chainfile);
}
if (strlen(trim($docroot)) > 0) {
$docroot = makeCorrectDir($docroot);
} else {
$docroot = '';
}
$result_checkfordouble_stmt = Database::prepare("
SELECT `id` FROM `" . TABLE_PANEL_IPSANDPORTS . "`
WHERE `ip` = :ip AND `port` = :port");
$result_checkfordouble = Database::pexecute_first($result_checkfordouble_stmt, array(
'ip' => $ip,
'port' => $port
));
if ($result_checkfordouble['id'] != '') {
standard_error('myipnotdouble', '', true);
}
$ins_stmt = Database::prepare("
INSERT INTO `" . TABLE_PANEL_IPSANDPORTS . "`
SET
`ip` = :ip, `port` = :port, `listen_statement` = :ls,
`namevirtualhost_statement` = :nvhs, `vhostcontainer` = :vhc,
`vhostcontainer_servername_statement` = :vhcss,
`specialsettings` = :ss, `ssl` = :ssl,
`ssl_cert_file` = :ssl_cert, `ssl_key_file` = :ssl_key,
`ssl_ca_file` = :ssl_ca, `ssl_cert_chainfile` = :ssl_chain,
`default_vhostconf_domain` = :dvhd, `docroot` = :docroot;
");
$ins_data = array(
'ip' => $ip,
'port' => $port,
'ls' => $listen_statement,
'nvhs' => $namevirtualhost_statement,
'vhc' => $vhostcontainer,
'vhcss' => $vhostcontainer_servername_statement,
'ss' => $specialsettings,
'ssl' => $ssl,
'ssl_cert' => $ssl_cert_file,
'ssl_key' => $ssl_key_file,
'ssl_ca' => $ssl_ca_file,
'ssl_chain' => $ssl_cert_chainfile,
'dvhd' => $default_vhostconf_domain,
'docroot' => $docroot
);
Database::pexecute($ins_stmt, $ins_data);
$ins_data['id'] = Database::lastInsertId();
inserttask('1');
// Using nameserver, insert a task which rebuilds the server config
inserttask('4');
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
$ip = '[' . $ip . ']';
}
$this->logger()->logAction(ADM_ACTION, LOG_WARNING, "[API] added IP/port '" . $ip . ":" . $port . "'");
// get ip for return-array
$result = $this->apiCall('IpsAndPorts.get', array(
'id' => $ins_data['id']
));
return $this->response(200, "successfull", $result);
}
throw new Exception("Not allowed to execute given command.", 403);
}
/**
* update ip/port entry by given id
*
* @param int $id
* @param string $ip
* optional
* @param int $port
* optional, default 80
* @param bool $listen_statement
* optional, default 0 (false)
* @param bool $namevirtualhost_statement
* optional, default 0 (false)
* @param bool $vhostcontainer
* optional, default 0 (false)
* @param string $specialsettings
* optional, default empty
* @param bool $vhostcontainer_servername_statement
* optional, default 0 (false)
* @param string $default_vhostconf_domain
* optional, defatul empty
* @param string $docroot
* optional, default empty (point to froxlor)
* @param bool $ssl
* optional, default 0 (false)
* @param string $ssl_cert_file
* optional, requires $ssl = 1, default empty
* @param string $ssl_key_file
* optional, requires $ssl = 1, default empty
* @param string $ssl_ca_file
* optional, requires $ssl = 1, default empty
* @param string $ssl_cert_chainfile
* optional, requires $ssl = 1, default empty
*
*
* @access admin
* @throws Exception
* @return array
*/
public function update()
{
if ($this->isAdmin() && ($this->getUserDetail('change_serversettings') || ! empty($this->getUserDetail('ip')))) {
$id = $this->getParam('id');
$result = $this->apiCall('IpsAndPorts.get', array(
'id' => $id
));
$ip = validate_ip2($this->getParam('ip', true, $result['ip']), false, 'invalidip', false, false, false, true);
$port = validate($this->getParam('port', true, $result['port']), 'port', '/^(([1-9])|([1-9][0-9])|([1-9][0-9][0-9])|([1-9][0-9][0-9][0-9])|([1-5][0-9][0-9][0-9][0-9])|(6[0-4][0-9][0-9][0-9])|(65[0-4][0-9][0-9])|(655[0-2][0-9])|(6553[0-5]))$/Di', array(
'stringisempty',
'myport'
), array(), true);
$listen_statement = $this->getBoolParam('listen_statement', true, $result['listen_statement']);
$namevirtualhost_statement = $this->getBoolParam('namevirtualhost_statement', true, $result['namevirtualhost_statement']);
$vhostcontainer = $this->getBoolParam('vhostcontainer', true, $result['vhostcontainer']);
$specialsettings = validate(str_replace("\r\n", "\n", $this->getParam('specialsettings', true, $result['specialsettings'])), 'specialsettings', '/^[^\0]*$/', '', array(), true);
$vhostcontainer_servername_statement = $this->getParam('vhostcontainer_servername_statement', true, $result['vhostcontainer_servername_statement']);
$default_vhostconf_domain = validate(str_replace("\r\n", "\n", $this->getParam('default_vhostconf_domain', true, $result['default_vhostconf_domain'])), 'default_vhostconf_domain', '/^[^\0]*$/', '', array(), true);
$docroot = validate($this->getParam('docroot', true, $result['docroot']), 'docroot', '', '', array(), true);
if ((int) Settings::Get('system.use_ssl') == 1) {
$ssl = $this->getBoolParam('ssl', true, $result['ssl']);
$ssl_cert_file = validate($this->getParam('ssl_cert_file', $ssl, $result['ssl_cert_file']), 'ssl_cert_file', '', '', array(), true);
$ssl_key_file = validate($this->getParam('ssl_key_file', $ssl, $result['ssl_key_file']), 'ssl_key_file', '', '', array(), true);
$ssl_ca_file = validate($this->getParam('ssl_ca_file', true, $result['ssl_ca_file']), 'ssl_ca_file', '', '', array(), true);
$ssl_cert_chainfile = validate($this->getParam('ssl_cert_chainfile', true, $result['ssl_cert_chainfile']), 'ssl_cert_chainfile', '', '', array(), true);
} else {
$ssl = 0;
$ssl_cert_file = '';
$ssl_key_file = '';
$ssl_ca_file = '';
$ssl_cert_chainfile = '';
}
$result_checkfordouble_stmt = Database::prepare("
SELECT `id` FROM `" . TABLE_PANEL_IPSANDPORTS . "`
WHERE `ip` = :ip AND `port` = :port
");
$result_checkfordouble = Database::pexecute_first($result_checkfordouble_stmt, array(
'ip' => $ip,
'port' => $port
));
$result_sameipotherport_stmt = Database::prepare("
SELECT `id` FROM `" . TABLE_PANEL_IPSANDPORTS . "`
WHERE `ip` = :ip AND `id` <> :id
");
$result_sameipotherport = Database::pexecute_first($result_sameipotherport_stmt, array(
'ip' => $ip,
'id' => $id
), true, true);
if ($listen_statement != '1') {
$listen_statement = '0';
}
if ($namevirtualhost_statement != '1') {
$namevirtualhost_statement = '0';
}
if ($vhostcontainer != '1') {
$vhostcontainer = '0';
}
if ($vhostcontainer_servername_statement != '1') {
$vhostcontainer_servername_statement = '0';
}
if ($ssl != '1') {
$ssl = '0';
}
if ($ssl_cert_file != '') {
$ssl_cert_file = makeCorrectFile($ssl_cert_file);
}
if ($ssl_key_file != '') {
$ssl_key_file = makeCorrectFile($ssl_key_file);
}
if ($ssl_ca_file != '') {
$ssl_ca_file = makeCorrectFile($ssl_ca_file);
}
if ($ssl_cert_chainfile != '') {
$ssl_cert_chainfile = makeCorrectFile($ssl_cert_chainfile);
}
if (strlen(trim($docroot)) > 0) {
$docroot = makeCorrectDir($docroot);
} else {
$docroot = '';
}
if ($result['ip'] != $ip && $result['ip'] == Settings::Get('system.ipaddress') && $result_sameipotherport['id'] == '') {
standard_error('cantchangesystemip', '', true);
} elseif ($result_checkfordouble['id'] != '' && $result_checkfordouble['id'] != $id) {
standard_error('myipnotdouble', '', true);
} else {
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_IPSANDPORTS . "`
SET
`ip` = :ip, `port` = :port, `listen_statement` = :ls,
`namevirtualhost_statement` = :nvhs, `vhostcontainer` = :vhc,
`vhostcontainer_servername_statement` = :vhcss,
`specialsettings` = :ss, `ssl` = :ssl,
`ssl_cert_file` = :ssl_cert, `ssl_key_file` = :ssl_key,
`ssl_ca_file` = :ssl_ca, `ssl_cert_chainfile` = :ssl_chain,
`default_vhostconf_domain` = :dvhd, `docroot` = :docroot
WHERE `id` = :id;
");
$upd_data = array(
'ip' => $ip,
'port' => $port,
'ls' => $listen_statement,
'nvhs' => $namevirtualhost_statement,
'vhc' => $vhostcontainer,
'vhcss' => $vhostcontainer_servername_statement,
'ss' => $specialsettings,
'ssl' => $ssl,
'ssl_cert' => $ssl_cert_file,
'ssl_key' => $ssl_key_file,
'ssl_ca' => $ssl_ca_file,
'ssl_chain' => $ssl_cert_chainfile,
'dvhd' => $default_vhostconf_domain,
'docroot' => $docroot,
'id' => $id
);
Database::pexecute($upd_stmt, $upd_data);
inserttask('1');
// Using nameserver, insert a task which rebuilds the server config
inserttask('4');
$this->logger()->logAction(ADM_ACTION, LOG_WARNING, "[API] changed IP/port from '" . $result['ip'] . ":" . $result['port'] . "' to '" . $ip . ":" . $port . "'");
$result = $this->apiCall('IpsAndPorts.get', array(
'id' => $result['id']
));
return $this->response(200, "successfull", $result);
}
}
throw new Exception("Not allowed to execute given command.", 403);
}
/**
* delete an ip/port entry by id
*
* @param int $id
* ip-port-id
*
* @access admin
* @throws Exception
* @return array
*/
public function delete()
{
if ($this->isAdmin() && $this->getUserDetail('change_serversettings')) {
$id = $this->getParam('id');
$result = $this->apiCall('IpsAndPorts.get', array(
'id' => $id
));
$result_checkdomain_stmt = Database::prepare("
SELECT `id_domain` as `id` FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_ipandports` = :id
");
$result_checkdomain = Database::pexecute_first($result_checkdomain_stmt, array(
'id' => $id
), true, true);
if (empty($result_checkdomain)) {
if (! in_array($result['id'], explode(',', Settings::Get('system.defaultip'))) && ! in_array($result['id'], explode(',', Settings::Get('system.defaultsslip')))) {
// check whether there is the same IP with a different port
// in case this ip-address is the system.ipaddress and therefore
// when there is one - we have an alternative
$result_sameipotherport_stmt = Database::prepare("
SELECT `id` FROM `" . TABLE_PANEL_IPSANDPORTS . "`
WHERE `ip` = :ip AND `id` <> :id");
$result_sameipotherport = Database::pexecute_first($result_sameipotherport_stmt, array(
'id' => $id,
'ip' => $result['ip']
));
if (($result['ip'] != Settings::Get('system.ipaddress')) || ($result['ip'] == Settings::Get('system.ipaddress') && $result_sameipotherport['id'] != '')) {
$del_stmt = Database::prepare("
DELETE FROM `" . TABLE_PANEL_IPSANDPORTS . "`
WHERE `id` = :id
");
Database::pexecute($del_stmt, array(
'id' => $id
), true, true);
// also, remove connections to domains (multi-stack)
$del_stmt = Database::prepare("
DELETE FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_ipandports` = :id
");
Database::pexecute($del_stmt, array(
'id' => $id
), true, true);
inserttask('1');
// Using nameserver, insert a task which rebuilds the server config
inserttask('4');
$this->logger()->logAction(ADM_ACTION, LOG_WARNING, "[API] deleted IP/port '" . $result['ip'] . ":" . $result['port'] . "'");
return $this->response(200, "successfull", $result);
} else {
standard_error('cantdeletesystemip', '', true);
}
} else {
standard_error('cantdeletedefaultip', '', true);
}
} else {
standard_error('ipstillhasdomains', '', true);
}
}
throw new Exception("Not allowed to execute given command.", 403);
}
}

View File

@@ -1,481 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package API
* @since 0.10.0
*
*/
class Mysqls extends ApiCommand implements ResourceEntity
{
/**
* add a new mysql-database
*
* @param string $mysql_password
* password for the created database and database-user
* @param int $mysql_server
* optional, default is 0
* @param string $description
* optional, description for database
* @param bool $sendinfomail
* optional, send created resource-information to customer, default: false
* @param int $customer_id
* required when called as admin, not needed when called as customer
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function add()
{
if ($this->getUserDetail('mysqls_used') < $this->getUserDetail('mysqls') || $this->getUserDetail('mysqls') == '-1') {
// required paramters
$password = $this->getParam('mysql_password');
// parameters
$dbserver = $this->getParam('mysql_server', true, 0);
$databasedescription = $this->getParam('description', true, '');
$sendinfomail = $this->getBoolParam('sendinfomail', true, 0);
// validation
$password = validate($password, 'password', '', '', array(), true);
$password = validatePassword($password, true);
$databasedescription = validate(trim($databasedescription), 'description', '', '', array(), true);
// validate whether the dbserver exists
$dbserver = validate($dbserver, html_entity_decode($this->lng['mysql']['mysql_server']), '', '', 0, true);
Database::needRoot(true, $dbserver);
Database::needSqlData();
$sql_root = Database::getSqlData();
Database::needRoot(false);
if (! isset($sql_root) || ! is_array($sql_root)) {
throw new ErrorException("Database server with index #" . $dbserver . " is unknown", 404);
}
if ($sendinfomail != 1) {
$sendinfomail = 0;
}
// get needed customer info to reduce the mysql-usage-counter by one
$customer = $this->getCustomerData('mysqls');
$newdb_params = array(
'loginname' => ($this->isAdmin() ? $customer['loginname'] : $this->getUserDetail('loginname')),
'mysql_lastaccountnumber' => ($this->isAdmin() ? $customer['mysql_lastaccountnumber'] : $this->getUserDetail('mysql_lastaccountnumber'))
);
// create database, user, set permissions, etc.pp.
$dbm = new DbManager($this->logger());
$username = $dbm->createDatabase($newdb_params['loginname'], $password, $newdb_params['mysql_lastaccountnumber']);
// we've checked against the password in dbm->createDatabase
if ($username == false) {
standard_error('passwordshouldnotbeusername', '', true);
}
// add database info to froxlor
$stmt = Database::prepare("
INSERT INTO `" . TABLE_PANEL_DATABASES . "`
SET
`customerid` = :customerid,
`databasename` = :databasename,
`description` = :description,
`dbserver` = :dbserver
");
$params = array(
"customerid" => $customer['customerid'],
"databasename" => $username,
"description" => $databasedescription,
"dbserver" => $dbserver
);
Database::pexecute($stmt, $params, true, true);
$databaseid = Database::lastInsertId();
$params['id'] = $databaseid;
// update customer usage
Customers::increaseUsage($customer['customerid'], 'mysqls_used');
Customers::increaseUsage($customer['customerid'], 'mysql_lastaccountnumber');
// update admin usage
Admins::increaseUsage($this->getUserDetail('adminid'), 'mysqls_used');
// send info-mail?
if ($sendinfomail == 1) {
$pma = $this->lng['admin']['notgiven'];
if (Settings::Get('panel.phpmyadmin_url') != '') {
$pma = Settings::Get('panel.phpmyadmin_url');
}
Database::needRoot(true, $dbserver);
Database::needSqlData();
$sql_root = Database::getSqlData();
Database::needRoot(false);
$userinfo = $customer;
$replace_arr = array(
'SALUTATION' => getCorrectUserSalutation($userinfo),
'CUST_NAME' => getCorrectUserSalutation($userinfo), // < keep this for compatibility
'DB_NAME' => $username,
'DB_PASS' => $password,
'DB_DESC' => $databasedescription,
'DB_SRV' => $sql_root['host'],
'PMA_URI' => $pma
);
// get template for mail subject
$mail_subject = $this->getMailTemplate($userinfo, 'mails', 'new_database_by_customer_subject', $replace_arr, $this->lng['mails']['new_database_by_customer']['subject']);
// get template for mail body
$mail_body = $this->getMailTemplate($userinfo, 'mails', 'new_database_by_customer_mailbody', $replace_arr, $this->lng['mails']['new_database_by_customer']['mailbody']);
$_mailerror = false;
$mailerr_msg = "";
try {
$this->mailer()->Subject = $mail_subject;
$this->mailer()->AltBody = $mail_body;
$this->mailer()->msgHTML(str_replace("\n", "<br />", $mail_body));
$this->mailer()->addAddress($userinfo['email'], getCorrectUserSalutation($userinfo));
$this->mailer()->send();
} catch (phpmailerException $e) {
$mailerr_msg = $e->errorMessage();
$_mailerror = true;
} catch (Exception $e) {
$mailerr_msg = $e->getMessage();
$_mailerror = true;
}
if ($_mailerror) {
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_ERR, "[API] Error sending mail: " . $mailerr_msg);
standard_error('errorsendingmail', $userinfo['email'], true);
}
$this->mailer()->clearAddresses();
}
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_WARNING, "[API] added mysql-database '" . $username . "'");
$result = $this->apiCall('Mysqls.get', array(
'dbname' => $username
));
return $this->response(200, "successfull", $result);
}
throw new Exception("No more resources available", 406);
}
/**
* return a mysql database entry by either id or dbname
*
* @param int $id
* optional, the database-id
* @param string $dbname
* optional, the databasename
* @param int $mysql_server
* optional, specify database-server, default is none
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function get()
{
$id = $this->getParam('id', true, 0);
$dn_optional = ($id <= 0 ? false : true);
$dbname = $this->getParam('dbname', $dn_optional, '');
$dbserver = $this->getParam('mysql_server', true, - 1);
if ($this->isAdmin()) {
if ($this->getUserDetail('customers_see_all') != 1) {
// if it's a reseller or an admin who cannot see all customers, we need to check
// whether the database belongs to one of his customers
$_custom_list_result = $this->apiCall('Customers.listing');
$custom_list_result = $_custom_list_result['list'];
$customer_ids = array();
foreach ($custom_list_result as $customer) {
$customer_ids[] = $customer['customerid'];
}
if (count($customer_ids) > 0) {
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_DATABASES . "`
WHERE " . ($id > 0 ? "`id` = :iddn" : "`databasename` = :iddn") . ($dbserver >= 0 ? " AND `dbserver` = :dbserver" : "") . " AND `customerid` IN (".implode(", ", $customer_ids).")
");
$params = array(
'iddn' => ($id <= 0 ? $dbname : $id)
);
if ($dbserver >= 0) {
$params['dbserver'] = $dbserver;
}
} else {
throw new Exception("You do not have any customers yet", 406);
}
} else {
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_DATABASES . "`
WHERE " . ($id > 0 ? "`id` = :iddn" : "`databasename` = :iddn") . ($dbserver >= 0 ? " AND `dbserver` = :dbserver" : ""));
$params = array(
'iddn' => ($id <= 0 ? $dbname : $id)
);
if ($dbserver >= 0) {
$params['dbserver'] = $dbserver;
}
}
} else {
if (Settings::IsInList('panel.customer_hide_options', 'mysql')) {
throw new Exception("You cannot access this resource", 405);
}
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_DATABASES . "`
WHERE `customerid`= :customerid AND " . ($id > 0 ? "`id` = :iddn" : "`databasename` = :iddn") . ($dbserver >= 0 ? " AND `dbserver` = :dbserver" : ""));
$params = array(
'customerid' => $this->getUserDetail('customerid'),
'iddn' => ($id <= 0 ? $dbname : $id)
);
if ($dbserver >= 0) {
$params['dbserver'] = $dbserver;
}
}
$result = Database::pexecute_first($result_stmt, $params, true, true);
if ($result) {
Database::needRoot(true, $result['dbserver']);
$mbdata_stmt = Database::prepare("
SELECT SUM(data_length + index_length) as MB FROM information_schema.TABLES
WHERE table_schema = :table_schema
GROUP BY table_schema
");
Database::pexecute($mbdata_stmt, array(
"table_schema" => $result['databasename']
), true, true);
$mbdata = $mbdata_stmt->fetch(PDO::FETCH_ASSOC);
Database::needRoot(false);
$result['size'] = $mbdata['MB'];
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_NOTICE, "[API] get database '" . $result['databasename'] . "'");
return $this->response(200, "successfull", $result);
}
$key = ($id > 0 ? "id #" . $id : "dbname '" . $dbname . "'");
throw new Exception("MySQL database with " . $key . " could not be found", 404);
}
/**
* update a mysql database entry by either id or dbname
*
* @param int $id
* optional, the database-id
* @param string $dbname
* optional, the databasename
* @param int $mysql_server
* optional, specify database-server, default is none
* @param string $mysql_password
* optional, update password for the database
* @param string $description
* optional, description for database
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function update()
{
$id = $this->getParam('id', true, 0);
$dn_optional = ($id <= 0 ? false : true);
$dbname = $this->getParam('dbname', $dn_optional, '');
$dbserver = $this->getParam('mysql_server', true, - 1);
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'mysql')) {
throw new Exception("You cannot access this resource", 405);
}
$result = $this->apiCall('Mysqls.get', array(
'id' => $id,
'dbname' => $dbname,
'mysql_server' => $dbserver
));
$id = $result['id'];
// paramters
$password = $this->getParam('mysql_password', true, '');
$databasedescription = $this->getParam('description', true, '');
// validation
$password = validate($password, 'password', '', '', array(), true);
$databasedescription = validate(trim($databasedescription), 'description', '', '', array(), true);
// get needed customer info to reduce the mysql-usage-counter by one
$customer = $this->getCustomerData();
if ($password != '') {
// validate password
$password = validatePassword($password, true);
if ($password == $result['databasename']) {
standard_error('passwordshouldnotbeusername', '', true);
}
// Begin root-session
Database::needRoot(true, $result['dbserver']);
foreach (array_map('trim', explode(',', Settings::Get('system.mysql_access_host'))) as $mysql_access_host) {
$stmt = Database::prepare("SET PASSWORD FOR :dbname@:host = PASSWORD(:password)");
$params = array(
"dbname" => $result['databasename'],
"host" => $mysql_access_host,
"password" => $password
);
Database::pexecute($stmt, $params, true, true);
}
$stmt = Database::prepare("FLUSH PRIVILEGES");
Database::pexecute($stmt, null, true, true);
Database::needRoot(false);
// End root-session
}
$stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_DATABASES . "`
SET `description` = :desc
WHERE `customerid` = :customerid
AND `id` = :id
");
$params = array(
"desc" => $databasedescription,
"customerid" => $customer['customerid'],
"id" => $id
);
Database::pexecute($stmt, $params, true, true);
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_WARNING, "[API] updated mysql-database '" . $result['databasename'] . "'");
$result = $this->apiCall('Mysqls.get', array(
'dbname' => $result['databasename']
));
return $this->response(200, "successfull", $result);
}
/**
* list all databases, if called from an admin, list all databases of all customers you are allowed to view, or specify id or loginname for one specific customer
*
* @param int $mysql_server
* optional, specify dbserver to select from, else use all available
* @param int $customerid
* optional, admin-only, select dbs of a specific customer by id
* @param string $loginname
* optional, admin-only, select dbs of a specific customer by loginname
*
* @access admin, customer
* @throws Exception
* @return array count|list
*/
public function listing()
{
$result = array();
$dbserver = $this->getParam('mysql_server', true, - 1);
$customer_ids = $this->getAllowedCustomerIds('mysql');
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_DATABASES . "`
WHERE `customerid`= :customerid AND `dbserver` = :dbserver
");
if ($dbserver < 0) {
// use all dbservers
$dbservers_stmt = Database::query("SELECT DISTINCT `dbserver` FROM `" . TABLE_PANEL_DATABASES . "`");
$dbservers = $dbservers_stmt->fetchAll(PDO::FETCH_ASSOC);
} else {
// use specific dbserver
$dbservers = array(
array(
'dbserver' => $dbserver
)
);
}
foreach ($customer_ids as $customer_id) {
foreach ($dbservers as $_dbserver) {
Database::pexecute($result_stmt, array(
'customerid' => $customer_id,
'dbserver' => $_dbserver['dbserver']
), true, true);
// Begin root-session
Database::needRoot(true, $_dbserver['dbserver']);
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
$mbdata_stmt = Database::prepare("
SELECT SUM(data_length + index_length) as MB FROM information_schema.TABLES
WHERE table_schema = :table_schema
GROUP BY table_schema
");
Database::pexecute($mbdata_stmt, array(
"table_schema" => $row['databasename']
), true, true);
$mbdata = $mbdata_stmt->fetch(PDO::FETCH_ASSOC);
$row['size'] = $mbdata['MB'];
$result[] = $row;
}
Database::needRoot(false);
}
}
return $this->response(200, "successfull", array(
'count' => count($result),
'list' => $result
));
}
/**
* delete a mysql database by either id or dbname
*
* @param int $id
* optional, the database-id
* @param string $dbname
* optional, the databasename
* @param int $mysql_server
* optional, specify database-server, default is none
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function delete()
{
$id = $this->getParam('id', true, 0);
$dn_optional = ($id <= 0 ? false : true);
$dbname = $this->getParam('dbname', $dn_optional, '');
$dbserver = $this->getParam('mysql_server', true, - 1);
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'mysql')) {
throw new Exception("You cannot access this resource", 405);
}
$result = $this->apiCall('Mysqls.get', array(
'id' => $id,
'dbname' => $dbname,
'mysql_server' => $dbserver
));
$id = $result['id'];
// Begin root-session
Database::needRoot(true, $result['dbserver']);
$dbm = new DbManager($this->logger());
$dbm->getManager()->deleteDatabase($result['databasename']);
Database::needRoot(false);
// End root-session
// delete from table
$stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_DATABASES . "` WHERE `id` = :id");
Database::pexecute($stmt, array(
"id" => $id
), true, true);
// get needed customer info to reduce the mysql-usage-counter by one
$customer = $this->getCustomerData();
$mysql_used = $customer['mysqls_used'];
// reduce mysql-usage-counter
$resetaccnumber = ($mysql_used == '1') ? " , `mysql_lastaccountnumber` = '0' " : '';
Customers::decreaseUsage($customer['customerid'], 'mysqls_used', $resetaccnumber);
// update admin usage
Admins::decreaseUsage(($this->isAdmin() ? $customer['adminid'] : $this->getUserDetail('adminid')), 'mysqls_used');
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_WARNING, "[API] deleted database '" . $result['databasename'] . "'");
return $this->response(200, "successfull", $result);
}
}

View File

@@ -1,589 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package API
* @since 0.10.0
*
*/
class PhpSettings extends ApiCommand implements ResourceEntity
{
/**
* lists all php-setting entries
*
* @param bool $with_subdomains
* optional, also include subdomains to the list domains that use the config, default 0 (false)
*
* @access admin
* @throws Exception
* @return array count|list
*/
public function listing()
{
if ($this->isAdmin()) {
$this->logger()->logAction(ADM_ACTION, LOG_NOTICE, "[API] list php-configs");
$with_subdomains = $this->getBoolParam('with_subdomains', true, false);
$result = Database::query("
SELECT c.*, fd.description as fpmdesc
FROM `" . TABLE_PANEL_PHPCONFIGS . "` c
LEFT JOIN `" . TABLE_PANEL_FPMDAEMONS . "` fd ON fd.id = c.fpmsettingid
ORDER BY c.description ASC
");
$phpconfigs = array();
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
$query_params = array(
'id' => $row['id']
);
$query = "SELECT * FROM `" . TABLE_PANEL_DOMAINS . "`
WHERE `phpsettingid` = :id";
if (!$with_subdomains) {
$query .= " AND `parentdomainid` = '0'";
}
if ((int) $this->getUserDetail('domains_see_all') == 0) {
$query .= " AND `adminid` = :adminid";
$query_params['adminid'] = $this->getUserDetail('adminid');
}
if ((int) Settings::Get('panel.phpconfigs_hidestdsubdomain') == 1) {
$ssdids_res = Database::query("
SELECT DISTINCT `standardsubdomain` FROM `" . TABLE_PANEL_CUSTOMERS . "`
WHERE `standardsubdomain` > 0 ORDER BY `standardsubdomain` ASC;");
$ssdids = array();
while ($ssd = $ssdids_res->fetch(PDO::FETCH_ASSOC)) {
$ssdids[] = $ssd['standardsubdomain'];
}
if (count($ssdids) > 0) {
$query .= " AND `id` NOT IN (" . implode(', ', $ssdids) . ")";
}
}
$domains = array();
$subdomains = array();
$domainresult_stmt = Database::prepare($query);
Database::pexecute($domainresult_stmt, $query_params, true, true);
if (Database::num_rows() > 0) {
while ($row2 = $domainresult_stmt->fetch(PDO::FETCH_ASSOC)) {
if ($row2['parentdomainid'] != 0) {
$subdomains[] = $row2['domain'];
} else {
$domains[] = $row2['domain'];
}
}
}
// check whether we use that config as froxor-vhost config
if (Settings::Get('system.mod_fcgid_defaultini_ownvhost') == $row['id'] || Settings::Get('phpfpm.vhost_defaultini') == $row['id']) {
$domains[] = Settings::Get('system.hostname');
}
// check whether this is our default config
if ((Settings::Get('system.mod_fcgid') == '1' && Settings::Get('system.mod_fcgid_defaultini') == $row['id']) || (Settings::Get('phpfpm.enabled') == '1' && Settings::Get('phpfpm.defaultini') == $row['id'])) {
$row['is_default'] = true;
}
$row['domains'] = $domains;
$row['subdomains'] = $subdomains;
$phpconfigs[] = $row;
}
return $this->response(200, "successfull", array(
'count' => count($phpconfigs),
'list' => $phpconfigs
));
}
throw new Exception("Not allowed to execute given command.", 403);
}
/**
* return a php-setting entry by id
*
* @param int $id
* php-settings-id
*
* @access admin
* @throws Exception
* @return array
*/
public function get()
{
if ($this->isAdmin()) {
$id = $this->getParam('id');
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_PHPCONFIGS . "` WHERE `id` = :id
");
$result = Database::pexecute_first($result_stmt, array(
'id' => $id
), true, true);
if ($result) {
return $this->response(200, "successfull", $result);
}
throw new Exception("php-config with id #" . $id . " could not be found", 404);
}
throw new Exception("Not allowed to execute given command.", 403);
}
/**
* add new php-settings entry
*
* @param string $description
* description of the php-config
* @param string $phpsettings
* the actual ini-settings
* @param string $binary
* optional the binary to php-cgi if FCGID is used
* @param string $file_extensions
* optional allowed php-file-extensions if FCGID is used, default is 'php'
* @param int $mod_fcgid_starter
* optional number of fcgid-starters if FCGID is used, default is -1
* @param int $mod_fcgid_maxrequests
* optional number of fcgid-maxrequests if FCGID is used, default is -1
* @param string $mod_fcgid_umask
* optional umask if FCGID is used, default is '022'
* @param int $fpmconfig
* optional id of the fpm-daemon-config if FPM is used
* @param bool $phpfpm_enable_slowlog
* optional whether to write a slowlog or not if FPM is used, default is 0 (false)
* @param string $phpfpm_reqtermtimeout
* optional request terminate timeout if FPM is used, default is '60s'
* @param string $phpfpm_reqslowtimeout
* optional request slowlog timeout if FPM is used, default is '5s'
* @param bool $phpfpm_pass_authorizationheader
* optional whether to pass authorization header to webserver if FPM is used, default is 0 (false)
* @param bool $override_fpmconfig
* optional whether to override fpm-daemon-config value for the following settings if FPM is used, default is 0 (false)
* @param string $pm
* optional process-manager to use if FPM is used (allowed values are 'static', 'dynamic' and 'ondemand'), default is fpm-daemon-value
* @param int $max_children
* optional number of max children if FPM is used, default is the fpm-daemon-value
* @param int $start_server
* optional number of servers to start if FPM is used, default is fpm-daemon-value
* @param int $min_spare_servers
* optional number of minimum spare servers if FPM is used, default is fpm-daemon-value
* @param int $max_spare_servers
* optional number of maximum spare servers if FPM is used, default is fpm-daemon-value
* @param int $max_requests
* optional number of maximum requests if FPM is used, default is fpm-daemon-value
* @param int $idle_timeout
* optional number of seconds for idle-timeout if FPM is used, default is fpm-daemon-value
* @param string $limit_extensions
* optional limitation of php-file-extensions if FPM is used, default is fpm-daemon-value
*
* @access admin
* @throws Exception
* @return array
*/
public function add()
{
if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) {
// required parameter
$description = $this->getParam('description');
$phpsettings = $this->getParam('phpsettings');
if (Settings::Get('system.mod_fcgid') == 1) {
$binary = $this->getParam('binary');
$fpm_config_id = 1;
} elseif (Settings::Get('phpfpm.enabled') == 1) {
$fpm_config_id = intval($this->getParam('fpmconfig'));
} else {
$fpm_config_id = 1;
}
// parameters
$file_extensions = $this->getParam('file_extensions', true, 'php');
$mod_fcgid_starter = $this->getParam('mod_fcgid_starter', true, - 1);
$mod_fcgid_maxrequests = $this->getParam('mod_fcgid_maxrequests', true, - 1);
$mod_fcgid_umask = $this->getParam('mod_fcgid_umask', true, "022");
$fpm_enableslowlog = $this->getBoolParam('phpfpm_enable_slowlog', true, 0);
$fpm_reqtermtimeout = $this->getParam('phpfpm_reqtermtimeout', true, "60s");
$fpm_reqslowtimeout = $this->getParam('phpfpm_reqslowtimeout', true, "5s");
$fpm_pass_authorizationheader = $this->getBoolParam('phpfpm_pass_authorizationheader', true, 0);
$override_fpmconfig = $this->getBoolParam('override_fpmconfig', true, 0);
$def_fpmconfig = $this->apiCall('FpmDaemons.get', array(
'id' => $fpm_config_id
));
$pmanager = $this->getParam('pm', true, $def_fpmconfig['pm']);
$max_children = $this->getParam('max_children', true, $def_fpmconfig['max_children']);
$start_servers = $this->getParam('start_servers', true, $def_fpmconfig['start_servers']);
$min_spare_servers = $this->getParam('min_spare_servers', true, $def_fpmconfig['min_spare_servers']);
$max_spare_servers = $this->getParam('max_spare_servers', true, $def_fpmconfig['max_spare_servers']);
$max_requests = $this->getParam('max_requests', true, $def_fpmconfig['max_requests']);
$idle_timeout = $this->getParam('idle_timeout', true, $def_fpmconfig['idle_timeout']);
$limit_extensions = $this->getParam('limit_extensions', true, $def_fpmconfig['limit_extensions']);
// validation
$description = validate($description, 'description', '', '', array(), true);
$phpsettings = validate(str_replace("\r\n", "\n", $phpsettings), 'phpsettings', '/^[^\0]*$/', '', array(), true);
if (Settings::Get('system.mod_fcgid') == 1) {
$binary = makeCorrectFile(validate($binary, 'binary', '', '', array(), true));
$file_extensions = validate($file_extensions, 'file_extensions', '/^[a-zA-Z0-9\s]*$/', '', array(), true);
$mod_fcgid_starter = validate($mod_fcgid_starter, 'mod_fcgid_starter', '/^[0-9]*$/', '', array(
'-1',
''
), true);
$mod_fcgid_maxrequests = validate($mod_fcgid_maxrequests, 'mod_fcgid_maxrequests', '/^[0-9]*$/', '', array(
'-1',
''
), true);
$mod_fcgid_umask = validate($mod_fcgid_umask, 'mod_fcgid_umask', '/^[0-9]*$/', '', array(), true);
// disable fpm stuff
$fpm_config_id = 1;
$fpm_enableslowlog = 0;
$fpm_reqtermtimeout = 0;
$fpm_reqslowtimeout = 0;
$fpm_pass_authorizationheader = 0;
$override_fpmconfig = 0;
} elseif (Settings::Get('phpfpm.enabled') == 1) {
$fpm_reqtermtimeout = validate($fpm_reqtermtimeout, 'phpfpm_reqtermtimeout', '/^([0-9]+)(|s|m|h|d)$/', '', array(), true);
$fpm_reqslowtimeout = validate($fpm_reqslowtimeout, 'phpfpm_reqslowtimeout', '/^([0-9]+)(|s|m|h|d)$/', '', array(), true);
if (! in_array($pmanager, array(
'static',
'dynamic',
'ondemand'
))) {
throw new ErrorException("Unknown process manager", 406);
}
if (empty($limit_extensions)) {
$limit_extensions = '.php';
}
$limit_extensions = validate($limit_extensions, 'limit_extensions', '/^(\.[a-z]([a-z0-9]+)\ ?)+$/', '', array(), true);
// disable fcgid stuff
$binary = '/usr/bin/php-cgi';
$file_extensions = 'php';
$mod_fcgid_starter = 0;
$mod_fcgid_maxrequests = 0;
$mod_fcgid_umask = "022";
}
if (strlen($description) == 0 || strlen($description) > 50) {
standard_error('descriptioninvalid', '', true);
}
$ins_stmt = Database::prepare("
INSERT INTO `" . TABLE_PANEL_PHPCONFIGS . "` SET
`description` = :desc,
`binary` = :binary,
`file_extensions` = :fext,
`mod_fcgid_starter` = :starter,
`mod_fcgid_maxrequests` = :mreq,
`mod_fcgid_umask` = :umask,
`fpm_slowlog` = :fpmslow,
`fpm_reqterm` = :fpmreqterm,
`fpm_reqslow` = :fpmreqslow,
`phpsettings` = :phpsettings,
`fpmsettingid` = :fpmsettingid,
`pass_authorizationheader` = :fpmpassauth,
`override_fpmconfig` = :ofc,
`pm` = :pm,
`max_children` = :max_children,
`start_servers` = :start_servers,
`min_spare_servers` = :min_spare_servers,
`max_spare_servers` = :max_spare_servers,
`max_requests` = :max_requests,
`idle_timeout` = :idle_timeout,
`limit_extensions` = :limit_extensions
");
$ins_data = array(
'desc' => $description,
'binary' => $binary,
'fext' => $file_extensions,
'starter' => $mod_fcgid_starter,
'mreq' => $mod_fcgid_maxrequests,
'umask' => $mod_fcgid_umask,
'fpmslow' => $fpm_enableslowlog,
'fpmreqterm' => $fpm_reqtermtimeout,
'fpmreqslow' => $fpm_reqslowtimeout,
'phpsettings' => $phpsettings,
'fpmsettingid' => $fpm_config_id,
'fpmpassauth' => $fpm_pass_authorizationheader,
'ofc' => $override_fpmconfig,
'pm' => $pmanager,
'max_children' => $max_children,
'start_servers' => $start_servers,
'min_spare_servers' => $min_spare_servers,
'max_spare_servers' => $max_spare_servers,
'max_requests' => $max_requests,
'idle_timeout' => $idle_timeout,
'limit_extensions' => $limit_extensions
);
Database::pexecute($ins_stmt, $ins_data, true, true);
$ins_data['id'] = Database::lastInsertId();
inserttask('1');
$this->logger()->logAction(ADM_ACTION, LOG_INFO, "[API] php setting with description '" . $description . "' has been created by '" . $this->getUserDetail('loginname') . "'");
$result = $this->apiCall('PhpSettings.get', array(
'id' => $ins_data['id']
));
return $this->response(200, "successfull", $result);
}
throw new Exception("Not allowed to execute given command.", 403);
}
/**
* update a php-setting entry by given id
*
* @param int $id
* @param string $description
* description of the php-config
* @param string $phpsettings
* the actual ini-settings
* @param string $binary
* optional the binary to php-cgi if FCGID is used
* @param string $file_extensions
* optional allowed php-file-extensions if FCGID is used, default is 'php'
* @param int $mod_fcgid_starter
* optional number of fcgid-starters if FCGID is used, default is -1
* @param int $mod_fcgid_maxrequests
* optional number of fcgid-maxrequests if FCGID is used, default is -1
* @param string $mod_fcgid_umask
* optional umask if FCGID is used, default is '022'
* @param int $fpmconfig
* optional id of the fpm-daemon-config if FPM is used
* @param bool $phpfpm_enable_slowlog
* optional whether to write a slowlog or not if FPM is used, default is 0 (false)
* @param string $phpfpm_reqtermtimeout
* optional request terminate timeout if FPM is used, default is '60s'
* @param string $phpfpm_reqslowtimeout
* optional request slowlog timeout if FPM is used, default is '5s'
* @param bool $phpfpm_pass_authorizationheader
* optional whether to pass authorization header to webserver if FPM is used, default is 0 (false)
* @param bool $override_fpmconfig
* optional whether to override fpm-daemon-config value for the following settings if FPM is used, default is 0 (false)
* @param string $pm
* optional process-manager to use if FPM is used (allowed values are 'static', 'dynamic' and 'ondemand'), default is fpm-daemon-value
* @param int $max_children
* optional number of max children if FPM is used, default is the fpm-daemon-value
* @param int $start_server
* optional number of servers to start if FPM is used, default is fpm-daemon-value
* @param int $min_spare_servers
* optional number of minimum spare servers if FPM is used, default is fpm-daemon-value
* @param int $max_spare_servers
* optional number of maximum spare servers if FPM is used, default is fpm-daemon-value
* @param int $max_requests
* optional number of maximum requests if FPM is used, default is fpm-daemon-value
* @param int $idle_timeout
* optional number of seconds for idle-timeout if FPM is used, default is fpm-daemon-value
* @param string $limit_extensions
* optional limitation of php-file-extensions if FPM is used, default is fpm-daemon-value
*
* @access admin
* @throws Exception
* @return array
*/
public function update()
{
if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) {
// required parameter
$id = $this->getParam('id');
$result = $this->apiCall('PhpSettings.get', array(
'id' => $id
));
// parameters
$description = $this->getParam('description', true, $result['description']);
$phpsettings = $this->getParam('phpsettings', true, $result['phpsettings']);
$binary = $this->getParam('binary', true, $result['binary']);
$fpm_config_id = intval($this->getParam('fpmconfig', true, $result['fpmsettingid']));
$file_extensions = $this->getParam('file_extensions', true, $result['file_extensions']);
$mod_fcgid_starter = $this->getParam('mod_fcgid_starter', true, $result['mod_fcgid_starter']);
$mod_fcgid_maxrequests = $this->getParam('mod_fcgid_maxrequests', true, $result['mod_fcgid_maxrequests']);
$mod_fcgid_umask = $this->getParam('mod_fcgid_umask', true, $result['mod_fcgid_umask']);
$fpm_enableslowlog = $this->getBoolParam('phpfpm_enable_slowlog', true, $result['fpm_slowlog']);
$fpm_reqtermtimeout = $this->getParam('phpfpm_reqtermtimeout', true, $result['fpm_reqterm']);
$fpm_reqslowtimeout = $this->getParam('phpfpm_reqslowtimeout', true, $result['fpm_reqslow']);
$fpm_pass_authorizationheader = $this->getBoolParam('phpfpm_pass_authorizationheader', true, $result['pass_authorizationheader']);
$override_fpmconfig = $this->getBoolParam('override_fpmconfig', true, $result['override_fpmconfig']);
$pmanager = $this->getParam('pm', true, $result['pm']);
$max_children = $this->getParam('max_children', true, $result['max_children']);
$start_servers = $this->getParam('start_servers', true, $result['start_servers']);
$min_spare_servers = $this->getParam('min_spare_servers', true, $result['min_spare_servers']);
$max_spare_servers = $this->getParam('max_spare_servers', true, $result['max_spare_servers']);
$max_requests = $this->getParam('max_requests', true, $result['max_requests']);
$idle_timeout = $this->getParam('idle_timeout', true, $result['idle_timeout']);
$limit_extensions = $this->getParam('limit_extensions', true, $result['limit_extensions']);
// validation
$description = validate($description, 'description', '', '', array(), true);
$phpsettings = validate(str_replace("\r\n", "\n", $phpsettings), 'phpsettings', '/^[^\0]*$/', '', array(), true);
if (Settings::Get('system.mod_fcgid') == 1) {
$binary = makeCorrectFile(validate($binary, 'binary', '', '', array(), true));
$file_extensions = validate($file_extensions, 'file_extensions', '/^[a-zA-Z0-9\s]*$/', '', array(), true);
$mod_fcgid_starter = validate($mod_fcgid_starter, 'mod_fcgid_starter', '/^[0-9]*$/', '', array(
'-1',
''
), true);
$mod_fcgid_maxrequests = validate($mod_fcgid_maxrequests, 'mod_fcgid_maxrequests', '/^[0-9]*$/', '', array(
'-1',
''
), true);
$mod_fcgid_umask = validate($mod_fcgid_umask, 'mod_fcgid_umask', '/^[0-9]*$/', '', array(), true);
// disable fpm stuff
$fpm_config_id = 1;
$fpm_enableslowlog = 0;
$fpm_reqtermtimeout = 0;
$fpm_reqslowtimeout = 0;
$fpm_pass_authorizationheader = 0;
$override_fpmconfig = 0;
} elseif (Settings::Get('phpfpm.enabled') == 1) {
$fpm_reqtermtimeout = validate($fpm_reqtermtimeout, 'phpfpm_reqtermtimeout', '/^([0-9]+)(|s|m|h|d)$/', '', array(), true);
$fpm_reqslowtimeout = validate($fpm_reqslowtimeout, 'phpfpm_reqslowtimeout', '/^([0-9]+)(|s|m|h|d)$/', '', array(), true);
if (! in_array($pmanager, array(
'static',
'dynamic',
'ondemand'
))) {
throw new ErrorException("Unknown process manager", 406);
}
if (empty($limit_extensions)) {
$limit_extensions = '.php';
}
$limit_extensions = validate($limit_extensions, 'limit_extensions', '/^(\.[a-z]([a-z0-9]+)\ ?)+$/', '', array(), true);
// disable fcgid stuff
$binary = '/usr/bin/php-cgi';
$file_extensions = 'php';
$mod_fcgid_starter = 0;
$mod_fcgid_maxrequests = 0;
$mod_fcgid_umask = "022";
}
if (strlen($description) == 0 || strlen($description) > 50) {
standard_error('descriptioninvalid', '', true);
}
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_PHPCONFIGS . "` SET
`description` = :desc,
`binary` = :binary,
`file_extensions` = :fext,
`mod_fcgid_starter` = :starter,
`mod_fcgid_maxrequests` = :mreq,
`mod_fcgid_umask` = :umask,
`fpm_slowlog` = :fpmslow,
`fpm_reqterm` = :fpmreqterm,
`fpm_reqslow` = :fpmreqslow,
`phpsettings` = :phpsettings,
`fpmsettingid` = :fpmsettingid,
`pass_authorizationheader` = :fpmpassauth,
`override_fpmconfig` = :ofc,
`pm` = :pm,
`max_children` = :max_children,
`start_servers` = :start_servers,
`min_spare_servers` = :min_spare_servers,
`max_spare_servers` = :max_spare_servers,
`max_requests` = :max_requests,
`idle_timeout` = :idle_timeout,
`limit_extensions` = :limit_extensions
WHERE `id` = :id
");
$upd_data = array(
'desc' => $description,
'binary' => $binary,
'fext' => $file_extensions,
'starter' => $mod_fcgid_starter,
'mreq' => $mod_fcgid_maxrequests,
'umask' => $mod_fcgid_umask,
'fpmslow' => $fpm_enableslowlog,
'fpmreqterm' => $fpm_reqtermtimeout,
'fpmreqslow' => $fpm_reqslowtimeout,
'phpsettings' => $phpsettings,
'fpmsettingid' => $fpm_config_id,
'fpmpassauth' => $fpm_pass_authorizationheader,
'ofc' => $override_fpmconfig,
'pm' => $pmanager,
'max_children' => $max_children,
'start_servers' => $start_servers,
'min_spare_servers' => $min_spare_servers,
'max_spare_servers' => $max_spare_servers,
'max_requests' => $max_requests,
'idle_timeout' => $idle_timeout,
'limit_extensions' => $limit_extensions,
'id' => $id
);
Database::pexecute($upd_stmt, $upd_data, true, true);
inserttask('1');
$this->logger()->logAction(ADM_ACTION, LOG_INFO, "[API] php setting with description '" . $description . "' has been updated by '" . $this->getUserDetail('loginname') . "'");
$result = $this->apiCall('PhpSettings.get', array(
'id' => $id
));
return $this->response(200, "successfull", $result);
}
throw new Exception("Not allowed to execute given command.", 403);
}
/**
* delete a php-setting entry by id
*
* @param int $id
* php-settings-id
*
* @access admin
* @throws Exception
* @return array
*/
public function delete()
{
if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) {
$id = $this->getParam('id');
$result = $this->apiCall('PhpSettings.get', array(
'id' => $id
));
if ((Settings::Get('system.mod_fcgid') == '1' && Settings::Get('system.mod_fcgid_defaultini_ownvhost') == $id) || (Settings::Get('phpfpm.enabled') == '1' && Settings::Get('phpfpm.vhost_defaultini') == $id)) {
standard_error('cannotdeletehostnamephpconfig', '', true);
}
if ((Settings::Get('system.mod_fcgid') == '1' && Settings::Get('system.mod_fcgid_defaultini') == $id) || (Settings::Get('phpfpm.enabled') == '1' && Settings::Get('phpfpm.defaultini') == $id)) {
standard_error('cannotdeletedefaultphpconfig', '', true);
}
// set php-config to default for all domains using the
// config that is to be deleted
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_DOMAINS . "` SET
`phpsettingid` = '1' WHERE `phpsettingid` = :id
");
Database::pexecute($upd_stmt, array(
'id' => $id
), true, true);
$del_stmt = Database::prepare("
DELETE FROM `" . TABLE_PANEL_PHPCONFIGS . "` WHERE `id` = :id
");
Database::pexecute($del_stmt, array(
'id' => $id
), true, true);
inserttask('1');
$this->logger()->logAction(ADM_ACTION, LOG_INFO, "[API] php setting '" . $result['description'] . "' has been deleted by '" . $this->getUserDetail('loginname') . "'");
return $this->response(200, "successfull", $result);
}
throw new Exception("Not allowed to execute given command.", 403);
}
}

View File

@@ -1,880 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package API
* @since 0.10.0
*
*/
class SubDomains extends ApiCommand implements ResourceEntity
{
/**
* add a new subdomain
*
* @param string $subdomain
* part before domain.tld to create as subdomain
* @param string $domain
* domainname of main-domain
* @param int $alias
* optional, domain-id of a domain that the new domain should be an alias of
* @param string $path
* optional, destination path relative to the customers-homedir, default is customers-homedir
* @param string $url
* optional, overwrites path value with an URL to generate a redirect, alternatively use the path parameter also for URLs
* @param int $openbasedir_path
* optional, either 0 for customers-homedir or 1 for domains-docroot
* @param int $phpsettingid
* optional, php-settings-id, if empty the $domain value is used
* @param int $redirectcode
* optional, redirect-code-id from TABLE_PANEL_REDIRECTCODES
* @param bool $ssl_redirect
* optional, whether to generate a https-redirect or not, default false; requires SSL to be enabled
* @param bool $letsencrypt
* optional, whether to generate a Let's Encrypt certificate for this domain, default false; requires SSL to be enabled
* @param int $hsts_maxage
* optional max-age value for HSTS header, default 0
* @param bool $hsts_sub
* optional whether or not to add subdomains to the HSTS header, default 0
* @param bool $hsts_preload
* optional whether or not to preload HSTS header value, default 0
* @param int $customerid
* required when called as admin, not needed when called as customer
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function add()
{
if ($this->getUserDetail('subdomains_used') < $this->getUserDetail('subdomains') || $this->getUserDetail('subdomains') == '-1') {
// parameters
$subdomain = $this->getParam('subdomain');
$domain = $this->getParam('domain');
// optional parameters
$aliasdomain = $this->getParam('alias', true, 0);
$path = $this->getParam('path', true, '');
$url = $this->getParam('url', true, '');
$openbasedir_path = $this->getParam('openbasedir_path', true, 1);
$phpsettingid = $this->getParam('phpsettingid', true, 0);
$redirectcode = $this->getParam('redirectcode', true, Settings::Get('customredirect.default'));
$isemaildomain = $this->getParam('isemaildomain', true, 0);
if (Settings::Get('system.use_ssl')) {
$ssl_redirect = $this->getBoolParam('ssl_redirect', true, 0);
$letsencrypt = $this->getBoolParam('letsencrypt', true, 0);
$hsts_maxage = $this->getParam('hsts_maxage', true, 0);
$hsts_sub = $this->getBoolParam('hsts_sub', true, 0);
$hsts_preload = $this->getBoolParam('hsts_preload', true, 0);
} else {
$ssl_redirect = 0;
$letsencrypt = 0;
$hsts_maxage = 0;
$hsts_sub = 0;
$hsts_preload = 0;
}
// get needed customer info to reduce the subdomain-usage-counter by one
$customer = $this->getCustomerData('subdomains');
// validation
if (substr($subdomain, 0, 4) == 'xn--') {
standard_error('domain_nopunycode', '', true);
}
$idna_convert = new idna_convert_wrapper();
$subdomain = $idna_convert->encode(preg_replace(array(
'/\:(\d)+$/',
'/^https?\:\/\//'
), '', validate($subdomain, 'subdomain', '', 'subdomainiswrong', array(), true)));
// merge the two parts together
$completedomain = $subdomain . '.' . $domain;
if (Settings::Get('system.validate_domain') && ! validateDomain($completedomain)) {
standard_error(array(
'stringiswrong',
'mydomain'
), '', true);
}
if ($completedomain == Settings::Get('system.hostname')) {
standard_error('admin_domain_emailsystemhostname', '', true);
}
// check whether the domain already exists
$completedomain_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_DOMAINS . "`
WHERE `domain` = :domain
AND `customerid` = :customerid
AND `email_only` = '0'
AND `caneditdomain` = '1'
");
$completedomain_check = Database::pexecute_first($completedomain_stmt, array(
"domain" => $completedomain,
"customerid" => $customer['customerid']
), true, true);
if ($completedomain_check) {
// no exception so far - domain exists
standard_error('domainexistalready', $completedomain, true);
}
// alias domain checked?
if ($aliasdomain != 0) {
// also check ip/port combination to be the same, #176
$aliasdomain_stmt = Database::prepare("
SELECT `d`.`id` FROM `" . TABLE_PANEL_DOMAINS . "` `d` , `" . TABLE_PANEL_CUSTOMERS . "` `c` , `" . TABLE_DOMAINTOIP . "` `dip`
WHERE `d`.`aliasdomain` IS NULL
AND `d`.`id` = :id
AND `c`.`standardsubdomain` <> `d`.`id`
AND `d`.`customerid` = :customerid
AND `c`.`customerid` = `d`.`customerid`
AND `d`.`id` = `dip`.`id_domain`
AND `dip`.`id_ipandports`
IN (SELECT `id_ipandports` FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_domain` = :id )
GROUP BY `d`.`domain`
ORDER BY `d`.`domain` ASC
");
$aliasdomain_check = Database::pexecute_first($aliasdomain_stmt, array(
"id" => $aliasdomain,
"customerid" => $customer['customerid']
), true, true);
if ($aliasdomain_check['id'] != $aliasdomain) {
standard_error('domainisaliasorothercustomer', '', true);
}
triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $this->logger());
}
// validate / correct path/url of domain
$_doredirect = false;
$path = $this->validateDomainDocumentRoot($path, $url, $customer, $completedomain, $_doredirect);
if ($openbasedir_path != 1) {
$openbasedir_path = 0;
}
// get main domain for various checks
$domain_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_DOMAINS . "`
WHERE `domain` = :domain
AND `customerid` = :customerid
AND `parentdomainid` = '0'
AND `email_only` = '0'
AND `caneditdomain` = '1'
");
$domain_check = Database::pexecute_first($domain_stmt, array(
"domain" => $domain,
"customerid" => $customer['customerid']
), true, true);
if (! $domain_check) {
// the given main-domain
standard_error('maindomainnonexist', $domain, true);
} elseif ($subdomain == 'www' && $domain_check['wwwserveralias'] == '1') {
// you cannot add 'www' as subdomain when the maindomain generates a www-alias
standard_error('wwwnotallowed', '', true);
} elseif (strtolower($completedomain_check['domain']) == strtolower($completedomain)) {
// the domain does already exist as main-domain
standard_error('domainexistalready', $completedomain, true);
}
// if allowed, check for 'is email domain'-flag
if ($domain_check['subcanemaildomain'] == '1' || $domain_check['subcanemaildomain'] == '2') {
$isemaildomain = intval($isemaildomain);
} else {
$isemaildomain = $domain_check['subcanemaildomain'] == '3' ? 1 : 0;
}
if ($ssl_redirect != 0) {
// a ssl-redirect only works if there actually is a
// ssl ip/port assigned to the domain
if (domainHasSslIpPort($domain_check['id']) == true) {
$ssl_redirect = '1';
$_doredirect = true;
} else {
standard_error('sslredirectonlypossiblewithsslipport', '', true);
}
}
if ($letsencrypt != 0) {
// let's encrypt only works if there actually is a
// ssl ip/port assigned to the domain
if (domainHasSslIpPort($domain_check['id']) == true) {
$letsencrypt = '1';
} else {
standard_error('letsencryptonlypossiblewithsslipport', '', true);
}
}
// Temporarily deactivate ssl_redirect until Let's Encrypt certificate was generated
if ($ssl_redirect > 0 && $letsencrypt == 1) {
$ssl_redirect = 2;
}
// get the phpsettingid from parentdomain, #107
$phpsid_stmt = Database::prepare("
SELECT `phpsettingid` FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `id` = :id
");
$phpsid_result = Database::pexecute_first($phpsid_stmt, array(
"id" => $domain_check['id']
), true, true);
if (! isset($phpsid_result['phpsettingid']) || (int) $phpsid_result['phpsettingid'] <= 0) {
// assign default config
$phpsid_result['phpsettingid'] = 1;
}
// check whether the customer has chosen its own php-config
if ($phpsettingid > 0 && $phpsettingid != $phpsid_result['phpsettingid']) {
$phpsid_result['phpsettingid'] = intval($phpsettingid);
}
// acutall insert domain
$stmt = Database::prepare("
INSERT INTO `" . TABLE_PANEL_DOMAINS . "` SET
`customerid` = :customerid,
`adminid` = :adminid,
`domain` = :domain,
`documentroot` = :documentroot,
`aliasdomain` = :aliasdomain,
`parentdomainid` = :parentdomainid,
`wwwserveralias` = :wwwserveralias,
`isemaildomain` = :isemaildomain,
`iswildcarddomain` = :iswildcarddomain,
`phpenabled` = :phpenabled,
`openbasedir` = :openbasedir,
`openbasedir_path` = :openbasedir_path,
`speciallogfile` = :speciallogfile,
`specialsettings` = :specialsettings,
`ssl_redirect` = :ssl_redirect,
`phpsettingid` = :phpsettingid,
`letsencrypt` = :letsencrypt,
`hsts` = :hsts,
`hsts_sub` = :hsts_sub,
`hsts_preload` = :hsts_preload
");
$params = array(
"customerid" => $customer['customerid'],
"adminid" => $customer['adminid'],
"domain" => $completedomain,
"documentroot" => $path,
"aliasdomain" => $aliasdomain != 0 ? $aliasdomain : null,
"parentdomainid" => $domain_check['id'],
"wwwserveralias" => $domain_check['wwwserveralias'] == '1' ? '1' : '0',
"iswildcarddomain" => $domain_check['iswildcarddomain'] == '1' ? '1' : '0',
"isemaildomain" => $isemaildomain,
"openbasedir" => $domain_check['openbasedir'],
"openbasedir_path" => $openbasedir_path,
"phpenabled" => $domain_check['phpenabled'],
"speciallogfile" => $domain_check['speciallogfile'],
"specialsettings" => $domain_check['specialsettings'],
"ssl_redirect" => $ssl_redirect,
"phpsettingid" => $phpsid_result['phpsettingid'],
"letsencrypt" => $letsencrypt,
"hsts" => $hsts_maxage,
"hsts_sub" => $hsts_sub,
"hsts_preload" => $hsts_preload
);
Database::pexecute($stmt, $params, true, true);
$subdomain_id = Database::lastInsertId();
$stmt = Database::prepare("
INSERT INTO `" . TABLE_DOMAINTOIP . "`
(`id_domain`, `id_ipandports`)
SELECT LAST_INSERT_ID(), `id_ipandports`
FROM `" . TABLE_DOMAINTOIP . "`
WHERE `id_domain` = :id_domain
");
Database::pexecute($stmt, array(
"id_domain" => $domain_check['id']
));
if ($_doredirect) {
addRedirectToDomain($subdomain_id, $redirectcode);
}
inserttask('1');
// Using nameserver, insert a task which rebuilds the server config
inserttask('4');
Customers::increaseUsage($customer['customerid'], 'subdomains_used');
Admins::increaseUsage(($this->isAdmin() ? $customer['adminid'] : $this->getUserDetail('adminid')), 'subdomains_used');
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_INFO, "[API] added subdomain '" . $completedomain . "'");
$result = $this->apiCall('SubDomains.get', array(
'id' => $subdomain_id
));
return $this->response(200, "successfull", $result);
}
throw new Exception("No more resources available", 406);
}
/**
* return a subdomain entry by either id or domainname
*
* @param int $id
* optional, the domain-id
* @param string $domainname
* optional, the domainname
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function get()
{
$id = $this->getParam('id', true, 0);
$dn_optional = ($id <= 0 ? false : true);
$domainname = $this->getParam('domainname', $dn_optional, '');
// convert possible idn domain to punycode
if (substr($domainname, 0, 4) != 'xn--') {
$idna_convert = new idna_convert_wrapper();
$domainname = $idna_convert->encode($domainname);
}
if ($this->isAdmin()) {
if ($this->getUserDetail('customers_see_all') != 1) {
// if it's a reseller or an admin who cannot see all customers, we need to check
// whether the database belongs to one of his customers
$_custom_list_result = $this->apiCall('Customers.listing');
$custom_list_result = $_custom_list_result['list'];
$customer_ids = array();
foreach ($custom_list_result as $customer) {
$customer_ids[] = $customer['customerid'];
}
if (count($customer_ids) > 0) {
$result_stmt = Database::prepare("
SELECT d.*, pd.`subcanemaildomain`, pd.`isbinddomain` as subisbinddomain
FROM `" . TABLE_PANEL_DOMAINS . "` d, `" . TABLE_PANEL_DOMAINS . "` pd
WHERE " . ($id > 0 ? "d.`id` = :iddn" : "d.`domain` = :iddn") . " AND d.`customerid` IN (" . implode(", ", $customer_ids) . ")
AND ((d.`parentdomainid`!='0' AND pd.`id` = d.`parentdomainid`) OR (d.`parentdomainid`='0' AND pd.`id` = d.`id`))
");
$params = array(
'iddn' => ($id <= 0 ? $domainname : $id)
);
} else {
throw new Exception("You do not have any customers yet", 406);
}
} else {
$result_stmt = Database::prepare("
SELECT d.*, pd.`subcanemaildomain`, pd.`isbinddomain` as subisbinddomain
FROM `" . TABLE_PANEL_DOMAINS . "` d, `" . TABLE_PANEL_DOMAINS . "` pd
WHERE " . ($id > 0 ? "d.`id` = :iddn" : "d.`domain` = :iddn") . "
AND ((d.`parentdomainid`!='0' AND pd.`id` = d.`parentdomainid`) OR (d.`parentdomainid`='0' AND pd.`id` = d.`id`))
");
$params = array(
'iddn' => ($id <= 0 ? $domainname : $id)
);
}
} else {
if (Settings::IsInList('panel.customer_hide_options', 'domains')) {
throw new Exception("You cannot access this resource", 405);
}
$result_stmt = Database::prepare("
SELECT d.*, pd.`subcanemaildomain`, pd.`isbinddomain` as subisbinddomain
FROM `" . TABLE_PANEL_DOMAINS . "` d, `" . TABLE_PANEL_DOMAINS . "` pd
WHERE d.`customerid`= :customerid AND " . ($id > 0 ? "d.`id` = :iddn" : "d.`domain` = :iddn") . "
AND ((d.`parentdomainid`!='0' AND pd.`id` = d.`parentdomainid`) OR (d.`parentdomainid`='0' AND pd.`id` = d.`id`))
");
$params = array(
'customerid' => $this->getUserDetail('customerid'),
'iddn' => ($id <= 0 ? $domainname : $id)
);
}
$result = Database::pexecute_first($result_stmt, $params, true, true);
if ($result) {
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_NOTICE, "[API] get subdomain '" . $result['domain'] . "'");
return $this->response(200, "successfull", $result);
}
$key = ($id > 0 ? "id #" . $id : "domainname '" . $domainname . "'");
throw new Exception("Subdomain with " . $key . " could not be found", 404);
}
/**
* update subdomain entry by either id or domainname
*
* @param int $id
* optional, the domain-id
* @param string $domainname
* optional, the domainname
* @param int $alias
* optional, domain-id of a domain that the new domain should be an alias of
* @param string $path
* optional, destination path relative to the customers-homedir, default is customers-homedir
* @param string $url
* optional, overwrites path value with an URL to generate a redirect, alternatively use the path parameter also for URLs
* @param int $selectserveralias
* optional, 0 = wildcard, 1 = www-alias, 2 = none
* @param bool $isemaildomain
* optional
* @param int $openbasedir_path
* optional, either 0 for customers-homedir or 1 for domains-docroot
* @param int $phpsettingid
* optional, php-settings-id, if empty the $domain value is used
* @param int $redirectcode
* optional, redirect-code-id from TABLE_PANEL_REDIRECTCODES
* @param bool $ssl_redirect
* optional, whether to generate a https-redirect or not, default false; requires SSL to be enabled
* @param bool $letsencrypt
* optional, whether to generate a Let's Encrypt certificate for this domain, default false; requires SSL to be enabled
* @param int $hsts_maxage
* optional max-age value for HSTS header
* @param bool $hsts_sub
* optional whether or not to add subdomains to the HSTS header
* @param bool $hsts_preload
* optional whether or not to preload HSTS header value
* @param int $customerid
* required when called as admin, not needed when called as customer
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function update()
{
$id = $this->getParam('id', true, 0);
$dn_optional = ($id <= 0 ? false : true);
$domainname = $this->getParam('domainname', $dn_optional, '');
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'domains')) {
throw new Exception("You cannot access this resource", 405);
}
$result = $this->apiCall('SubDomains.get', array(
'id' => $id,
'domainname' => $domainname
));
$id = $result['id'];
// parameters
$aliasdomain = $this->getParam('alias', true, 0);
$path = $this->getParam('path', true, $result['documentroot']);
$url = $this->getParam('url', true, '');
// default: 0 = wildcard, 1 = www-alias, 2 = none
$_serveraliasdefault = $result['iswildcarddomain'] == '1' ? 0 : ($result['wwwserveralias'] == '1' ? 1 : 2);
$selectserveralias = $this->getParam('selectserveralias', true, $_serveraliasdefault);
$isemaildomain = $this->getBoolParam('isemaildomain', true, $result['isemaildomain']);
$openbasedir_path = $this->getParam('openbasedir_path', true, $result['openbasedir_path']);
$phpsettingid = $this->getParam('phpsettingid', true, $result['phpsettingid']);
$redirectcode = $this->getParam('redirectcode', true, getDomainRedirectId($id));
if (Settings::Get('system.use_ssl')) {
$ssl_redirect = $this->getBoolParam('ssl_redirect', true, $result['ssl_redirect']);
$letsencrypt = $this->getBoolParam('letsencrypt', true, $result['letsencrypt']);
$hsts_maxage = $this->getParam('hsts_maxage', true, $result['hsts']);
$hsts_sub = $this->getBoolParam('hsts_sub', true, $result['hsts_sub']);
$hsts_preload = $this->getBoolParam('hsts_preload', true, $result['hsts_preload']);
} else {
$ssl_redirect = 0;
$letsencrypt = 0;
$hsts_maxage = 0;
$hsts_sub = 0;
$hsts_preload = 0;
}
// get needed customer info to reduce the subdomain-usage-counter by one
$customer = $this->getCustomerData();
$alias_stmt = Database::prepare("SELECT COUNT(`id`) AS count FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `aliasdomain`= :aliasdomain");
$alias_check = Database::pexecute_first($alias_stmt, array(
"aliasdomain" => $result['id']
));
$alias_check = $alias_check['count'];
// alias domain checked?
if ($aliasdomain != 0) {
$aliasdomain_stmt = Database::prepare("
SELECT `id` FROM `" . TABLE_PANEL_DOMAINS . "` `d`,`" . TABLE_PANEL_CUSTOMERS . "` `c`
WHERE `d`.`customerid`= :customerid
AND `d`.`aliasdomain` IS NULL
AND `d`.`id`<>`c`.`standardsubdomain`
AND `c`.`customerid`= :customerid
AND `d`.`id`= :id
");
$aliasdomain_check = Database::pexecute_first($aliasdomain_stmt, array(
"id" => $aliasdomain,
"customerid" => $customer['customerid']
), true, true);
if ($aliasdomain_check['id'] != $aliasdomain) {
standard_error('domainisaliasorothercustomer', '', true);
}
triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $this->logger());
}
// validate / correct path/url of domain
$_doredirect = false;
$path = $this->validateDomainDocumentRoot($path, $url, $customer, $result['domain'], $_doredirect);
// set alias-fields according to selected alias mode
$iswildcarddomain = ($selectserveralias == '0') ? '1' : '0';
$wwwserveralias = ($selectserveralias == '1') ? '1' : '0';
// if allowed, check for 'is email domain'-flag
if ($result['parentdomainid'] != '0' && ($result['subcanemaildomain'] == '1' || $result['subcanemaildomain'] == '2') && $isemaildomain != $result['isemaildomain']) {
$isemaildomain = intval($isemaildomain);
} elseif ($result['parentdomainid'] != '0') {
$isemaildomain = $result['subcanemaildomain'] == '3' ? 1 : 0;
}
// check changes of openbasedir-path variable
if ($openbasedir_path != 1) {
$openbasedir_path = 0;
}
if ($ssl_redirect != 0) {
// a ssl-redirect only works if there actually is a
// ssl ip/port assigned to the domain
if (domainHasSslIpPort($result['id']) == true) {
$ssl_redirect = '1';
$_doredirect = true;
} else {
standard_error('sslredirectonlypossiblewithsslipport', '', true);
}
}
if ($letsencrypt != 0) {
// let's encrypt only works if there actually is a
// ssl ip/port assigned to the domain
if (domainHasSslIpPort($result['id']) == true) {
$letsencrypt = '1';
} else {
standard_error('letsencryptonlypossiblewithsslipport', '', true);
}
}
// We can't enable let's encrypt for wildcard - domains when using acme-v1
if ($iswildcarddomain == '1' && $letsencrypt == '1' && Settings::Get('system.leapiversion') == '1') {
standard_error('nowildcardwithletsencrypt');
}
// if using acme-v2 we cannot issue wildcard-certificates
// because they currently only support the dns-01 challenge
if ($iswildcarddomain == '0' && $letsencrypt == '1' && Settings::Get('system.leapiversion') == '2') {
standard_error('nowildcardwithletsencryptv2');
}
// Temporarily deactivate ssl_redirect until Let's Encrypt certificate was generated
if ($ssl_redirect > 0 && $letsencrypt == 1 && $result['letsencrypt'] != $letsencrypt) {
$ssl_redirect = 2;
}
// is-email-domain flag changed - remove mail accounts and mail-addresses
if (($result['isemaildomain'] == '1') && $isemaildomain == '0') {
$params = array(
"customerid" => $customer['customerid'],
"domainid" => $id
);
$stmt = Database::prepare("DELETE FROM `" . TABLE_MAIL_USERS . "` WHERE `customerid`= :customerid AND `domainid`= :domainid");
Database::pexecute($stmt, $params, true, true);
$stmt = Database::prepare("DELETE FROM `" . TABLE_MAIL_VIRTUAL . "` WHERE `customerid`= :customerid AND `domainid`= :domainid");
Database::pexecute($stmt, $params, true, true);
$idna_convert = new idna_convert_wrapper();
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_NOTICE, "[API] automatically deleted mail-table entries for '" . $idna_convert->decode($result['domain']) . "'");
}
// handle redirect
if ($_doredirect) {
updateRedirectOfDomain($id, $redirectcode);
}
if ($path != $result['documentroot'] || $isemaildomain != $result['isemaildomain'] || $wwwserveralias != $result['wwwserveralias'] || $iswildcarddomain != $result['iswildcarddomain'] || $aliasdomain != $result['aliasdomain'] || $openbasedir_path != $result['openbasedir_path'] || $ssl_redirect != $result['ssl_redirect'] || $letsencrypt != $result['letsencrypt'] || $hsts_maxage != $result['hsts'] || $hsts_sub != $result['hsts_sub'] || $hsts_preload != $result['hsts_preload'] || $phpsettingid != $result['phpsettingid']) {
$stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_DOMAINS . "` SET
`documentroot`= :documentroot,
`isemaildomain`= :isemaildomain,
`wwwserveralias`= :wwwserveralias,
`iswildcarddomain`= :iswildcarddomain,
`aliasdomain`= :aliasdomain,
`openbasedir_path`= :openbasedir_path,
`ssl_redirect`= :ssl_redirect,
`letsencrypt`= :letsencrypt,
`hsts` = :hsts,
`hsts_sub` = :hsts_sub,
`hsts_preload` = :hsts_preload,
`phpsettingid` = :phpsettingid
WHERE `customerid`= :customerid AND `id`= :id
");
$params = array(
"documentroot" => $path,
"isemaildomain" => $isemaildomain,
"wwwserveralias" => $wwwserveralias,
"iswildcarddomain" => $iswildcarddomain,
"aliasdomain" => ($aliasdomain != 0 && $alias_check == 0) ? $aliasdomain : null,
"openbasedir_path" => $openbasedir_path,
"ssl_redirect" => $ssl_redirect,
"letsencrypt" => $letsencrypt,
"hsts" => $hsts_maxage,
"hsts_sub" => $hsts_sub,
"hsts_preload" => $hsts_preload,
"phpsettingid" => $phpsettingid,
"customerid" => $customer['customerid'],
"id" => $id
);
Database::pexecute($stmt, $params, true, true);
if ($result['aliasdomain'] != $aliasdomain) {
// trigger when domain id for alias destination has changed: both for old and new destination
triggerLetsEncryptCSRForAliasDestinationDomain($result['aliasdomain'], $this->logger());
triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $this->logger());
} elseif ($result['wwwserveralias'] != $wwwserveralias || $result['letsencrypt'] != $letsencrypt) {
// or when wwwserveralias or letsencrypt was changed
triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $this->logger());
}
// check whether LE has been disabled, so we remove the certificate
if ($letsencrypt == '0' && $result['letsencrypt'] == '1') {
$del_stmt = Database::prepare("
DELETE FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` WHERE `domainid` = :id
");
Database::pexecute($del_stmt, array(
'id' => $id
), true, true);
}
inserttask('1');
inserttask('4');
$idna_convert = new idna_convert_wrapper();
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_INFO, "[API] edited domain '" . $idna_convert->decode($result['domain']) . "'");
}
$result = $this->apiCall('SubDomains.get', array(
'id' => $id
));
return $this->response(200, "successfull", $result);
}
/**
* lists all subdomain entries
*
* @access admin, customer
* @throws Exception
* @return array count|list
*/
public function listing()
{
if ($this->isAdmin()) {
// if we're an admin, list all databases of all the admins customers
// or optionally for one specific customer identified by id or loginname
$customerid = $this->getParam('customerid', true, 0);
$loginname = $this->getParam('loginname', true, '');
if (! empty($customerid) || ! empty($loginname)) {
$result = $this->apiCall('Customers.get', array(
'id' => $customerid,
'loginname' => $loginname
));
$custom_list_result = array(
$result
);
} else {
$_custom_list_result = $this->apiCall('Customers.listing');
$custom_list_result = $_custom_list_result['list'];
}
$customer_ids = array();
$customer_stdsubs = array();
foreach ($custom_list_result as $customer) {
$customer_ids[] = $customer['customerid'];
$customer_stdsubs[$customer['customerid']] = $customer['standardsubdomain'];
}
} else {
if (Settings::IsInList('panel.customer_hide_options', 'domains')) {
throw new Exception("You cannot access this resource", 405);
}
$customer_ids = array(
$this->getUserDetail('customerid')
);
$customer_stdsubs = array(
$this->getUserDetail('customerid') => $this->getUserDetail('standardsubdomain')
);
}
// prepare select statement
$domains_stmt = Database::prepare("
SELECT `d`.`id`, `d`.`customerid`, `d`.`domain`, `d`.`documentroot`, `d`.`isbinddomain`, `d`.`isemaildomain`, `d`.`caneditdomain`, `d`.`iswildcarddomain`, `d`.`parentdomainid`, `d`.`letsencrypt`, `d`.`termination_date`, `ad`.`id` AS `aliasdomainid`, `ad`.`domain` AS `aliasdomain`, `da`.`id` AS `domainaliasid`, `da`.`domain` AS `domainalias`
FROM `" . TABLE_PANEL_DOMAINS . "` `d`
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `ad` ON `d`.`aliasdomain`=`ad`.`id`
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `da` ON `da`.`aliasdomain`=`d`.`id`
WHERE `d`.`customerid`= :customerid
AND `d`.`email_only`='0'
AND `d`.`id` <> :standardsubdomain
");
$result = array();
foreach ($customer_ids as $customer_id) {
Database::pexecute($domains_stmt, array(
"customerid" => $customer_id,
"standardsubdomain" => $customer_stdsubs[$customer_id]
), true, true);
while ($row = $domains_stmt->fetch(PDO::FETCH_ASSOC)) {
$result[] = $row;
}
}
return $this->response(200, "successfull", array(
'count' => count($result),
'list' => $result
));
}
/**
* delete a subdomain by either id or domainname
*
* @param int $id
* optional, the domain-id
* @param string $domainname
* optional, the domainname
*
* @access admin, customer
* @throws Exception
* @return array
*/
public function delete()
{
$id = $this->getParam('id', true, 0);
$dn_optional = ($id <= 0 ? false : true);
$domainname = $this->getParam('domainname', $dn_optional, '');
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'domains')) {
throw new Exception("You cannot access this resource", 405);
}
$result = $this->apiCall('SubDomains.get', array(
'id' => $id,
'domainname' => $domainname
));
$id = $result['id'];
// get needed customer info to reduce the subdomain-usage-counter by one
$customer = $this->getCustomerData();
if (! $this->isAdmin() && $result['caneditdomain'] == 0) {
throw new Exception("You cannot edit this resource", 405);
}
if ($result['isemaildomain'] == '1') {
// check for e-mail addresses
$emails_stmt = Database::prepare("
SELECT COUNT(`id`) AS `count` FROM `" . TABLE_MAIL_VIRTUAL . "`
WHERE `customerid` = :customerid AND `domainid` = :domainid
");
$emails = Database::pexecute_first($emails_stmt, array(
"customerid" => $customer['customerid'],
"domainid" => $id
), true, true);
if ($emails['count'] != '0') {
standard_error('domains_cantdeletedomainwithemail', '', true);
}
}
triggerLetsEncryptCSRForAliasDestinationDomain($result['aliasdomain'], $this->logger());
// delete domain from table
$stmt = Database::prepare("
DELETE FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `customerid` = :customerid AND `id` = :id
");
Database::pexecute($stmt, array(
"customerid" => $customer['customerid'],
"id" => $id
), true, true);
// remove connections to ips and domainredirects
$del_stmt = Database::prepare("
DELETE FROM `" . TABLE_DOMAINTOIP . "`
WHERE `id_domain` = :domainid
");
Database::pexecute($del_stmt, array(
'domainid' => $id
), true, true);
// remove redirect-codes
$del_stmt = Database::prepare("
DELETE FROM `" . TABLE_PANEL_DOMAINREDIRECTS . "`
WHERE `did` = :domainid
");
Database::pexecute($del_stmt, array(
'domainid' => $id
), true, true);
// remove certificate from domain_ssl_settings, fixes #1596
$del_stmt = Database::prepare("
DELETE FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "`
WHERE `domainid` = :domainid
");
Database::pexecute($del_stmt, array(
'domainid' => $id
), true, true);
// remove possible existing DNS entries
$del_stmt = Database::prepare("
DELETE FROM `" . TABLE_DOMAIN_DNS . "`
WHERE `domain_id` = :domainid
");
Database::pexecute($del_stmt, array(
'domainid' => $id
), true, true);
inserttask('1');
// Using nameserver, insert a task which rebuilds the server config
inserttask('4');
// remove domains DNS from powerDNS if used, #581
inserttask('11', $result['domain']);
// reduce subdomain-usage-counter
Customers::decreaseUsage($customer['customerid'], 'subdomains_used');
// update admin usage
Admins::decreaseUsage(($this->isAdmin() ? $customer['adminid'] : $this->getUserDetail('adminid')), 'subdomains_used');
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_WARNING, "[API] deleted subdomain '" . $result['domain'] . "'");
return $this->response(200, "successfull", $result);
}
/**
* validate given path and replace with url if given and valid
*
* @param string $path
* @param string $url
* @param array $customer
* @param string $completedomain
* @param boolean $_doredirect
*
* @return string validated path
* @throws Exception
*/
private function validateDomainDocumentRoot($path = null, $url = null, $customer = null, $completedomain = null, &$_doredirect = false)
{
// check whether an URL was specified
$_doredirect = false;
if (! empty($url) && validateUrl($url)) {
$path = $url;
$_doredirect = true;
} else {
$path = validate($path, 'path', '', '', array(), true);
}
// check whether path is a real path
if (! preg_match('/^https?\:\/\//', $path) || ! validateUrl($path)) {
if (strstr($path, ":") !== false) {
standard_error('pathmaynotcontaincolon', '', true);
}
// If path is empty or '/' and 'Use domain name as default value for DocumentRoot path' is enabled in settings,
// set default path to subdomain or domain name
if ((($path == '') || ($path == '/')) && Settings::Get('system.documentroot_use_default_value') == 1) {
$path = makeCorrectDir($customer['documentroot'] . '/' . $completedomain);
} else {
$path = makeCorrectDir($customer['documentroot'] . '/' . $path);
}
} else {
// no it's not, create a redirect
$_doredirect = true;
}
return $path;
}
}

View File

@@ -1,125 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package API
* @since 0.10.0
*
*/
class Traffic extends ApiCommand implements ResourceEntity
{
/**
* You cannot add traffic data
*
* @throws Exception
*/
public function add()
{
throw new Exception('You cannot add traffic data', 303);
}
/**
* to get specific traffic details use year, month and/or day parameter for Traffic.listing()
*
* @throws Exception
*/
public function get()
{
throw new Exception('To get specific traffic details use year, month and/or day parameter for Traffic.listing()', 303);
}
/**
* You cannot update traffic data
*
* @throws Exception
*/
public function update()
{
throw new Exception('You cannot update traffic data', 303);
}
/**
* list traffic information
*
* @param int $year
* optional, default empty
* @param int $month
* optional, default empty
* @param int $day
* optional, default empty
* @param bool $customer_traffic
* optional, admin-only, whether to output ones own traffic or all of ones customers, default is 0 (false)
* @param int $customerid
* optional, admin-only, select traffic of a specific customer by id
* @param string $loginname
* optional, admin-only, select traffic of a specific customer by loginname
*
* @access admin, customer
* @throws Exception
* @return array count|list
*/
public function listing()
{
$year = $this->getParam('year', true, "");
$month = $this->getParam('month', true, "");
$day = $this->getParam('day', true, "");
$customer_traffic = $this->getBoolParam('customer_traffic', true, 0);
$customer_ids = $this->getAllowedCustomerIds();
$result = array();
$params = array();
// check for year/month/day
$where_str = "";
if (! empty($year) && is_numeric($year)) {
$where_str .= " AND `year` = :year";
$params['year'] = $year;
}
if (! empty($month) && is_numeric($month)) {
$where_str .= " AND `month` = :month";
$params['month'] = $month;
}
if (! empty($day) && is_numeric($day)) {
$where_str .= " AND `day` = :day";
$params['day'] = $day;
}
if (! $this->isAdmin() || ($this->isAdmin() && $customer_traffic)) {
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_TRAFFIC . "`
WHERE `customerid` IN (".implode(", ", $customer_ids).")" . $where_str);
} else {
$params['adminid'] = $this->getUserDetail('adminid');
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_TRAFFIC_ADMINS . "`
WHERE `adminid` = :adminid" . $where_str);
}
Database::pexecute($result_stmt, $params, true, true);
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
$result[] = $row;
}
$this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_NOTICE, "[API] list traffic");
return $this->response(200, "successfull", array(
'count' => count($result),
'list' => $result
));
}
/**
* You cannot delete traffic data
*
* @throws Exception
*/
public function delete()
{
throw new Exception('You cannot delete traffic data', 303);
}
}

View File

@@ -1,30 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package API
* @since 0.10.0
*
*/
interface ResourceEntity
{
public function listing();
public function get();
public function add();
public function update();
public function delete();
}

View File

@@ -1,62 +0,0 @@
<?php
class HttpClient
{
/**
* Executes simple GET request
*
* @param string $url
*
* @return array
*/
public static function urlGet($url, $follow_location = true)
{
include FROXLOR_INSTALL_DIR . '/lib/version.inc.php';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_USERAGENT, 'Froxlor/' . $version);
if ($follow_location) {
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
}
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
if ($output === false) {
$e = curl_error($ch);
curl_close($ch);
throw new \Exception("Curl error: " . $e);
}
curl_close($ch);
return $output;
}
/**
* Downloads and stores a file from an url
*
* @param string $url
* @param string $target
*
* @return array
*/
public static function fileGet($url, $target)
{
include FROXLOR_INSTALL_DIR . '/lib/version.inc.php';
$fh = fopen($target, 'w');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_USERAGENT, 'Froxlor/' . $version);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 50);
//give curl the file pointer so that it can write to it
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FILE, $fh);
$output = curl_exec($ch);
if ($output === false) {
$e = curl_error($ch);
curl_close($ch);
throw new \Exception("Curl error: " . $e);
}
curl_close($ch);
return $output;
}
}

View File

@@ -1,129 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2018 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Michael Kaufmann <d00p@froxlor.org>
* @author Froxlor team <team@froxlor.org> (2018-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Classes
*
* @since 0.9.39
*
*/
/**
* Class SImExporter
*
* Import/Export settings to JSON
*
* @copyright (c) the authors
* @author Michael Kaufmann <d00p@froxlor.org>
* @author Froxlor team <team@froxlor.org> (2018-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Classes
*/
class SImExporter
{
/**
* settings which are not being exported
*
* @var array
*/
private static $_no_export = [
'panel.adminmail',
'admin.show_news_feed',
'system.lastaccountnumber',
'system.lastguid',
'system.ipaddress',
'system.last_traffic_run',
'system.hostname',
'system.mysql_access_host',
'system.lastcronrun',
'system.defaultip',
'system.defaultsslip'.
'system.last_tasks_run',
'system.last_archive_run',
'system.leprivatekey',
'system.lepublickey'
];
public static function export()
{
$result_stmt = Database::query("
SELECT * FROM `" . TABLE_PANEL_SETTINGS . "` ORDER BY `settingid` ASC
");
$_data = array();
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
$index = $row['settinggroup'] . "." . $row['varname'];
if (! in_array($index, self::$_no_export)) {
$_data[$index] = $row['value'];
}
}
// add checksum for validation
$_data['_sha'] = sha1(var_export($_data, true));
$_export = json_encode($_data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
if (! $_export) {
throw new Exception("Error exporting settings: " . json_last_error_msg());
}
return $_export;
}
public static function import($json_str = null)
{
// decode data
$_data = json_decode($json_str, true);
if ($_data) {
// get validity check data
$_sha = isset($_data['_sha']) ? $_data['_sha'] : false;
$_version = isset($_data['panel.version']) ? $_data['panel.version'] : false;
$_dbversion = isset($_data['panel.db_version']) ? $_data['panel.db_version'] : false;
// check if we have everything we need
if (! $_sha || ! $_version || ! $_dbversion) {
throw new Exception("Invalid froxlor settings data. Unable to import.");
}
// validate import file
unset($_data['_sha']);
// compare
if ($_sha != sha1(var_export($_data, true))) {
throw new Exception("SHA check of import data failed. Unable to import.");
}
// do not import version info - but we need that to possibily update settings
// when there were changes in the variable-name or similar
unset($_data['panel.version']);
unset($_data['panel.db_version']);
// validate we got ssl enabled ips when ssl is enabled
// otherwise deactivate it
if ($_data['system.use_ssl'] == 1) {
$result_ssl_ipsandports_stmt = Database::prepare("
SELECT COUNT(*) as count_ssl_ip FROM `" . TABLE_PANEL_IPSANDPORTS . "` WHERE `ssl`='1'
");
$result = Database::pexecute_first($result_ssl_ipsandports_stmt);
if ($result['count_ssl_ip'] <= 0) {
// no ssl-ip -> deactivate
$_data['system.use_ssl'] = 0;
// deactivate other ssl-related settings
$_data['system.leenabled'] = 0;
$_data['system.le_froxlor_enabled'] = 0;
$_data['system.le_froxlor_redirect'] = 0;
}
}
// store new data
foreach ($_data as $index => $value) {
Settings::Set($index, $value);
}
// save to DB
Settings::Flush();
// all good
return true;
}
throw new Exception("Invalid JSON data: " . json_last_error_msg());
}
}