diff --git a/customer_extras.php b/customer_extras.php index 104d4b2c..0124b9b8 100644 --- a/customer_extras.php +++ b/customer_extras.php @@ -223,42 +223,22 @@ if ($page == 'overview') { eval("echo \"" . getTemplate("extras/htaccess") . "\";"); } elseif ($action == 'delete' && $id != 0) { - $result_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_HTACCESS . "` - WHERE `customerid` = :customerid - AND `id` = :id"); - Database::pexecute($result_stmt, array( - "customerid" => $userinfo['customerid'], - "id" => $id - )); - $result = $result_stmt->fetch(PDO::FETCH_ASSOC); + try { + $json_result = DirOptions::getLocal($userinfo, array( + 'id' => $id + ))->get(); + } catch (Exception $e) { + dynamic_error($e->getMessage()); + } + $result = json_decode($json_result, true)['data']; if (isset($result['customerid']) && $result['customerid'] != '' && $result['customerid'] == $userinfo['customerid']) { if (isset($_POST['send']) && $_POST['send'] == 'send') { - // do we have to remove the symlink and folder in suexecpath? - if ((int) Settings::Get('perl.suexecworkaround') == 1) { - $loginname = getCustomerDetail($result['customerid'], '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)); - $log->logAction(USR_ACTION, LOG_DEBUG, "deleted suexecworkaround symlink '" . $perlsymlink . "'"); - } - // remove folder in suexec-path - if (file_exists($suexecpath)) { - safe_exec('rm -rf ' . escapeshellarg($suexecpath)); - $log->logAction(USR_ACTION, LOG_DEBUG, "deleted suexecworkaround path '" . $suexecpath . "'"); - } + try { + DirOptions::getLocal($userinfo, $_POST)->delete(); + } catch (Exception $e) { + dynamic_error($e->getMessage()); } - $stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_HTACCESS . "` - WHERE `customerid`= :customerid - AND `id`= :id"); - Database::pexecute($stmt, array( - "customerid" => $userinfo['customerid'], - "id" => $id - )); - $log->logAction(USR_ACTION, LOG_INFO, "deleted htaccess for '" . str_replace($userinfo['documentroot'], '/', $result['path']) . "'"); - inserttask('1'); redirectTo($filename, array( 'page' => $page, 's' => $s @@ -273,74 +253,15 @@ if ($page == 'overview') { } } elseif ($action == 'add') { if (isset($_POST['send']) && $_POST['send'] == 'send') { - $path = makeCorrectDir(validate($_POST['path'], 'path')); - $userpath = $path; - $path = makeCorrectDir($userinfo['documentroot'] . '/' . $path); - $path_dupe_check_stmt = Database::prepare("SELECT `id`, `path` FROM `" . TABLE_PANEL_HTACCESS . "` - WHERE `path`= :path - AND `customerid`= :customerid"); - Database::pexecute($path_dupe_check_stmt, array( - "path" => $path, - "customerid" => $userinfo['customerid'] + try { + DirOptions::getLocal($userinfo, $_POST)->add(); + } catch (Exception $e) { + dynamic_error($e->getMessage()); + } + redirectTo($filename, array( + 'page' => $page, + 's' => $s )); - $path_dupe_check = $path_dupe_check_stmt->fetch(PDO::FETCH_ASSOC); - - if (! $_POST['path']) { - standard_error('invalidpath'); - } - - if (isset($_POST['options_cgi']) && (int) $_POST['options_cgi'] != 0) { - $options_cgi = '1'; - } else { - $options_cgi = '0'; - } - - $error404path = ''; - if (isset($_POST['error404path'])) { - $error404path = correctErrorDocument($_POST['error404path']); - } - - $error403path = ''; - if (isset($_POST['error403path'])) { - $error403path = correctErrorDocument($_POST['error403path']); - } - - $error500path = ''; - if (isset($_POST['error500path'])) { - $error500path = correctErrorDocument($_POST['error500path']); - } - - if ($path_dupe_check['path'] == $path) { - standard_error('errordocpathdupe', $userpath); - } elseif ($path == '') { - standard_error('patherror'); - } else { - $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" => $userinfo['customerid'], - "path" => $path, - "options_indexes" => $_POST['options_indexes'] == '1' ? '1' : '0', - "error403path" => $error403path, - "error404path" => $error404path, - "error500path" => $error500path, - "options_cgi" => $options_cgi - ); - Database::pexecute($stmt, $params); - - $log->logAction(USR_ACTION, LOG_INFO, "added htaccess for '" . $path . "'"); - inserttask('1'); - redirectTo($filename, array( - 'page' => $page, - 's' => $s - )); - } } else { $pathSelect = makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid']); $cperlenabled = customerHasPerlEnabled($userinfo['customerid']); @@ -354,55 +275,22 @@ if ($page == 'overview') { eval("echo \"" . getTemplate("extras/htaccess_add") . "\";"); } } elseif (($action == 'edit') && ($id != 0)) { - $result_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_HTACCESS . "` - WHERE `customerid` = :customerid - AND `id` = :id"); - Database::pexecute($result_stmt, array( - "customerid" => $userinfo['customerid'], - "id" => $id - )); - $result = $result_stmt->fetch(PDO::FETCH_ASSOC); + try { + $json_result = DirOptions::getLocal($userinfo, array( + 'id' => $id + ))->get(); + } catch (Exception $e) { + dynamic_error($e->getMessage()); + } + $result = json_decode($json_result, true)['data']; if ((isset($result['customerid'])) && ($result['customerid'] != '') && ($result['customerid'] == $userinfo['customerid'])) { if (isset($_POST['send']) && $_POST['send'] == 'send') { - $option_indexes = intval($_POST['options_indexes']); - $options_cgi = isset($_POST['options_cgi']) ? intval($_POST['options_cgi']) : 0; - - if ($option_indexes != '1') { - $option_indexes = '0'; + try { + DirOptions::getLocal($userinfo, $_POST)->update(); + } catch (Exception $e) { + dynamic_error($e->getMessage()); } - - if ($options_cgi != '1') { - $options_cgi = '0'; - } - - $error404path = correctErrorDocument($_POST['error404path']); - $error403path = correctErrorDocument($_POST['error403path']); - $error500path = correctErrorDocument($_POST['error500path']); - - if (($option_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" => $userinfo['customerid'], - "options_indexes" => $_POST['options_indexes'] == '1' ? '1' : '0', - "error403path" => $error403path, - "error404path" => $error404path, - "error500path" => $error500path, - "options_cgi" => $options_cgi, - "id" => $id - ); - Database::pexecute($stmt, $params); - $log->logAction(USR_ACTION, LOG_INFO, "edited htaccess for '" . str_replace($userinfo['documentroot'], '/', $result['path']) . "'"); - } - redirectTo($filename, array( 'page' => $page, 's' => $s diff --git a/lib/classes/api/commands/class.DirOptions.php b/lib/classes/api/commands/class.DirOptions.php new file mode 100644 index 00000000..8325f9f9 --- /dev/null +++ b/lib/classes/api/commands/class.DirOptions.php @@ -0,0 +1,357 @@ + (2010-) + * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @package API + * @since 0.10.0 + * + */ +class DirOptions extends ApiCommand implements ResourceEntity +{ + + 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->getParam('options_indexes', true, 0); + $options_cgi = $this->getParam('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 ($options_indexes != 0) { + $options_indexes = '1'; + } else { + $options_indexes = '0'; + } + + if ($options_cgi != 0) { + $options_cgi = '1'; + } else { + $options_cgi = '0'; + } + + 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($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-protection for '" . $username . " (" . $path . ")'"); + inserttask('1'); + + $result = $this->apiCall('DirOptions.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 customer-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); + + $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 (:customerid) + AND `id` = :id + "); + $params['customerid'] = implode(", ", $customer_ids); + } 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); + } + + 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->getParam('options_indexes', true, $result['options_indexes']); + $options_cgi = $this->getParam('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 ($options_indexes != 0) { + $options_indexes = '1'; + } else { + $options_indexes = '0'; + } + + if ($options_cgi != 0) { + $options_cgi = '1'; + } else { + $options_cgi = '0'; + } + + if (! empty($error404path)) { + $error404path = correctErrorDocument($error404path, true); + } + + if (! empty($error403path)) { + $error403path = correctErrorDocument($error403path, true); + } + + if (! empty($error500path)) { + $error500path = correctErrorDocument($error500path, true); + } + + if (($option_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" => $option_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_stmt = Database::prepare(" + SELECT * FROM `" . TABLE_PANEL_HTACCESS . "` + WHERE `customerid` IN (:customerids) + "); + Database::pexecute($result_stmt, array( + "customerids" => implode(', ', $customer_ids) + ), 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 + * optional, the directory-option-id + * + * @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($userinfo['documentroot'], '/', $result['path']) . "'"); + inserttask('1'); + return $this->response(200, "successfull", $result); + } +} diff --git a/lib/classes/api/commands/class.DirProtections.php b/lib/classes/api/commands/class.DirProtections.php index e654cd4b..95a8e1bc 100644 --- a/lib/classes/api/commands/class.DirProtections.php +++ b/lib/classes/api/commands/class.DirProtections.php @@ -271,7 +271,7 @@ class DirProtections extends ApiCommand implements ResourceEntity * delete a directory-protection by either id or username * * @param int $id - * optional, the ftp-user-id + * optional, the directory-protection-id * @param string $username * optional, the username * @@ -293,7 +293,7 @@ class DirProtections extends ApiCommand implements ResourceEntity throw new Exception("You cannot access this resource", 405); } - // get ftp-user + // get directory protection $result = $this->apiCall('DirProtections.get', array( 'id' => $id, 'username' => $username diff --git a/lib/functions/froxlor/function.CorrectErrorDocument.php b/lib/functions/froxlor/function.CorrectErrorDocument.php index 7df4bf37..72c995d4 100644 --- a/lib/functions/froxlor/function.CorrectErrorDocument.php +++ b/lib/functions/froxlor/function.CorrectErrorDocument.php @@ -20,13 +20,14 @@ * refs #267 * * @param string error-document-string + * @param bool $throw_exception * * @return string error-document-string * */ -function correctErrorDocument($errdoc = null) { +function correctErrorDocument($errdoc = null, $throw_exception = false) { - global $idna_convert; + $idna_convert = new idna_convert_wrapper(); if ($errdoc !== null && $errdoc != '') { // not a URL @@ -46,14 +47,14 @@ function correctErrorDocument($errdoc = null) { else { // string won't work for lighty if (Settings::Get('system.webserver') == 'lighttpd') { - standard_error('stringerrordocumentnotvalidforlighty'); + standard_error('stringerrordocumentnotvalidforlighty', '', $throw_exception); } elseif(substr($errdoc, -1) != '"') { $errdoc .= '"'; } } } else { if (Settings::Get('system.webserver') == 'lighttpd') { - standard_error('urlerrordocumentnotvalidforlighty'); + standard_error('urlerrordocumentnotvalidforlighty', '', $throw_exception); } } }