andre 10 сар өмнө
parent
commit
0ed10e195f

+ 1211 - 0
TDHosting.php

@@ -0,0 +1,1211 @@
+<?php
+/**
+ * WHMCS cwp7 Provisioning Module
+ *
+ * Provisioning for User Account on the cwp7 Server
+ *
+ * @see https://centos-webpanel.com/
+ * @copyright Copyright (c) Thurdata GmbH 2022
+ * @license GPL
+ */
+use WHMCS\Database\Capsule;
+
+require_once 'Net/DNS2.php';
+require_once(__DIR__ . '/api/cwp7/Admin.php');
+
+if (!defined('WHMCS')) {
+	die('This file cannot be accessed directly');
+}
+
+/**
+ * Define CWP7 product metadata parameters. 
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/meta-data-params/
+ *
+ * @return array
+ */
+function cwp7_MetaData() {
+    return array(
+        'DisplayName' => 'CentOS Web Panel Provisioning',
+        'APIVersion' => '1.2',
+        'DefaultNonSSLPort' => '2031',
+        'DefaultSSLPort' => '2031',
+        'RequiresServer' => true,
+        'ServiceSingleSignOnLabel' => 'Login to CWP7',
+        'AdminSingleSignOnLabel' => 'Login to CWP7 Admin'
+    );
+}
+
+/**
+ * Test connection to a CWP7 server with the given server parameters.
+ *
+ * Allows an admin user to verify that an API connection can be
+ * successfully made with the given configuration parameters for a
+ * server.
+ *
+ * When defined in a module, a test connection button will appear
+ * alongside the server type dropdown when adding or editing an
+ * existing server.
+ *
+ * @param array $params common module parameters
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/module-parameters/
+ *
+ * @return array
+ */
+function cwp7_Testconnection($params) {
+	$cwp7 = new cwp7_Admin($params['serverhostname'], $params['serveraccesshash']);
+	$response = $cwp7->getServerType();
+	if($response['status'] == 'OK') {
+		return array(
+			'success' => true,
+			'error' => '',
+		);
+	}
+	logModuleCall(
+		'cwp7',
+		__FUNCTION__,
+		$params,
+		'debug',
+		$response
+	);
+	return array(
+        'success' => false,
+        'error' => $response['error_msg'] ? $response['error_msg'] : $response['msj'],
+    );
+}
+
+/**
+ * Define CWP7 product configuration options. 
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/config-options/
+ *
+ * @return array
+ */
+function cwp7_ConfigOptions() {
+    $whmcs = App::self();
+    $serverGroupID = $whmcs->get_req_var('servergroup');
+    $serverIDObj = Capsule::table('tblservergroupsrel')
+        ->select('serverid')
+        ->where('groupid', '=', $serverGroupID)
+		->get();
+	$serverIDs = array();
+	foreach($serverIDObj as $serverID) {
+		array_push($serverIDs, $serverID->serverid);
+	}
+    $server = Capsule::table('tblservers')
+        ->select('hostname', 'accesshash')
+        ->where('id', $serverIDs)
+        ->where('active', '=', 1)
+		->first();
+	$cwp7 = new cwp7_Admin($server->hostname, $server->accesshash);
+	$cwp7Packages = $cwp7->getPackages();
+	if($cwp7Packages['status'] != 'OK') {
+		logModuleCall(
+			'cwp7',
+			__FUNCTION__,
+			$cwp7Packages['status'],
+			'Could not fetch packages',
+			$cwp7Packages['error_msg']
+		);
+		return false;
+	}
+	$cwp7PackageNames = array();
+	foreach($cwp7Packages['msj'] as $cwp7Package) {
+		array_push($cwp7PackageNames, $cwp7Package['package_name']);
+	}
+	$configOptions = array();
+    $configOptions['package'] = array(
+        'FriendlyName' => 'CWP7 Package',
+        'Type' => 'dropdown',
+        'Options' => implode(',', $cwp7PackageNames),
+		'Description' => 'Select CWP7 Package',
+	);
+	$configOptions['inode'] = array( "Type" => "text" , "Description" => "Max of inode", "Default" => "0",);
+	$configOptions['nofile'] = array( "Type" => "text", "Description" => "Max of nofile", "Default" => "100",);
+	$configOptions['nproc'] = array( "Type" => "text" , "Description" => "Nproc limit - 40 suggested", "Default" => "40",);
+	$configOptions['Own Nameserver IP'] = array( "Type" => "text" , "Description" => "Own Name Server IP", "Default" => "185.163.51.142",);
+	return $configOptions;
+}
+
+/**
+ * Provision a new account of a CWP7 server.
+ *
+ * Attempt to provision a new CWP7 account. This is
+ * called any time provisioning is requested inside of WHMCS. Depending upon the
+ * configuration, this can be any of:
+ * * When a new order is placed
+ * * When an invoice for a new order is paid
+ * * Upon manual request by an admin user
+ *
+ * @param array $params common module parameters
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
+ * 
+ * @return string 'success' or an error message
+ */
+function cwp7_CreateAccount($params) {
+	$username = strtolower(substr($params['clientsdetails']['firstname'],0,2) . substr($params['clientsdetails']['lastname'],0,3)) . $params['serviceid'];
+	$userdomain = $username . '.local';
+	try {
+		Capsule::table('tblhosting')
+		->where('id', '=', $params['serviceid'])
+		->update(
+				array(
+				'username'	=> $username,
+				'domain'  	=> $userdomain,
+				)
+		);
+	} catch (\Exception $e) {
+		logModuleCall(
+			'cwp7',
+			__FUNCTION__,
+			$params,
+			'Error: could save username & domain in database',
+			$e->getMessage()
+			);
+		return 'Error: could save username & password in database';
+	}	
+	if ($params["server"] == 1) {
+		$data = array(
+			'package' => $params['configoption1'],
+			'domain' => $userdomain,
+			'user' => $username,
+			'pass' => $params['password'],
+			'email' => $params['clientsdetails']['email'],
+			'inode' => (int) $params["configoption2"],
+            'nofile' => (int) $params["configoption3"],
+            'nproc' => (int) $params["configoption4"],
+            'server_ips'=>$params["serverip"],
+		);
+		$cwp7 = new cwp7_Admin($params['serverhostname'], $params['serveraccesshash']);
+		$response = $cwp7->createAccount($data);
+	}
+	if($response['status'] != 'OK') {
+		return 'Error: ' . $response['error_msg'];
+	}
+	return 'success';
+}
+
+/**
+ * Removes a CWP7 account.
+ *
+ * Called when a termination is requested. This can be invoked automatically for
+ * overdue products if enabled, or requested manually by an admin user.
+ *
+ * @param array $params common module parameters
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
+ *
+ * @return string 'success' or an error message
+ */
+function cwp7_TerminateAccount($params) {
+	$cwp7 = new cwp7_Admin($params['serverhostname'], $params['serveraccesshash']);
+	$response = $cwp7->deleteAccount(array('user' => $params['username'], 'email' => $params['clientsdetails']['email']));
+	if($response['status'] == 'Error') {
+		return 'Error: ' . $response['msj'];
+	}
+	return 'success';
+}
+
+/**
+ * Set a CWP7 account to status inactive.
+ *
+ * Called when a suspension is requested. This is invoked automatically by WHMCS
+ * when a product becomes overdue on payment or can be called manually by admin
+ * user.
+ *
+ * @param array $params common module parameters
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
+ *
+ * @return string 'success' or an error message
+ */
+function cwp7_SuspendAccount($params) {
+	$cwp7 = new cwp7_Admin($params['serverhostname'], $params['serveraccesshash']);
+	$response = $cwp7->suspendAccount($params['username']);
+	if($response['status'] != 'OK') {
+		return 'Error: ' . $response['error_msg'];
+	}
+	return 'success';
+}
+
+/**
+ * Set a CWP7 account to status active.
+ *
+ * Called when an un-suspension is requested. This is invoked
+ * automatically upon payment of an overdue invoice for a product, or
+ * can be called manually by admin user.
+ *
+ * @param array $params common module parameters
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
+ *
+ * @return string 'success' or an error message
+ */
+function cwp7_UnsuspendAccount($params) {
+	$cwp7 = new cwp7_Admin($params['serverhostname'], $params['serveraccesshash']);
+	$response = $cwp7->unsuspendAccount($params['username']);
+	if($response['status'] != 'OK') {
+		return 'Error: ' . $response['error_msg'];
+	}
+	return 'success';
+}
+
+/**
+ * Client area output logic handling.
+ *
+ * This function is used to define module specific client area output. It should
+ * return an array consisting of a template file and optional additional
+ * template variables to make available to that template.
+ *
+ * @param array $params common module parameters
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/client-area-output/
+ *
+ * @return array
+ */
+function cwp7_ClientArea($params) {
+	$clientInfo = array('moduleclientarea' => '1');
+	$cwp7 = new cwp7_Admin($params['serverhostname'], $params['serveraccesshash']);
+	$response = $cwp7->getAutoSSL($params['username']);
+	if($response['status'] == 'OK') {
+		$sslSites = array();
+		foreach($response['msj'] as $sslSite) {
+			$sslSites[$sslSite['ssl']] = array(
+				'auotssl'	=> $sslSite['autossl'],
+				'expire'	=> $sslSite['exp'],
+			);
+		}
+	}
+	$response = $cwp7->getAccount($params['username']);
+	if($response['status'] != 'OK') {
+		logModuleCall(
+			'cwp7',
+			__FUNCTION__,
+			$params,
+			'debug',
+			$response
+		);
+	}
+	if(cwp7CheckLimit($params,'domains')){
+		$clientInfo['domainlimit'] = 1;
+	} else {
+		$clientInfo['domainlimit'] = 0;
+	};
+	if(cwp7CheckLimit($params,'subdomins')){
+		$clientInfo['subdomainlimit'] = 1;
+	} else {
+		$clientInfo['subdomainlimit'] = 0;
+	};
+	$clientInfo['db_max'] = $response['result']['account_info']['db_max'];
+	$clientInfo['db_used'] = $response['result']['account_info']['db_used'];
+	$clientInfo['ftp_accounts'] = $response['result']['account_info']['ftp_accounts'];
+	$clientInfo['ftp_accounts_used'] = $response['result']['account_info']['ftp_accounts_used'];
+	$clientInfo['addons_domains'] = $response['result']['account_info']['addons_domains'];
+	$clientInfo['addons_domains_used'] = $response['result']['account_info']['addons_domains_used'];
+	$clientInfo['sub_domains'] = $response['result']['account_info']['sub_domains'];
+	$clientInfo['sub_domains_used'] = $response['result']['account_info']['sub_domains_used'];
+	$clientInfo['space_usage'] = $response['result']['account_info']['space_usage'];
+	$clientInfo['space_disk'] = $response['result']['account_info']['space_disk'];
+	$clientInfo['bandwidth_used'] = $response['result']['account_info']['bandwidth_used'];
+	$clientInfo['bandwidth'] = $response['result']['account_info']['bandwidth'];
+	$domains = $response['result']['domains'];
+	$subDomains = $response['result']['subdomins'];
+	$clientInfo['domains'] = array();
+	foreach($domains as $domain) {
+		if($domain['path'] == '/home/' . $params['username'] . '/public_html') {
+			$clientInfo['mgmtDomain'] = $domain['domain'];
+			$clientInfo['mgmtEmail'] = $domain['email'];
+		} else {
+			$domain['relpath'] = str_replace('/home/' . $params['username'], '~', $domain['path']);
+			if(array_key_exists($domain['domain'], $sslSites)) {
+				$domain['ssl'] = 1;
+				$domain['sslexpire'] = $sslSites[$domain['domain']]['expire'];
+				$domain['autossl'] = $sslSites[$domain['domain']]['auotssl'];
+			}
+			if(cwp7CheckA($domain['domain'],$params['serverip'],$params['configoption5']) == 1) {
+				$domain['DNS'] = 1;
+			}
+			$domain['domainNS'] = cwp7CheckSOA($domain['domain'],$params['configoption5']);
+			$domain['subdomains'] = array();
+			foreach($subDomains as $subDomain) {
+				if($subDomain['domain'] == $domain['domain']) {
+					$subFQDN = $subDomain['subdomain'] . '.' . $subDomain['domain'];
+					$subDomain['relpath'] = str_replace('/home/' . $params['username'], '~', $subDomain['path']);
+					if(array_key_exists($subFQDN, $sslSites)) {
+						$subDomain['ssl'] = 1;
+						$subDomain['sslexpire'] = $sslSites[$subFQDN]['expire'];
+						$subDomain['autossl'] = $sslSites[$subFQDN]['auotssl'];
+					} else {
+						unset($subDomain['ssl']);
+						unset($subDomain['sslexpire']);
+						unset($subDomain['autossl']);
+					}
+					if(cwp7CheckA($subFQDN,$params['serverip'],$params['configoption5']) == 1) {
+						$subDomain['DNS'] = 1;
+					} else {
+						unset($subDomain['DNS']);
+					}
+				array_push($domain['subdomains'], $subDomain);
+				}
+			}
+			array_push($clientInfo['domains'], $domain);
+		}
+	}
+	return array(
+        'tabOverviewReplacementTemplate' => 'clientarea',
+        'vars' => $clientInfo,
+    );
+}
+
+/**
+ * Perform single sign-on for a CWP7 account.
+ *
+ * When successful, returns a URL to which the user should be redirected.
+ *
+ * @param array $params common module parameters
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/single-sign-on/
+ *
+ * @return array
+ */
+function cwp7_ServiceSingleSignOn($params) {
+	$cwp7 = new cwp7_Admin($params['serverhostname'], $params['serveraccesshash']);
+	$response = $cwp7->getLoginLink($params['username']);
+	if($response['status'] == 'OK') {
+		$link = $response['msj']['details'];
+		$linkautologin = $link[0]['url'];
+		return array(
+			'success' => true,
+			'redirectTo' => $linkautologin,
+		);
+	} else {
+		return array(
+			'success' => false,
+			'redirectTo' => '',
+		);
+	}
+}
+
+/**
+ * Change the password for a CWP7 account.
+ *
+ * Called when a password change is requested. This can occur either due to a
+ * client requesting it via the client area or an admin requesting it from the
+ * admin side.
+ *
+ * This option is only available to client end users when the product is in an
+ * active status.
+ *
+ * @param array $params common module parameters
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
+ *
+ * @return string "success" or an error message
+ */
+function cwp7_ChangePassword($params) {
+	$cwp7 = new cwp7_Admin($params['serverhostname'], $params['serveraccesshash']);
+	$response = $cwp7->changePass(array('user' => $params['username'], 'password' => $params['password']));
+	if($response['status'] != 'OK') {
+		return 'Error: ' . $response['error_msg'];
+	}
+	return 'success';
+}
+
+/**
+ * Upgrade or downgrade a CWP7 account by package.
+ *
+ * Called to apply any change in product assignment or parameters. It
+ * is called to provision upgrade or downgrade orders, as well as being
+ * able to be invoked manually by an admin user.
+ *
+ * This same function is called for upgrades and downgrades of both
+ * products and configurable options.
+ *
+ * @param array $params common module parameters
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
+ *
+ * @return string "success" or an error message
+ */
+function cwp7_ChangePackage($params) {
+	$cwp7 = new cwp7_Admin($params['serverhostname'], $params['serveraccesshash']);
+	$data = array(
+		'user' => $params['username'],
+		'email' => $params['clientsdetails']['email'],
+		'package' => $params['configoption1'],
+		'inode' => (int) $params["configoption2"],
+		'openfiles' => (int) $params["configoption3"],
+		'processes' => (int) $params["configoption4"],
+		'server_ips'=> $params["serverip"],
+	);
+	$response = $cwp7->modifyAccount($data);
+	if($response['status'] != 'OK') {
+		return 'Error: ' . $response['error_msg'];
+	}
+	return 'success';
+}
+
+/**
+ * Usage Update
+ * 
+ * Important: Runs daily per server not per product
+ * Run Manually: /admin/reports.php?report=disk_usage_summary&action=updatestats
+ * @param array $params common module parameters
+ * 
+ * @see https://developers.whmcs.com/provisioning-modules/usage-update/
+ */
+function cwp7_UsageUpdate($params) {
+	$cwp7 = new cwp7_Admin($params['serverhostname'], $params['serveraccesshash']);
+	$response = $cwp7->getAllAccounts();
+	if($response['status'] == 'OK'){
+		$results = $response['msj'];
+		for($i = 0; $i < count($results); $i++){
+			if($results[$i]['diskusage'] == '') { 
+				$diskusage = 0;
+			} else {
+				$diskusage = trim($results[$i]['diskusage']);
+			}
+			if($results[$i]['disklimit'] == '') {
+				$disklimit = 0;
+			} else {
+				$disklimit = trim($results[$i]['disklimit']);
+			}
+			if($results[$i]['bandwidth'] == '') {
+				$bandwidth = 0;
+			} else {
+				$bandwidth  =trim($results[$i]['bandwidth']);
+			}
+			if($results[$i]['bwlimit'] == '') {
+				$bwlimit = 0;
+			} else {
+				$bwlimit = trim($results[$i]['bwlimit']);
+			}
+			$domain = trim($results[$i]['domain']);
+			try {
+				\WHMCS\Database\Capsule::table('tblhosting')
+					->where('server', $params['serverid'])
+					->where('domain', $domain)
+					->update([
+						'diskusage' => $diskusage,
+						'disklimit' => $disklimit,
+						'bwusage' => $bandwidth,
+						'bwlimit' => $bwlimit,
+						'lastupdate' => date('Y-m-d H:i:S'),
+					]);
+			} catch (\Exception $e) {
+				logActivity('ERROR: Unable to update server usage: ' . $e->getMessage());
+			}
+		}
+	}
+}
+
+/**
+ * Additional actions a client user can invoke.
+ *
+ * Define additional actions a client user can perform for an instance of a
+ * product/service.
+ *
+ * Any actions you define here will be automatically displayed in the available
+ * list of actions within the client area.
+ *
+ * @return array
+ */
+function cwp7_ClientAreaCustomButtonArray ($params) {
+	if(cwp7CheckLimit($params, 'domains')) {
+		return array();
+	}
+	return array(
+		'Neue Domain' => 'newDomain',
+	);
+}
+
+/**
+ * Additional actions a client user can invoke.
+ *
+ * Define additional actions a client user is allowed to perform for an instance of a
+ * product/service.
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
+ * 
+ * @return array
+ */
+function cwp7_ClientAreaAllowedFunctions() {
+	return array(
+		"Enable SSL" => "enableSSL",
+		"Renew SSL" => "renewSSL",
+		"Set DNS" => "setDNS",
+		"Unset DNS" => "unsetDNS",
+		"Confirm Enable SSL" => "enableSSLConfirm",
+		"Confirm Renew SSL" => "renewSSLConfirm",
+		"Confirm Set DNS" => "setDNSConfirm",
+		"Confirm Unset DNS" => "unsetDNSConfirm",
+		"Info DNS" => "infoDNS",
+		"Info SSL" => "infoSSL",
+		"Add Domain" => "addDomain",
+		"new Domain" => "newDomain",
+		"Add Subdomain" => "addSubdomain",
+		"New Subdomain" => "newSubdomain",
+		"Confirm Delete Domain" => "delDomainConfirm",
+		"Delete Domain" => "delDomain",
+		"Confirm Delete Subdomain" => "delSubdomainConfirm",
+		"Delete Subdomain" => "delSubdomain",
+  	);
+}
+
+/**
+ * Opens a form to add a new domain.
+ *
+ * @param array $params common module parameters
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
+ *
+ * @return array template information
+ */
+function cwp7_newDomain($params) {
+	return array(
+        'breadcrumb' => array(
+            'clientarea.php?action=productdetails&id=' . $params['serviceid'] . '&modop=custom&a=newDomain' => 'Neue Domain',
+        ),
+        'templatefile' => 'cwp7_add_domain',
+    );
+}
+
+/**
+ * Adds a new domain to a CWP7 account.
+ *
+ * @param array $params common module parameters
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
+ *
+ * @return string "success" or an error message
+ */
+function cwp7_addDomain($params) {
+	if(!filter_var($_POST['d'], FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)){
+		return 'Error: invalid domain name';
+	}
+	if(cwp7CheckLimit($params, 'domains')) {
+		return 'Error: domain limit exceeded';
+	}
+	$vars['user'] = $params['username'];
+	$vars['name'] = $_POST['d'];
+	$vars['type'] = 'domain';
+	$cwp7 = new cwp7_Admin($params['serverhostname'], $params['serveraccesshash']);
+	$response = $cwp7->addDomain($vars);
+	if($response['status'] != 'OK') {
+		return 'Error: ' . $response['error_msg'];
+	}
+	return 'success';
+}
+
+/**
+ * Opens a form to add a new subdomain to a domain.
+ *
+ * @param array $params common module parameters
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
+ *
+ * @return array template information
+ */
+function cwp7_newSubdomain($params) {
+	if(!filter_var($_POST['d'], FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)){
+		return 'Error: invalid domain name';
+	}
+	return array(
+        'breadcrumb' => array(
+            'clientarea.php?action=productdetails&id=' . $params['serviceid'] . '&modop=custom&a=newSubdomain' => 'Neue Subdomain',
+        ),
+		'templatefile' => 'cwp7_add_subdomain',
+		'vars' => array(
+            'domainselected' => $_POST['d'],
+        ),
+    );
+}
+
+/**
+ * Adds a new subdomain to domain of a CWP7 account.
+ *
+ * @param array $params common module parameters
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
+ *
+ * @return string "success" or an error message
+ */
+function cwp7_addSubdomain($params) {
+	if(!filter_var($_POST['d'], FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)){
+		return 'Error: invalid domain name';
+	}
+	if(!filter_var($_POST['s'], FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)){
+		return 'Error: invalid subdomain name';
+	}
+	if($_POST['s'] == 'www') {
+		return 'Error: default Subdomain www wurde bereits automatisch erstellt' ;
+	}
+	if(cwp7CheckLimit($params, 'subdomins')) {
+		return 'Error: subdomain limit exceeded';
+	}
+	$vars['user'] = $params['username'];
+	$vars['name'] = $_POST['s'] . '.' . $_POST['d'];
+	$vars['type'] = 'subdomain';
+	$cwp7 = new cwp7_Admin($params['serverhostname'], $params['serveraccesshash']);
+	$response = $cwp7->addDomain($vars);
+	if($response['status'] != 'OK') {
+		return 'Error: ' . $response['error_msg'];
+	}
+	return 'success';
+}
+
+/**
+ * Opens a form to delete a domain from a CWP7 account.
+ *
+ * @param array $params common module parameters
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
+ *
+ * @return array template information
+ */
+function cwp7_delDomainConfirm($params) {
+	return array(
+		'templatefile' => 'cwp7_del_domain_confirm',
+		'vars' => array(
+			'deldomain' => $_POST['d'],
+		),
+    );
+}
+
+/**
+ * Removes a domain from a CWP7 account.
+ *
+ * @param array $params common module parameters
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
+ *
+ * @return string "success" or an error message
+ */
+function cwp7_delDomain($params) {
+	if(!filter_var($_POST['d'], FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)){
+		return 'Error: invalid domain name';
+	}
+	$cwp7 = new cwp7_Admin($params['serverhostname'], $params['serveraccesshash']);
+	$response = $cwp7->getAccount($params['username']);
+	if($response['status'] != 'OK') {
+		logModuleCall(
+			'cwp7',
+			__FUNCTION__,
+			$params,
+			'debug',
+			$response
+		);
+	}
+	$domains = $response['result']['domains'];
+	$clientdomains = array();
+	foreach($domains as $domain){
+		if($domain['domain'] != $params['domain']) {
+			array_push($clientdomains, $domain['domain']);
+		}
+	}
+	if(!in_array($_POST['d'], $clientdomains)) {
+		logModuleCall(
+			'cwp7',
+			__FUNCTION__,
+			$_POST,
+			'POST DATA VIOLATION',
+			$params
+		);
+		return 'Error: ' . $_POST['d'] . ' not in client domains';
+	}
+	// do delete domain
+	$vars['user'] = $params['username'];
+	$vars['name'] = $_POST['d'];
+	$vars['type'] = 'domain';
+	$response = $cwp7->deleteDomain($vars);
+	if($response['status'] != 'OK') {
+		return 'Error: ' . $response['error_msg'];
+	}
+	return 'success';
+}
+
+/**
+ * Opens a form to delete a subdomain from domain of a CWP7 account.
+ *
+ * @param array $params common module parameters
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
+ *
+ * @return array template information
+ */
+function cwp7_delSubdomainConfirm($params) {
+	return array(
+		'templatefile' => 'cwp7_del_subdomain_confirm',
+		'vars' => array(
+			'delsubdomain' => $_POST['d'],
+		),
+    );
+}
+
+/**
+ * Removes a subdomain from a domain of a CWP7 account.
+ *
+ * @param array $params common module parameters
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
+ *
+ * @return string "success" or an error message
+ */
+function cwp7_delSubdomain($params) {
+	if(!filter_var($_POST['d'], FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)){
+		return 'Error: invalid domain name';
+	}
+	$cwp7 = new cwp7_Admin($params['serverhostname'], $params['serveraccesshash']);
+	$response = $cwp7->getAccount($params['username']);
+	if($response['status'] != 'OK') {
+		logModuleCall(
+			'cwp7',
+			__FUNCTION__,
+			$params,
+			'debug',
+			$response
+		);
+	}
+	$subdomains = $response['result']['subdomins'];
+	$clientsubdomains = array();
+	foreach($subdomains as $subdomain){
+		if($subdomain['domain'] != $params['domain']) {
+			array_push($clientsubdomains, $subdomain['subdomain'] . "." . $subdomain['domain']);
+		}
+	}
+	if(!in_array($_POST['d'], $clientsubdomains)) {
+		logModuleCall(
+			'cwp7',
+			__FUNCTION__,
+			$_POST,
+			'POST DATA VIOLATION',
+			$params
+		);
+		return 'Error: ' . $_POST['d'] . ' not in client subdomains';
+	}
+	// do delete subdomain
+	$vars['user'] = $params['username'];
+	$vars['name'] = $_POST['d'];
+	$vars['type'] = 'subdomain';
+	$response = $cwp7->deleteDomain($vars);
+	if($response['status'] != 'OK') {
+		return 'Error: ' . $response['error_msg'];
+	}
+	return 'success';
+}
+
+/**
+ * Opens a form to enable SSL for a subdomain or domain of a CWP7 account.
+ *
+ * @param array $params common module parameters
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
+ *
+ * @return array template information
+ */
+function cwp7_enableSSLConfirm($params) {
+	return array(
+		'templatefile' => 'cwp7_enable_SSL_confirm',
+		'vars' => array(
+			'SSLdomain' => $_POST['d'],
+		),
+    );
+}
+
+/**
+ * Aktivate CWP7 AutoSSL for a subdomain or domain of a CWP7 account.
+ *
+ * @param array $params common module parameters
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
+ *
+ * @return string "success" or an error message
+ */
+function cwp7_enableSSL($params) {
+	if(!filter_var($_POST['d'], FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)){
+		return 'Error: invalid domain name';
+	}
+	$vars['user'] = $params['username'];
+	$vars['name'] = $_POST['d'];
+	$cwp7 = new cwp7_Admin($params['serverhostname'], $params['serveraccesshash']);
+	$response = $cwp7->addAutoSSL($vars);
+	if($response['status'] != 'OK') {
+		return 'Error: ' . $response['error_msg'];
+	}
+	return 'success';
+}
+
+/**
+ * Opens a form to renew a SSL certificate for a subdomain or domain of a CWP7 account.
+ *
+ * @param array $params common module parameters
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
+ *
+ * @return array template information
+ */
+function cwp7_renewSSLConfirm($params) {
+	return array(
+		'templatefile' => 'cwp7_renew_SSL_confirm',
+		'vars' => array(
+			'SSLdomain' => $_POST['d'],
+		),
+    );
+}
+
+/**
+ * Renews a SSL certificate for a subdomain or domain of a CWP7 account.
+ *
+ * @param array $params common module parameters
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
+ *
+ * @return string "success" or an error message
+ */
+function cwp7_renewSSL($params) {
+	if(!filter_var($_POST['d'], FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)){
+		return 'Error: invalid domain name';
+	}
+	$vars['user'] = $params['username'];
+	$vars['name'] = $_POST['d'];
+	$cwp7 = new cwp7_Admin($params['serverhostname'], $params['serveraccesshash']);
+	$response = $cwp7->updateAutoSSL($vars);
+	if($response['status'] != 'OK') {
+		return 'Error: ' . $response['error_msg'];
+	}
+	return 'success';
+}
+
+/**
+ * Opens a form to set a DNS record for a subdomain or domain of a CWP7 account.
+ *
+ * @param array $params common module parameters
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
+ *
+ * @return array template information
+ */
+function cwp7_setDNSConfirm($params) {
+	if(isset($_POST['s'])){
+		return array(
+			'templatefile' => 'cwp7_set_DNS_confirm',
+			'vars' => array(
+				'DNSdomain' => $_POST['d'],
+				'DNSsubdomain' => $_POST['s'],
+			),
+		);
+	}
+	return array(
+		'templatefile' => 'cwp7_set_DNS_confirm',
+		'vars' => array(
+			'DNSdomain' => $_POST['d'],
+		),
+    );
+}
+
+/**
+ * Opens a form to unsset a DNS record for a subdomain or domain of a CWP7 account.
+ *
+ * @param array $params common module parameters
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
+ *
+ * @return array template information
+ */
+function cwp7_unsetDNSConfirm($params) {
+	if(isset($_POST['s'])){
+		return array(
+			'templatefile' => 'cwp7_unset_DNS_confirm',
+			'vars' => array(
+				'DNSdomain' => $_POST['d'],
+				'DNSsubdomain' => $_POST['s'],
+			),
+		);
+	}
+	return array(
+		'templatefile' => 'cwp7_unset_DNS_confirm',
+		'vars' => array(
+			'DNSdomain' => $_POST['d'],
+		),
+    );
+}
+
+/**
+ * Update a DNS zone for a domain setting a new record for a domain or subdomain of a CWP7 account.
+ *
+ * @param array $params common module parameters
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
+ *
+ * @return string "success" or an error message
+ */
+function cwp7_setDNS($params) {
+	if(!filter_var($_POST['d'], FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)){
+		return 'Error: invalid domain name';
+	}
+	$domainName = $_POST['d'];
+    $zoneRecords = array();
+	if(isset($_POST['s'])){
+		if(!filter_var($_POST['s'], FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)){
+			return 'Error: invalid subdomain name';
+		}
+		$hostName = $_POST['s'] . '.' . $domainName . '.';
+		$newRecord = array(
+			'line' => $hostName.'|A|0',
+			'name' => $hostName,
+			'type' => 'A',
+			'class' => 'IN',
+			'data' => array(
+				'address' => $params['serverip'],
+			),
+		);
+		array_push($zoneRecords, $newRecord);
+	} else {
+		$hostName = $domainName . '.';
+		$domainRecord = array(
+			'line' => $hostName.'|A|0',
+			'name' => $hostName,
+			'type' => 'A',
+			'class' => 'IN',
+			'data' => array(
+				'address' => $params['serverip'],
+			),
+		);
+		array_push($zoneRecords, $domainRecord);
+		$wwwRecord = array(
+			'line' => 'www'.$hostName.'|A|0',
+			'name' => 'www'.$hostName,
+			'type' => 'A',
+			'class' => 'IN',
+			'data' => array(
+				'address' => $params['serverip'],
+			),
+		);
+		array_push($zoneRecords, $wwwRecord);
+	}
+	$zoneIDcollection = Capsule::table('dns_manager2_zone')
+		->select('id')
+		->where('name', '=', $domainName)
+		->where('clientid', '=', $params['userid'])
+		->get();
+	$zoneIDobj = $zoneIDcollection[0];
+	$zoneID = $zoneIDobj->{'id'};
+	if(!isset($zoneID)) {
+		return 'Error: Zone for domain ' . $domainName . ' or not owned by client';
+	}
+	$dnsZone = localAPI('dnsmanager', array( 'dnsaction' => 'getZone', 'zone_id' => $zoneID));
+    foreach($dnsZone['data']->records as $record) {
+        if(($record->name != $hostName) || ($record->type != 'A' && $record->type != 'CNAME')) {
+            array_push($zoneRecords, $record);
+        };
+    }
+    $result = localAPI('dnsmanager' ,
+        array(
+            'dnsaction' => 'updateZone',
+            'zone_id' => $zoneID,
+            'records' => $zoneRecords,
+        )
+	);
+    if($result['result'] != 'success') {
+        return 'Error: ' . $result['message'];
+    }
+	return 'success';
+}
+
+/**
+ * Removing a DNS record for a domain or subdomain of a CWP7 account.
+ *
+ * @param array $params common module parameters
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
+ *
+ * @return string "success" or an error message
+ */
+function cwp7_unsetDNS($params) {
+	if(!filter_var($_POST['d'], FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)){
+		return 'Error: invalid domain name';
+	}
+	$domainName = $_POST['d'];
+    $zoneRecords = array();
+	if(isset($_POST['s'])){
+		if(!filter_var($_POST['s'], FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)){
+			return 'Error: invalid subdomain name';
+		}
+		$hostName = $_POST['s'] . '.' . $domainName . '.';
+	} else {
+		$hostName = $domainName . '.';
+	}
+	$zoneIDcollection = Capsule::table('dns_manager2_zone')
+		->select('id')
+		->where('name', '=', $domainName)
+		->where('clientid', '=', $params['userid'])
+		->get();
+	$zoneIDobj = $zoneIDcollection[0];
+	$zoneID = $zoneIDobj->{'id'};
+	if(!isset($zoneID)) {
+		return 'Error: Zone for domain ' . $domainName . ' or not owned by client';
+	}
+	$dnsZone = localAPI('dnsmanager', array( 'dnsaction' => 'getZone', 'zone_id' => $zoneID));
+    foreach($dnsZone['data']->records as $record) {
+        if(($record->name != $hostName) || ($record->type != 'A' && $record->type != 'CNAME')) {
+            array_push($zoneRecords, $record);
+        };
+    }
+    $result = localAPI('dnsmanager' ,
+        array(
+            'dnsaction' => 'updateZone',
+            'zone_id' => $zoneID,
+            'records' => $zoneRecords,
+        )
+	);
+    if($result['result'] != 'success') {
+        return 'Error: ' . $result['message'];
+    }
+	return 'success';
+}
+
+/**
+ * Opens a form to inform about the DNS status of a subdomain or domain of a CWP7 account.
+ *
+ * @param array $params common module parameters
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
+ *
+ * @return array template information
+ */
+function cwp7_infoDNS($params) {
+	if(!filter_var($_POST['d'], FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)){
+		return 'Error: invalid domain name';
+	}
+	$cwp7nameserver = cwp7CheckSOA($_POST['d'],$params['configoption5']);
+	return array(
+        'templatefile' => 'cwp7_help_dns',
+        'vars' => array(
+            'infodomain' => $_POST['d'],
+            'cwp7nameserver' => $cwp7nameserver,
+        ),
+    );
+}
+
+/**
+ * Opens a form to inform about the SSL status of a subdomain or domain of a CWP7 account.
+ *
+ * @param array $params common module parameters
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
+ *
+ * @return array template information
+ */
+function cwp7_infoSSL($params) {
+	if(!filter_var($_POST['d'], FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)){
+		return 'Error: invalid domain name';
+	}
+	return array(
+        'templatefile' => 'cwp7_help_ssl',
+        'vars' => array(
+            'infodomain' => $_POST['d'],
+        ),
+    );
+}
+
+/**
+ * Ask nameservers for a IP adress of a given host.
+ *
+ * @param string $host hostname
+ * @param string $serverIP CWP7 server IP
+ * @param string $nameserverIP polled name server IP
+ * @param int $recurse optional -> used to follow CNAME responses
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
+ *
+ * @return bool
+ */
+function cwp7CheckA($host, $serverIP, $nameserverIP, $recurse = 0) {
+	if($recurse > 3) {
+		return false;
+	}
+	$nameserver = array($nameserverIP);
+    # try NS1
+    $resolver = new Net_DNS2_Resolver(array('nameservers' => $nameserver));
+    try {
+        $result = $resolver->query($host, 'A');
+    } catch(Net_DNS2_Exception $e) {
+    # try default nameserver
+        $resolver = new Net_DNS2_Resolver();
+        try {
+            $result = $resolver->query($host, 'A');
+        } catch(Net_DNS2_Exception $e) {
+			logModuleCall(
+				'cwp7',
+				__FUNCTION__,
+				$e,
+				'DNS lookup exception',
+				$e->getMessage()
+			);
+			return false;
+		}
+    }
+	$hostA = $result->answer;
+	if($hostA[0]->type == 'CNAME') {
+		if(cwp7CheckA($hostA[0]->cname, $serverIP, $nameserverIP, $recurse++)) {
+			return true;
+		}
+	}
+	if($hostA[0]->type == 'A') {
+		if($hostA[0]->address == $serverIP){
+			return true;
+		}
+	}
+	return false;
+}
+
+/**
+ * Ask nameservers for the authority of a domain.
+ *
+ * @param string $domain domain name
+ * @param string $nameserverIP polled name server IP
+ * @param string $nameserverName name of the own namesever
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
+ *
+ * @return string 'none' -> not registered, 'self' -> registered at own or the name of an other responsible nameserver
+ */
+function cwp7CheckSOA($domain, $nameserverIP) {
+	$nameserver = array($nameserverIP);
+    # try NS1
+	$resolver = new Net_DNS2_Resolver(array('nameservers' => $nameserver));
+    try {
+            $result = $resolver->query($domain, 'SOA');
+            return 'self';
+    } catch(Net_DNS2_Exception $e) {
+    # try default NS
+    	$resolver = new Net_DNS2_Resolver();
+        try {
+            $result = $resolver->query($domain, 'SOA');
+        } catch(Net_DNS2_Exception $e) {
+            return 'none';
+        }
+    }
+	return $result->answer[0]->mname;
+}
+
+/**
+ * Check limits for a service of an account .
+ *
+ * @param array $params common module parameters
+ * @param string $type domains|subdomins
+ *
+ * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
+ *
+ * @return bool true -> limit reached, false -> limit not reached
+ */
+function cwp7CheckLimit($params, $type) {
+	$cwp7 = new cwp7_Admin($params['serverhostname'], $params['serveraccesshash']);
+	$response = $cwp7->getQuota($params['username']);
+	if($response[$type]['sw'] < 1) {
+		return true;
+	}
+	return false;
+}

+ 69 - 0
TDHosting_add_domain.tpl

@@ -0,0 +1,69 @@
+<h2>Neue Domain erstellen</h2>
+<hr>
+<div class="tab-content margin-bottom">
+	<div class="section">
+		<div class="product-details">
+			<div class="row row-eq-height row-eq-height-sm">
+				<div class="col-md-6">
+					<div class="product-holder product-status-{$rawstatus|strtolower}" style="min-height: unset; height:210px">
+						<div class="product-content">
+							<div class="product-image">
+								<div class="feature-icon">
+									<img src="/templates/croster/thurdata/productgroups/{$gid}.svg" class="img-fluid" style="height:100px;">
+								</div>
+							</div>
+							<h4><small>Hosting Account</small> - {$domain}</h4>
+							<div class="status-sticker-wrapper">
+								<div class="status-sticker product-status-{$rawstatus|strtolower}">
+									{$status}
+								</div>
+							</div>
+						</div>
+					</div>
+				</div>
+				<div class="col-md-6">
+					<table width="100%" border="0">
+						<tbody>
+							<tr>
+								<td>
+									<div class="alert alert-info">
+										Geben Sie den Namen der neuen Hosting Domain ein. 
+										Diese Domain wird in Ihrem Hosting-Account erstellt. 
+										Dabei wird auch automatisch eine <b>www</b> Subdomain hinzugefügt. 
+										Einen DNS Eintrag, ein SSL Zertifikat oder weitere Subdomains 
+										für Ihre neue Domain können Sie danach in der Übersicht erstellen.
+									</div>
+								</td>
+							</tr>
+							<tr>
+								<td>						
+									<form style="display:flex;flex-direction:row;align-items:center;justify-content: space-between;" method="post" action="clientarea.php?action=productdetails">
+										<input type="hidden" name="id" value="{$id}" />
+										<input type="hidden" name="modop" value="custom" />
+										<input type="hidden" name="a" value="addDomain" />
+										<input style="margin-right:20px;" class="form-control" type="text" maxlength=256 name="d" /> 
+										<button type="submit" class="btn btn-primary btn-block">
+											Erstellen
+										</button>
+									</form>
+								</td>
+							</tr>
+						</tbody>
+					</table>
+				</div>
+			</div>
+		</div>
+	</div>
+	<div class="section">
+		<div class="row row-eq-height row-eq-height-sm">
+			<div class="col-md-4">
+				<form method="post" action="clientarea.php?action=productdetails">
+					<input type="hidden" name="id" value="{$id}" />
+					<button type="submit" class="btn btn-default btn-block">
+							{$LANG.clientareabacklink}
+					</button>
+				</form>
+			</div>
+		</div>
+	</div>
+</div>

+ 69 - 0
TDHosting_add_subdomain.tpl

@@ -0,0 +1,69 @@
+<h2>Neue Subdomain erstellen</h2>
+<hr>
+<div class="tab-content margin-bottom">
+	<div class="section">
+		<div class="product-details">
+			<div class="row row-eq-height row-eq-height-sm">
+				<div class="col-md-6">
+					<div class="product-holder product-status-{$rawstatus|strtolower}" style="min-height: unset; height:210px">
+						<div class="product-content">
+							<div class="product-image">
+								<div class="feature-icon">
+									<img src="/templates/croster/thurdata/productgroups/{$gid}.svg" class="img-fluid" style="height:100px;">
+								</div>
+							</div>
+							<h4><small>Hosting Account</small> - {$domain}</h4>
+							<div class="status-sticker-wrapper">
+								<div class="status-sticker product-status-{$rawstatus|strtolower}">
+									{$status}
+								</div>
+							</div>
+						</div>
+					</div>
+				</div>
+				<div class="col-md-6">
+					<table width="100%" border="0">
+						<tbody>
+							<tr>
+								<td>
+									<div class="alert alert-info">
+										Geben Sie den Namen der neuen Subdomain für {$domainselected} ein.
+										Einen DNS Eintrag und ein SSL Zertifikat für Ihre neue 
+										Subdomain können Sie danach in der Übersicht erstellen.
+									</div>
+								</td>
+							</tr>
+							<tr>
+								<td>						
+									<form style="display:flex;flex-direction:row;align-items:center;justify-content: space-between;" method="post" action="clientarea.php?action=productdetails">
+										<input type="hidden" name="id" value="{$id}" />
+										<input type="hidden" name="modop" value="custom" />
+										<input type="hidden" name="a" value="addSubdomain" />
+										<input type="hidden" name="d" value="{$domainselected}" />
+										<input style="margin-right:5px;" class="form-control" type="text" maxlength=256 name="s" />
+										<input style="margin-left:5px;margin-right:20px;" class="form-control" type="text" maxlength=256 value=".{$domainselected}" disabled /> 
+										<button type="submit" class="btn btn-primary btn-block">
+											Erstellen
+										</button>
+									</form>
+								</td>
+							</tr>
+						</tbody>
+					</table>
+				</div>
+			</div>
+		</div>
+	</div>
+	<div class="section">
+		<div class="row row-eq-height row-eq-height-sm">
+			<div class="col-md-4">
+				<form method="post" action="clientarea.php?action=productdetails">
+					<input type="hidden" name="id" value="{$id}" />
+					<button type="submit" class="btn btn-default btn-block">
+							{$LANG.clientareabacklink}
+					</button>
+				</form>
+			</div>
+		</div>
+	</div>
+</div>

+ 66 - 0
TDHosting_del_domain_confirm.tpl

@@ -0,0 +1,66 @@
+<h2>Domain löschen</h2>
+<hr>
+<div class="tab-content margin-bottom">
+	<div class="section">
+		<div class="product-details">
+			<div class="row row-eq-height row-eq-height-sm">
+				<div class="col-md-6">
+					<div class="product-holder product-status-{$rawstatus|strtolower}" style="min-height: unset; height:210px">
+						<div class="product-content">
+							<div class="product-image">
+								<div class="feature-icon">
+									<img src="/templates/croster/thurdata/productgroups/{$gid}.svg" class="img-fluid" style="height:100px;">
+								</div>
+							</div>
+							<h4><small>Hosting Account</small> - {$domain}</h4>
+							<div class="status-sticker-wrapper">
+								<div class="status-sticker product-status-{$rawstatus|strtolower}">
+									{$status}
+								</div>
+							</div>
+						</div>
+					</div>
+				</div>
+				<div class="col-md-6">
+					<table width="100%" border="0">
+						<tbody>
+							<tr>
+								<td>
+									<div class="alert alert-warning">
+										Bitte bestätigen Sie das Löschen der Domain<br />
+										<b>{$deldomain}</b>
+									</div>
+								</td>
+							</tr>
+							<tr>
+								<td>						
+									<form style="display:flex;flex-direction:row;align-items:center;justify-content: space-between;" method="post" action="clientarea.php?action=productdetails">
+										<input type="hidden" name="id" value="{$id}" />
+										<input type="hidden" name="modop" value="custom" />
+										<input type="hidden" name="a" value="delDomain" />
+										<input type="hidden" name="d" value="{$deldomain}" />
+										<button type="submit" class="btn btn-danger btn-block">
+											Löschen bestätigen
+										</button>
+									</form>
+								</td>
+							</tr>
+						</tbody>
+					</table>
+				</div>
+			</div>
+		</div>
+	</div>
+	<div class="section">
+		<div class="row row-eq-height row-eq-height-sm">
+			<div class="col-md-4">
+				<form method="post" action="clientarea.php?action=productdetails">
+					<input type="hidden" name="id" value="{$id}" />
+					<button type="submit" class="btn btn-default btn-block">
+							{$LANG.clientareabacklink}
+					</button>
+				</form>
+			</div>
+		</div>
+	</div>
+</div>

+ 66 - 0
TDHosting_del_subdomain_confirm.tpl

@@ -0,0 +1,66 @@
+<h2>Subdomain löschen</h2>
+<hr>
+<div class="tab-content margin-bottom">
+	<div class="section">
+		<div class="product-details">
+			<div class="row row-eq-height row-eq-height-sm">
+				<div class="col-md-6">
+					<div class="product-holder product-status-{$rawstatus|strtolower}" style="min-height: unset; height:210px">
+						<div class="product-content">
+							<div class="product-image">
+								<div class="feature-icon">
+									<img src="/templates/croster/thurdata/productgroups/{$gid}.svg" class="img-fluid" style="height:100px;">
+								</div>
+							</div>
+							<h4><small>Hosting Account</small> - {$domain}</h4>
+							<div class="status-sticker-wrapper">
+								<div class="status-sticker product-status-{$rawstatus|strtolower}">
+									{$status}
+								</div>
+							</div>
+						</div>
+					</div>
+				</div>
+				<div class="col-md-6">
+					<table width="100%" border="0">
+						<tbody>
+							<tr>
+								<td>
+									<div class="alert alert-warning">
+										Bitte bestätigen Sie das Löschen der Subdomain<br />
+										<b>{$delsubdomain}</b>
+									</div>
+								</td>
+							</tr>
+							<tr>
+								<td>						
+									<form style="display:flex;flex-direction:row;align-items:center;justify-content: space-between;" method="post" action="clientarea.php?action=productdetails">
+										<input type="hidden" name="id" value="{$id}" />
+										<input type="hidden" name="modop" value="custom" />
+										<input type="hidden" name="a" value="delSubdomain" />
+										<input type="hidden" name="d" value="{$delsubdomain}" />
+										<button type="submit" class="btn btn-danger btn-block">
+											Löschen bestätigen
+										</button>
+									</form>
+								</td>
+							</tr>
+						</tbody>
+					</table>
+				</div>
+			</div>
+		</div>
+	</div>
+	<div class="section">
+		<div class="row row-eq-height row-eq-height-sm">
+			<div class="col-md-4">
+				<form method="post" action="clientarea.php?action=productdetails">
+					<input type="hidden" name="id" value="{$id}" />
+					<button type="submit" class="btn btn-default btn-block">
+							{$LANG.clientareabacklink}
+					</button>
+				</form>
+			</div>
+		</div>
+	</div>
+</div>

+ 66 - 0
TDHosting_enable_SSL_confirm.tpl

@@ -0,0 +1,66 @@
+<h2>SSL aktivieren</h2>
+<hr>
+<div class="tab-content margin-bottom">
+	<div class="section">
+		<div class="product-details">
+			<div class="row row-eq-height row-eq-height-sm">
+				<div class="col-md-6">
+					<div class="product-holder product-status-{$rawstatus|strtolower}" style="min-height: unset; height:210px">
+						<div class="product-content">
+							<div class="product-image">
+								<div class="feature-icon">
+									<img src="/templates/croster/thurdata/productgroups/{$gid}.svg" class="img-fluid" style="height:100px;">
+								</div>
+							</div>
+							<h4><small>Hosting Account</small> - {$domain}</h4>
+							<div class="status-sticker-wrapper">
+								<div class="status-sticker product-status-{$rawstatus|strtolower}">
+									{$status}
+								</div>
+							</div>
+						</div>
+					</div>
+				</div>
+				<div class="col-md-6">
+					<table width="100%" border="0">
+						<tbody>
+							<tr>
+								<td>
+									<div class="alert alert-warning">
+										Zertifikate erstellen und aktivieren für die Domain<br />
+										<b>{$SSLdomain}</b>
+									</div>
+								</td>
+							</tr>
+							<tr>
+								<td>						
+									<form style="display:flex;flex-direction:row;align-items:center;justify-content: space-between;" method="post" action="clientarea.php?action=productdetails">
+										<input type="hidden" name="id" value="{$id}" />
+										<input type="hidden" name="modop" value="custom" />
+										<input type="hidden" name="a" value="enableSSL" />
+										<input type="hidden" name="d" value="{$SSLdomain}" />
+										<button type="submit" class="btn btn-primary btn-block">
+											Aktivieren
+										</button>
+									</form>
+								</td>
+							</tr>
+						</tbody>
+					</table>
+				</div>
+			</div>
+		</div>
+	</div>
+	<div class="section">
+		<div class="row row-eq-height row-eq-height-sm">
+			<div class="col-md-4">
+				<form method="post" action="clientarea.php?action=productdetails">
+					<input type="hidden" name="id" value="{$id}" />
+					<button type="submit" class="btn btn-default btn-block">
+							{$LANG.clientareabacklink}
+					</button>
+				</form>
+			</div>
+		</div>
+	</div>
+</div>

+ 76 - 0
TDHosting_help_dns.tpl

@@ -0,0 +1,76 @@
+<h2>Domain Status</h2>
+<hr>
+<div class="tab-content margin-bottom">
+    <div class="section">
+        <div class="product-details">
+            <div class="row row-eq-height row-eq-height-sm">
+                <div class="col-md-6">
+                    <div class="product-holder product-status-{$rawstatus|strtolower}" style="min-height: unset; height:210px">
+                        <div class="product-content">
+                            <div class="product-image">
+                                <div class="feature-icon">
+                                    <img src="/templates/croster/thurdata/productgroups/{$gid}.svg" class="img-fluid" style="height:100px;">
+                                </div>
+                            </div>
+                            <h4><small>Hosting Account</small> - {$domain}</h4>
+                            <div class="status-sticker-wrapper">
+                                <div class="status-sticker product-status-{$rawstatus|strtolower}">
+                                    {$status}
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <div class="col-md-6">
+                    <table width="100%" border="0">
+                        <tbody>
+                            <tr>
+                                <td>
+                                    <div class="alert alert-info">
+                                        Änderungen am DNS über Ihr Thurdata Portal sind nur möglich, 
+                                        wenn die Domain {$infodomain} bei Thurdata registriert ist.
+                                        {if $cwp7nameserver == 'none'}
+                                            Aktuell ist Ihre Domain {$infodomain} nicht registriert. 
+                                            Klicken Sie auf <b>Domain registrieren</b>, 
+                                            um bei uns Ihre neue Domain zu registrieren!
+                                        {else}
+                                            Ihre Domain {$infodomain} ist aktuell nicht bei Thurdata registriert. 
+                                            Klicken Sie auf <b>Domain transferieren</b>, 
+                                            um Ihre Domain bei Thurdata zu registrieren, 
+                                            oder nutzen Sie die DNS Werkzeuge Ihres aktuellen Registrars.
+                                        {/if}
+                                    </div>
+                                </td>
+                            </tr>
+                            <tr>
+                                <td>
+                                    {if $cwp7nameserver == 'none'}
+                                        <a href="/cart.php?a=add&domain=register" class="btn btn-primary btn-block">
+                                            Domain registrieren
+                                        </a>
+                                    {else}
+                                        <a href="/cart.php?a=add&domain=transfer" class="btn btn-primary btn-block">
+                                            Domain transferieren
+                                        </a>
+                                    {/if}
+                                </td>
+                            </tr>
+                        </tbody>
+                    </table>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="section">
+        <div class="row row-eq-height row-eq-height-sm">
+            <div class="col-md-4">
+                <form method="post" action="clientarea.php?action=productdetails">
+                    <input type="hidden" name="id" value="{$id}" />
+                    <button type="submit" class="btn btn-default btn-block">
+                            {$LANG.clientareabacklink}
+                    </button>
+                </form>
+            </div>
+        </div>
+    </div>
+</div>

+ 51 - 0
TDHosting_help_ssl.tpl

@@ -0,0 +1,51 @@
+<h2>Domain Status</h2>
+<hr>
+<div class="tab-content margin-bottom">
+    <div class="section">
+        <div class="product-details">
+            <div class="row row-eq-height row-eq-height-sm">
+                <div class="col-md-6">
+                    <div class="product-holder product-status-{$rawstatus|strtolower}" style="min-height: unset; height:210px">
+                        <div class="product-content">
+                            <div class="product-image">
+                                <div class="feature-icon">
+                                    <img src="/templates/croster/thurdata/productgroups/{$gid}.svg" class="img-fluid" style="height:100px;">
+                                </div>
+                            </div>
+                            <h4><small>Hosting Account</small> - {$domain}</h4>
+                            <div class="status-sticker-wrapper">
+                                <div class="status-sticker product-status-{$rawstatus|strtolower}">
+                                    {$status}
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <div class="col-md-6">
+                    <table width="100%" border="0">
+                        <tbody>
+                            <tr>
+                                <td>
+                                    <div class="alert alert-info">
+                                        Um ein gültiges Zertifikat für {$infodomain} zu erstellen, muss der DNS Name von {$infodomain} auf den Thurdata Webserver zeigen. 
+                                        Bitte aktivieren Sie zuerst das DNS für {$infodomain}!
+                                    </div>
+                                </td>
+                            </tr>
+                            <tr>
+                                <td>
+                                    <form method="post" action="clientarea.php?action=productdetails">
+                                        <input type="hidden" name="id" value="{$id}" />
+                                        <button type="submit" class="btn btn-default btn-block">
+                                            {$LANG.clientareabacklink}
+                                        </button>
+                                    </form>
+                                </td>
+                            </tr>
+                        </tbody>
+                    </table>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>

+ 66 - 0
TDHosting_renew_SSL_confirm.tpl

@@ -0,0 +1,66 @@
+<h2>Zertifikate erneuern</h2>
+<hr>
+<div class="tab-content margin-bottom">
+	<div class="section">
+		<div class="product-details">
+			<div class="row row-eq-height row-eq-height-sm">
+				<div class="col-md-6">
+					<div class="product-holder product-status-{$rawstatus|strtolower}" style="min-height: unset; height:210px">
+						<div class="product-content">
+							<div class="product-image">
+								<div class="feature-icon">
+									<img src="/templates/croster/thurdata/productgroups/{$gid}.svg" class="img-fluid" style="height:100px;">
+								</div>
+							</div>
+							<h4><small>Hosting Account</small> - {$domain}</h4>
+							<div class="status-sticker-wrapper">
+								<div class="status-sticker product-status-{$rawstatus|strtolower}">
+									{$status}
+								</div>
+							</div>
+						</div>
+					</div>
+				</div>
+				<div class="col-md-6">
+					<table width="100%" border="0">
+						<tbody>
+							<tr>
+								<td>
+									<div class="alert alert-warning">
+										Erneuerung des SSL Zertifikates für die Domain<br />
+										<b>{$SSLdomain}</b>
+									</div>
+								</td>
+							</tr>
+							<tr>
+								<td>						
+									<form style="display:flex;flex-direction:row;align-items:center;justify-content: space-between;" method="post" action="clientarea.php?action=productdetails">
+										<input type="hidden" name="id" value="{$id}" />
+										<input type="hidden" name="modop" value="custom" />
+										<input type="hidden" name="a" value="renewSSL" />
+										<input type="hidden" name="d" value="{$SSLdomain}" />
+										<button type="submit" class="btn btn-primary btn-block">
+											Erneuern
+										</button>
+									</form>
+								</td>
+							</tr>
+						</tbody>
+					</table>
+				</div>
+			</div>
+		</div>
+	</div>
+	<div class="section">
+		<div class="row row-eq-height row-eq-height-sm">
+			<div class="col-md-4">
+				<form method="post" action="clientarea.php?action=productdetails">
+					<input type="hidden" name="id" value="{$id}" />
+					<button type="submit" class="btn btn-default btn-block">
+							{$LANG.clientareabacklink}
+					</button>
+				</form>
+			</div>
+		</div>
+	</div>
+</div>

+ 71 - 0
TDHosting_set_DNS_confirm.tpl

@@ -0,0 +1,71 @@
+<h2>DNS aktivieren</h2>
+<hr>
+<div class="tab-content margin-bottom">
+	<div class="section">
+		<div class="product-details">
+			<div class="row row-eq-height row-eq-height-sm">
+				<div class="col-md-6">
+					<div class="product-holder product-status-{$rawstatus|strtolower}" style="min-height: unset; height:210px">
+						<div class="product-content">
+							<div class="product-image">
+								<div class="feature-icon">
+									<img src="/templates/croster/thurdata/productgroups/{$gid}.svg" class="img-fluid" style="height:100px;">
+								</div>
+							</div>
+							<h4><small>Hosting Account</small> - {$domain}</h4>
+							<div class="status-sticker-wrapper">
+								<div class="status-sticker product-status-{$rawstatus|strtolower}">
+									{$status}
+								</div>
+							</div>
+						</div>
+					</div>
+				</div>
+				<div class="col-md-6">
+					<table width="100%" border="0">
+						<tbody>
+							<tr>
+								<td>
+									<div class="alert alert-warning">
+										DNS Aktivierung für Domain&nbsp;
+										<b>{if $DNSsubdomain}{$DNSsubdomain}.{/if}{$DNSdomain}</b><br /><br />
+										<i class="fa fa-exclamation-circle"></i>
+										Achtung: Beachten Sie bitte, das die die Aktivierung erst dann in der Übersicht angezeigt wird, wenn die DNS-Propagation beendet wurde. Versuchen Sie eine Aktivierung daher nicht mehrmals hintereinander! 
+										</div>
+								</td>
+							</tr>
+							<tr>
+								<td>						
+									<form style="display:flex;flex-direction:row;align-items:center;justify-content: space-between;" method="post" action="clientarea.php?action=productdetails">
+										<input type="hidden" name="id" value="{$id}" />
+										<input type="hidden" name="modop" value="custom" />
+										<input type="hidden" name="a" value="setDNS" />
+										<input type="hidden" name="d" value="{$DNSdomain}" />
+										{if $DNSsubdomain}
+											<input type="hidden" name="s" value="{$DNSsubdomain}" />
+										{/if}
+										<button type="submit" class="btn btn-primary btn-block">
+											Aktivieren
+										</button>
+									</form>
+								</td>
+							</tr>
+						</tbody>
+					</table>
+				</div>
+			</div>
+		</div>
+	</div>
+	<div class="section">
+		<div class="row row-eq-height row-eq-height-sm">
+			<div class="col-md-4">
+				<form method="post" action="clientarea.php?action=productdetails">
+					<input type="hidden" name="id" value="{$id}" />
+					<button type="submit" class="btn btn-default btn-block">
+							{$LANG.clientareabacklink}
+					</button>
+				</form>
+			</div>
+		</div>
+	</div>
+</div>

+ 71 - 0
TDHosting_unset_DNS_confirm.tpl

@@ -0,0 +1,71 @@
+<h2>DNS deaktivieren</h2>
+<hr>
+<div class="tab-content margin-bottom">
+	<div class="section">
+		<div class="product-details">
+			<div class="row row-eq-height row-eq-height-sm">
+				<div class="col-md-6">
+					<div class="product-holder product-status-{$rawstatus|strtolower}" style="min-height: unset; height:210px">
+						<div class="product-content">
+							<div class="product-image">
+								<div class="feature-icon">
+									<img src="/templates/croster/thurdata/productgroups/{$gid}.svg" class="img-fluid" style="height:100px;">
+								</div>
+							</div>
+							<h4><small>Hosting Account</small> - {$domain}</h4>
+							<div class="status-sticker-wrapper">
+								<div class="status-sticker product-status-{$rawstatus|strtolower}">
+									{$status}
+								</div>
+							</div>
+						</div>
+					</div>
+				</div>
+				<div class="col-md-6">
+					<table width="100%" border="0">
+						<tbody>
+							<tr>
+								<td>
+									<div class="alert alert-warning">
+										DNS Deaktivierung für Domain&nbsp;
+										<b>{if $DNSsubdomain}{$DNSsubdomain}.{/if}{$DNSdomain}</b><br /><br />
+										<i class="fa fa-exclamation-circle"></i>
+										Achtung: Beachten Sie bitte, das die Deaktivierung erst dann in der Übersicht angezeigt wird, wenn die TTL des Eintrags abgelaufen ist. Versuchen Sie eine Deaktivierung daher nicht mehrmals hintereinander! 
+										</div>
+								</td>
+							</tr>
+							<tr>
+								<td>						
+									<form style="display:flex;flex-direction:row;align-items:center;justify-content: space-between;" method="post" action="clientarea.php?action=productdetails">
+										<input type="hidden" name="id" value="{$id}" />
+										<input type="hidden" name="modop" value="custom" />
+										<input type="hidden" name="a" value="unsetDNS" />
+										<input type="hidden" name="d" value="{$DNSdomain}" />
+										{if $DNSsubdomain}
+											<input type="hidden" name="s" value="{$DNSsubdomain}" />
+										{/if}
+										<button type="submit" class="btn btn-primary btn-block">
+											Deaktivieren
+										</button>
+									</form>
+								</td>
+							</tr>
+						</tbody>
+					</table>
+				</div>
+			</div>
+		</div>
+	</div>
+	<div class="section">
+		<div class="row row-eq-height row-eq-height-sm">
+			<div class="col-md-4">
+				<form method="post" action="clientarea.php?action=productdetails">
+					<input type="hidden" name="id" value="{$id}" />
+					<button type="submit" class="btn btn-default btn-block">
+							{$LANG.clientareabacklink}
+					</button>
+				</form>
+			</div>
+		</div>
+	</div>
+</div>

+ 416 - 0
api/TDHosting/Admin.php

@@ -0,0 +1,416 @@
+<?php
+/**
+ * cwp7_Admin
+ *
+ * @author André Genrich <andre.genrich@thurdata.ch>
+ * @author Roland Käser <roland.keaser@thurdata.ch>
+ * @version 0.9
+ * @copyright Copyright (c) 2021, Thurdata
+ * @example ../test.php
+ */
+/**
+ * cwp7_Admin class documentation
+ */
+/**
+ * cwp7_Admin is a class which allows to manage cwp7 accounts via web-api
+ *
+ * You may create, modify, migrate, delete and get the attributes of a cwp7 account using this class
+ *
+ * For the usage examples of all class methods check the source code of test.php
+ */
+class cwp7_Admin {
+    private $constructorSuccess;
+    private $cwp7URL;
+    private $cwp7ConType;
+    private $cwp7Port;
+    private $cwp7Secure;
+    protected $cwp7Token;
+	/**
+	 * Constructor
+     * @param string $cwp7Host cwp7 hostname or IP (example: cwp7.my.lan)
+	 * @param string $token api token
+	 * @param string $secure optional false to force unsecure (default true)
+	 */
+    function __construct($cwp7Host, $token, $secure=true) {
+        if(!in_array('curl', get_loaded_extensions())) {
+            $this->constructorSuccess = false;
+            return array('error_msg' => 'Error: PHP curl extension not available');
+        }
+        if (empty($cwp7Host) || empty($token)) {
+            $this->constructorSuccess = false;
+            return array('error_msg' => 'Error: Server login info missing, check server configuration');
+        }
+        if($secure) {
+            $this->cwp7ConType = 'https://';
+            $this->cwp7Secure = true;
+        } else {
+            $this->cwp7ConType = 'http://';
+            $this->cwp7Secure = false;
+        }
+        $cwp7Hostname = explode(':', $cwp7Host);
+        if (gethostbyname($cwp7Hostname[0]) == $cwp7Hostname[0] && !filter_var($cwp7Hostname[0], FILTER_VALIDATE_IP)) {
+            $this->constructorSuccess = false;
+            return array('error_msg' => 'Error: Cannot resolve ' . $cwp7Hostname[0] . ', check server configuration');
+        }
+        $this->cwp7Port = (isset($cwp7Hostname[1])) ? $cwp7Hostname[1] :  '2304';
+        $this->cwp7URL = $this->cwp7ConType . $cwp7Hostname[0] . ':' . $this->cwp7Port;
+        $this->cwp7Token = $token;
+        $this->constructorSuccess = true;
+    }
+
+    public function constructorSuccess() {
+        return $this->constructorSuccess;
+    }
+	/**
+	 * getAllAccounts
+	 * 
+	 * @return array of cwp7 accounts array of informations or error message
+	 */
+    public function getAllAccounts() {
+        $data = array();
+        return $this->doRequest('account', 'list', $data);
+    }
+	/**
+	 * getAccount
+	 * 
+	 * @param string $user user
+	 * 
+	 * @return array of account informations or error message
+	 */
+    public function getAccount($user) {
+        $data = array(
+            "user" => $user
+        );
+        return $this->doRequest('accountdetail', 'list', $data);
+    }
+	/**
+	 * createAccount
+	 * 
+	 * @param array $params avvount informations, email required.
+     * 
+	 * @return array of account informations or error message
+	 */
+    public function createAccount($params) {
+        if(!isset($params['package'])) {
+            return array('error_msg' => 'Error: missing parameter package');
+        }
+        if(!isset($params['domain'])) {
+            return array('error_msg' => 'Error: missing parameter domain');
+        }
+        if(!isset($params['user'])) {
+            return array('error_msg' => 'Error: missing parameter user');
+        }
+        if(!isset($params['pass'])) {
+            return array('error_msg' => 'Error: missing parameter pass');
+        }
+        if(!isset($params['email'])) {
+            return array('error_msg' => 'Error: missing parameter email');
+        }
+        if(!isset($params['inode'])) {
+            return array('error_msg' => 'Error: missing parameter inode');
+        }
+        if(!isset($params['nofile'])) {
+            return array('error_msg' => 'Error: missing parameter nofile');
+        }
+        if(!isset($params['nproc'])) {
+            return array('error_msg' => 'Error: missing parameter nproc');
+        }
+        if(!isset($params['server_ips'])) {
+            return array('error_msg' => 'Error: missing parameter server_ips');
+        }
+        if(!isset($params['autossl'])) {
+            $params['autossl'] = 0;
+        }
+        $data = array(
+            'domain'        => $params['domain'],
+            'user'          => $params['user'],
+            'username'      => $params['user'],
+            'pass'          => base64_encode($params['pass']),
+            'email'         => $params['email'],
+            'package'       => $params['package'],
+            'autossl'       => $params['autossl'],
+            'encodepass'    => true,
+			'inode'         => $params['inode'],
+            'limit_nofile'  => $params['nofile'],
+            'limit_nproc'   => $params['nproc'],
+            'server_ips'    => $params['server_ips'],
+        );
+        return $this->doRequest('account', 'add', $data);
+	}
+	/**
+	 * modifyAccount
+	 * 
+	 * @param array $params account informations, user, e-mail & new package required.
+     * 
+	 * @return array status -> OK or error message
+	 */
+    public function modifyAccount($params) {
+        if(!isset($params['user'])) {
+            return array('error_msg' => 'Error: missing parameter user');
+        }
+        if(!isset($params['email'])) {
+            return array('error_msg' => 'Error: missing parameter email');
+        }
+        if(!isset($params['package'])) {
+            return array('error_msg' => 'Error: missing parameter package');
+        }
+        return $this->doRequest('account', 'udp', $params);
+	}
+	/**
+	 * deleteAccount
+	 * 
+	 * @param array user & e-mail required
+	 * 
+	 * @return array success => true or error message
+	 */
+    public function deleteAccount($params)
+	{
+        if(!isset($params['user'])) {
+            return array('error_msg' => 'Error: missing parameter user');
+        }
+        if(!isset($params['email'])) {
+            return array('error_msg' => 'Error: missing parameter email');
+        }
+        $data = array(
+            "user"          => $params['user'],
+            "email"         => $params['email'],
+        );
+        return $this->doRequest('account', 'del', $data);
+	}
+	/**
+	 * suspendAccount
+	 * 
+	 * @param string $user user
+	 * 
+	 * @return array success => true or error message
+	 */
+    public function suspendAccount($user)
+	{
+        $data = array(
+            "user" => $user,
+        );
+        return $this->doRequest('account', 'susp', $data);
+	}
+	/**
+	 * unsuspendAccount
+	 * 
+	 * @param string $user user
+	 * 
+	 * @return array success => true or error message
+	 */
+    public function unsuspendAccount($user)
+	{
+        $data = array(
+            'user' => $user,
+        );
+        return $this->doRequest('account', 'unsp', $data);
+	}
+	/**
+	 * getPackages
+	 * 
+	 * @return array packages
+	 */
+    public function getPackages()
+	{
+        $data = array();
+        return $this->doRequest('packages', 'list', $data);
+    }
+	/**
+	 * changePassword
+	 * 
+	 * @return array packages
+	 */
+    public function changePass($params)
+	{
+        if(!isset($params['user'])) {
+            return array('error_msg' => 'Error: missing parameter user');
+        }
+        if(!isset($params['password'])) {
+            return array('error_msg' => 'Error: missing parameter password');
+        }
+        $data = array(
+            'user' => $params['user'],
+            'password' => $params['password'],
+        );
+        return $this->doRequest('changepass', 'upd', $data);
+    }
+    /**
+	 * addDomain
+     * 
+     * @param array $user user, $name domainname, $type domain or subdomain
+	 * 
+	 * @return array details
+	 */
+    public function addDomain($params)
+	{
+        if(!isset($params['user'])) {
+            return array('error_msg' => 'Error: missing parameter user');
+        }
+        if(!isset($params['name'])) {
+            return array('error_msg' => 'Error: missing parameter name');
+        }
+        if(!isset($params['type'])) {
+            return array('error_msg' => 'Error: missing parameter type');
+        }
+        $data = array(
+            'user'      => $params['user'],
+            'type'      => $params['type'],
+            'name'      => $params['name'],
+            'path'      => '/domains/' . $params['name'],
+            'autossl'   => 0,
+        );
+        return $this->doRequest('admindomains', 'add', $data);
+    }
+    /**
+	 * deleteDomain
+     * 
+     * @param array $user user, $name domainname, $type domain or subdomain
+	 * 
+	 * @return array details
+	 */
+    public function deleteDomain($params)
+	{
+        if(!isset($params['user'])) {
+            return array('error_msg' => 'Error: missing parameter user');
+        }
+        if(!isset($params['name'])) {
+            return array('error_msg' => 'Error: missing parameter name');
+        }
+        if(!isset($params['type'])) {
+            return array('error_msg' => 'Error: missing parameter type');
+        }
+        $data = array(
+            'user'      => $params['user'],
+            'type'      => $params['type'],
+            'name'      => $params['name'],
+        );
+        return $this->doRequest('admindomains', 'del', $data);
+    }
+    /**
+	 * getQuota
+     * 
+     * @param string $user user
+	 * 
+	 * @return array quota details
+	 */
+    public function getQuota($user)
+	{
+        $data = array('user' => $user);
+        return $this->doRequest('accountquota', 'list', $data);
+    }
+	/**
+	 * getAutoSSL
+     * 
+     * @param string $user user
+	 * 
+	 * @return array certificate data or error
+	 */
+    public function getAutoSSL($user)
+	{
+        $data = array('user' => $user);
+        return $this->doRequest('autossl', 'list', $data);
+    }
+	/**
+	 * addAutoSSL
+     * 
+     * @param array $user user, $name domainname
+	 * 
+	 * @return array status or error
+	 */
+    public function addAutoSSL($params)
+	{
+        if(!isset($params['user'])) {
+            return array('error_msg' => 'Error: missing parameter user');
+        }
+        if(!isset($params['name'])) {
+            return array('error_msg' => 'Error: missing parameter name');
+        }
+        $data = array('user' => $params['user'], 'name' => $params['name']);
+        return $this->doRequest('autossl', 'add', $data);
+    }
+	/**
+	 * renewAutoSSL
+     * 
+     * @param array $user user, $name cert name
+	 * 
+	 * @return array status or error
+	 */
+    public function updateAutoSSL($params)
+	{
+        if(!isset($params['user'])) {
+            return array('error_msg' => 'Error: missing parameter user');
+        }
+        if(!isset($params['name'])) {
+            return array('error_msg' => 'Error: missing parameter name');
+        }
+        $data = array('user' => $params['user'], 'name' => $params['name']);
+        return $this->doRequest('autossl', 'renew', $data);
+    }
+	/**
+	 * delAutoSSL
+     * 
+     * @param array $user user, $name doaminname
+	 * 
+	 * @return array status or error
+	 */
+    public function delAutoSSL($params)
+	{
+        if(!isset($params['user'])) {
+            return array('error_msg' => 'Error: missing parameter user');
+        }
+        if(!isset($params['name'])) {
+            return array('error_msg' => 'Error: missing parameter name');
+        }
+        $data = array('user' => $params['user'], 'name' => $params['name']);
+        return $this->doRequest('autossl', 'del', $data);
+    }
+	/**
+	 * getServerType
+	 * 
+	 * @return array status or error
+	 */
+    public function getServerType()
+	{
+        $data = array();
+        return $this->doRequest('typeserver', 'list', $data);
+    }
+	/**
+	 * getLoginLink
+	 * 
+	 * @return array status or error
+	 */
+    public function getLoginLink($user, $timer=5)
+	{
+        $data = array('user' => $user, 'timer' => $timer);
+        return $this->doRequest('user_session', 'list', $data);
+    }
+    /**
+     * doRequest
+     * 
+     * @param string $endpoint API endpoint
+     * @param string $action endpoint action
+     * @param array $data POST data
+     * 
+     * @return string API response
+     */
+    protected function doRequest($endpoint, $action, $data) {
+        $data['key'] = $this->cwp7Token;
+        $data['action'] = $action;
+//        $data['debug'] = 1;
+        $ch = curl_init();
+        curl_setopt($ch, CURLOPT_URL, $this->cwp7URL . '/v1/' . $endpoint);
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
+        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
+        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
+        curl_setopt($ch, CURLOPT_POST, 1);
+        $response = curl_exec($ch);
+        if(curl_getinfo($ch, CURLINFO_RESPONSE_CODE) != 200) {
+            curl_close($ch);
+            return array('status' => 'Error', 'err_msg' => curl_error($ch));
+        };
+        curl_close($ch);
+        return json_decode($response, true);
+    }
+}

+ 9 - 0
api/config.php

@@ -0,0 +1,9 @@
+<?php
+////////////
+// Config //
+////////////
+
+$TDHostingHost = '';
+$TDHostingToken = '';
+
+?>

+ 146 - 0
api/test.php

@@ -0,0 +1,146 @@
+<?php
+
+/**
+ * test.php
+ *
+ * contains examples about how to use 
+ * class methods for Sf_Admin
+ *
+ * @author André Genrich <andre.genrich@thurdata.ch>
+ * @version 1
+ * @copyright Copyright (c) Thurdata GmbH 2020
+ * @license GPL
+ * @name test.php
+ */
+
+/////////////
+// Require //
+/////////////
+
+require_once('config.php');
+require_once('cwp7/Admin.php');
+
+//////////
+// Args //
+//////////
+
+if(PHP_SAPI != 'cli')
+	$args = $_GET;
+else
+	$args = parse_args($argv);
+
+if(isset($args['action']))
+{
+	$action = $args['action'];
+}
+else
+{
+	echo 'No action, exiting' . PHP_EOL;
+	exit (-1);
+}
+
+function parse_args($argv){
+	array_shift($argv);
+	$out = array();
+	foreach ($argv as $arg){
+		if (substr($arg,0,2) == '--'){
+			$eqPos = strpos($arg,'=');
+			if ($eqPos === false){
+				$key = substr($arg,2);
+				$out[$key] = isset($out[$key]) ? $out[$key] : true;
+			} else {
+				$key = substr($arg,2,$eqPos-2);
+				$out[$key] = substr($arg,$eqPos+1);
+			}
+		} else if (substr($arg,0,1) == '-'){
+			if (substr($arg,2,1) == '='){
+				$key = substr($arg,1,1);
+				$out[$key] = substr($arg,3);
+			} else {
+				$chars = str_split(substr($arg,1));
+				foreach ($chars as $char){
+					$key = $char;
+					$out[$key] = isset($out[$key]) ? $out[$key] : true;
+				}
+			}
+		} else {
+			$out[] = $arg;
+		}
+	}
+	return $out;
+}
+
+/////////////////
+// Constructor //
+/////////////////
+
+$cwp7 = new cwp7_Admin($cwp7Host, $cwp7Token);
+$r = $cwp7->constructorSuccess();
+if(isset($r['error_msg'])) {
+	echo 'Error : cannot construct :-(' . PHP_EOL;
+	print_r($r);
+	exit();
+}
+
+/////////////
+// Actions //
+/////////////
+
+if($action == 'gaa')
+{
+    $r = $cwp7->getAllAccounts();
+	if($r['status'] == 'Error') {
+        echo 'Error : could not fetch list of accounts on '. $cwp7Host . ' :-(' . PHP_EOL;
+	} else {
+        echo 'OK : got a list of '. count($r['msj']) . ' accounts on ' . $cwp7Host . ' :-)' . PHP_EOL;
+    }
+	print_r($r);
+}
+
+// Get Account Informations
+if($action == 'gai')
+{
+	$r = $cwp7->getAccount($args['account_name']);
+	if($r['status'] == 'Error') {
+        echo 'Error : could not fetch information of '. $args['account_name'] . ' :-(' . PHP_EOL;
+	} else {
+		echo 'OK : got the infos for account ' . $args['account_name'] . ' :-)' . PHP_EOL;
+    }
+	print_r($r);
+}
+
+// Get all Packages
+if($action == 'gap')
+{
+	$r = $cwp7->getPackages();
+	if($r['status'] == 'Error') {
+        echo 'Error : could not fetch information of packages :-(' . PHP_EOL;
+	} else {
+		echo 'OK : got the infos of ' . count($r['msj']) . ' packages :-)' . PHP_EOL;
+    }
+	print_r($r);
+}
+
+// Get Quota Informations
+if($action == 'gqu')
+{
+	$r = $cwp7->getQuota($args['account_name']);
+	if($r['status'] == 'Error') {
+        echo 'Error : could not fetch quota information of '. $args['account_name'] . ' :-(' . PHP_EOL;
+	} else {
+		echo 'OK : got the quota infos for account ' . $args['account_name'] . ' :-)' . PHP_EOL;
+    }
+	print_r($r);
+}
+
+// Get AutoSSL Informations
+if($action == 'gas')
+{
+	$r = $cwp7->getAutoSSL($args['account_name']);
+	if($r['status'] == 'Error') {
+        echo 'Error : could not fetch AutoSSL information of '. $args['account_name'] . ' :-(' . PHP_EOL;
+	} else {
+		echo 'OK : got the AutoSSL infos for account ' . $args['account_name'] . ' :-)' . PHP_EOL;
+    }
+	print_r($r);
+}

+ 570 - 0
clientarea.tpl

@@ -0,0 +1,570 @@
+{*
+ **********************************************************
+ * Developed by: Team Theme Metro
+ * Website: http://www.thememetro.com
+ * Customized ny thurdata
+ **********************************************************
+*}
+{if $modulechangepwresult}
+  {if $modulechangepwresult == "success"}
+    {include file="$template/includes/alert.tpl" type="success" msg=$modulechangepasswordmessage textcenter=true}
+  {elseif $modulechangepwresult == "error"}
+    {include file="$template/includes/alert.tpl" type="error" msg=$modulechangepasswordmessage|strip_tags textcenter=true}
+  {/if}
+{/if}
+{if $pendingcancellation}
+  {include file="$template/includes/alert.tpl" type="error" msg=$LANG.cancellationrequestedexplanation textcenter=true idname="alertPendingCancellation"}
+{/if}
+{if $unpaidInvoice}
+  <div class="alert alert-{if $unpaidInvoiceOverdue}danger{else}warning{/if}"
+    id="alert{if $unpaidInvoiceOverdue}Overdue{else}Unpaid{/if}Invoice">
+    <div class="pull-right">
+      <a href="viewinvoice.php?id={$unpaidInvoice}" class="btn btn-xs btn-default">
+        {lang key='payInvoice'}
+      </a>
+    </div>
+    {$unpaidInvoiceMessage}
+  </div>
+{/if}
+<div class="tab-content margin-bottom">
+  <div class="tab-pane fade show active" id="tabOverview">
+    {if $tplOverviewTabOutput}
+      {$tplOverviewTabOutput}
+    {else}
+      <div class="section">
+        <div class="product-details">
+          <div class="row row-eq-height row-eq-height-sm">
+            <div class="col-md-6">
+              <div class="product-holder product-status-{$rawstatus|strtolower}" style="min-height: unset; height:210px">
+                <div class="product-content">
+                  <div class="product-image">
+                    <div class="feature-icon">
+                      <img src="/templates/croster/thurdata/productgroups/{$gid}.svg" class="img-fluid"
+                        style="height:100px;">
+                    </div>
+                  </div>
+                  <h4><small>Hosting Account</small> - {$domain}</h4>
+                  <div class="status-sticker-wrapper">
+                    <div class="status-sticker product-status-{$rawstatus|strtolower}">
+                      {$status}
+                    </div>
+                  </div>
+                </div>
+              </div>
+            </div>
+            <div class="col-md-6">
+              <div class="product-info" style="min-height: unset; height:210px;">
+                <table width="100%" border="0">
+                  <tr>
+                    <td class="list-heading" style="font-size: 85%;">{$LANG.clientareahostingregdate}</td>
+                    <td class="list-text" style="font-size: 85%;">{$regdate}</td>
+                  </tr>
+                  {if $billingcycle ne {lang key='orderpaymenttermfreeaccount'}}
+                    <tr>
+                      <td class="list-heading" style="font-size: 85%;">{$LANG.firstpaymentamount}</td>
+                      <td class="list-text" style="font-size: 85%;">{$firstpaymentamount}</td>
+                    </tr>
+                    <tr>
+                      <td class="list-heading" style="font-size: 85%;">{$LANG.recurringamount}</td>
+                      <td class="list-text" style="font-size: 85%;">{$recurringamount}</td>
+                    </tr>
+                    <tr>
+                      <td class="list-heading" style="font-size: 85%;">{$LANG.orderbillingcycle}</td>
+                      <td class="list-text" style="font-size: 85%;">{$billingcycle}</td>
+                    </tr>
+                    <tr>
+                      <td class="list-heading" style="font-size: 85%;">{$LANG.clientareahostingnextduedate}</td>
+                      <td class="list-text" style="font-size: 85%;">{$nextduedate}</td>
+                    </tr>
+                    <tr>
+                      <td class="list-heading" style="font-size: 85%;">{$LANG.orderpaymentmethod}</td>
+                      <td class="list-text" style="font-size: 85%;">{$paymentmethod}</td>
+                    </tr>
+                  {else}
+                    <tr>
+                      <td class="list-heading" style="font-size: 85%;"><strong>Trial Account</strong></td>
+                      {if $rawstatus eq "terminated"}
+                        <td class="list-text" style="font-size:85%;">
+                          {lang key='domainRenewal.expiredDaysAgo' days=((($smarty.now - ($regdate|@strtotime)) / 86400)|round) - 14}
+                        </td>
+                      {elseif 1123200 > ($smarty.now - ($regdate|@strtotime)) && ($smarty.now - ($regdate|@strtotime)) > 950400}
+                        {* wenn Heute - RegisterDatum < 13 Tage && > 11 Tage *}
+                        <td class="list-text" style="color:orange; font-size:85%">
+                          {lang key='domainRenewal.expiringIn' days=(14 - (($smarty.now - ($regdate|@strtotime)) / 86400)|round)}
+                        </td>
+                      {elseif ($smarty.now - ($regdate|@strtotime)) > 1123200} {* wenn Heute - RegisterDatum > 13 Tage *}
+                        <td class="list-text" style="color:red; font-size:85%;">{lang key='trialLastDay'}</td>
+                      {else}
+                        <td class="list-text" style="font-size: 85%;">
+                          {lang key='domainRenewal.expiringIn' days=(14 - (($smarty.now - ($regdate|@strtotime)) / 86400)|round)}
+                        </td>
+                      {/if}
+                    </tr>
+                    <tr>
+                      <td colspan="2"><br /><br /></td>
+                    </tr>
+                    <tr>
+                      <td></td>
+                      <td>
+                        {if $rawstatus eq "terminated"}
+                          <a href="/cart.php?gid={$gid}" class="btn btn-block btn-primary">{lang key='orderNow'}</a>
+                        {else}
+                          <a href="/upgrade.php?type=package&id={$id}"
+                            class="btn btn-block btn-primary">{lang key='upgradeNow'}</a>
+                        {/if}
+                      </td>
+                    </tr>
+                  {/if}
+                </table>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+      {*
+        {if $showcancelbutton || $packagesupgrade}
+          <div class="row">
+            {if $packagesupgrade}
+              <div class="col-xs-{if $showcancelbutton}6{else}12{/if}">
+                <a href="upgrade.php?type=package&amp;id={$id}" class="btn btn-block btn-primary">{$LANG.upgrade}</a>
+              </div>
+            {/if}
+            {if $showcancelbutton}
+              <div class="col-xs-{if $packagesupgrade}6{else}12{/if}">
+                <a href="clientarea.php?action=cancel&amp;id={$id}" class="btn btn-block btn-danger {if $pendingcancellation}disabled{/if}">{if $pendingcancellation}{$LANG.cancellationrequested}{else}{$LANG.clientareacancelrequestbutton}{/if}</a>
+              </div>
+            {/if}
+          </div>
+        {/if}
+      *}
+      {if $systemStatus == 'Active'}
+        {foreach $hookOutput as $output}
+          <div class="section">
+            <div>
+              {$output}
+            </div>
+            <div class=" clearfix"></div>
+          </div>
+        {/foreach}
+        {if $moduleclientarea || $lastupdate}
+          <div class="section">
+            <div class="card panel panel-tabs">
+              <div class="card-header">
+                <ul class="nav nav-pills card-header-pills flex-column flex-md-row">
+                  {if $moduleclientarea}
+                    <li class="nav-item">
+                      <a href="#manage" data-toggle="tab" class="nav-link active"><i class="fas fa-globe fa-fw"></i>
+                        {lang key='manage'}</a>
+                    </li>
+                  {/if}
+                  {if $lastupdate}
+                    <li class="nav-item">
+                      <a href="#resourceusage" data-toggle="tab" class="nav-link{if !$moduleclientarea} active{/if}"><i
+                          class="fas fa-inbox fa-fw"></i> {lang key='resourceUsage'}</a>
+                    </li>
+                  {/if}
+                  <a href="{$systemurl}clientarea.php?action=productdetails&id={$serviceid}&dosinglesignon=1"
+                    class="nav-link active" target=_blank style="margin-left: auto;">
+                    <i class="fas fa-sign-in fa-fw"></i> CWP Login
+                  </a>
+                </ul>
+              </div>
+              <div class="card-body">
+                <div class="tab-content">
+                  {if $moduleclientarea}
+                    <div class="tab-pane fade show active" role="tabpanel" id="manage" align="center">
+                      <div class="col-sm-12">
+                        <h4>{lang key='overview'}</h4>
+                        {if $domains|count > 0}
+                          {foreach $domains as $domain}
+                            <div style="font-size:85%;color:#999;">Domain</div>
+                            <table style="width:100%;border-collapse:collapse;border:1px solid grey;">
+                              <tr style="font-size:85%;background-color:#0273d4;color:#fff;">
+                                <th style="width:25%;text-align:left;padding:5px;">
+                                  DOMAIN NAME
+                                </th>
+                                <th style="min-width:50px;text-align:center;padding:5px;">
+                                </th>
+                                <th style="width:50%;text-align:left;padding:5px;">
+                                  WEBROOT
+                                </th>
+                                <th style="min-width:50px;text-align:center;padding:5px;" title="DNS Status">
+                                  DNS
+                                </th>
+                                <th style="min-width:50px;text-align:center;padding:5px;" title="SSL Status">
+                                  SSL
+                                </th>
+                                <th style="min-width:50px;text-align:center;padding:5px;" title="Gültigkeit des Zertifikats in Tagen">
+                                  EXP
+                                </th>
+                              </tr>
+                              <tr style="background-color:#ddd;">
+                                <td style="text-align:left;padding:5px;">
+                                  {if $domain.DNS == 1}<a class="btn-link" href="http{if $domain.ssl == 1}s{/if}://www.{$domain.domain}" target="_blank">{/if}
+                                  <strong>{$domain.domain}</strong><br /><small>www.{$domain.domain}</small>
+                                  {if $domain.DNS == 1}</a>{/if}
+                                </td>
+                                <td style="text-align:left;padding:5px;">
+                                  <form method="post" action="clientarea.php?action=productdetails">
+                                    <input type="hidden" name="id" value="{$serviceid}" />
+                                    <input type="hidden" name="modop" value="custom" />
+                                    <input type="hidden" name="a" value="delDomainConfirm" />
+                                    <input type="hidden" name="d" value="{$domain.domain}" />
+                                    <button title="Domain löschen" type="submit" class="fabutton" style="background:none;padding:0px;border:none;" {if $domain.subdomains|count > 0}disabled{/if}>
+                                      <i class="fas fa-trash fa-fw"></i>
+                                    </button>
+                                  </form>
+                                </td>
+                                <td style="text-align:left;padding:5px;">
+                                  {$domain.relpath}
+                                </td>
+                                <td style="text-align:center;padding:5px;border-left:1px dotted black;">
+                                  {if $domain.DNS == 1}
+                                    {if $domain.domainNS == 'self'}
+                                      <form method="post" action="clientarea.php?action=productdetails">
+                                        <input type="hidden" name="id" value="{$serviceid}" />
+                                        <input type="hidden" name="modop" value="custom" />
+                                        <input type="hidden" name="a" value="unsetDNSConfirm" />
+                                        <input type="hidden" name="d" value="{$domain.domain}" />
+                                        <button title="DNS deaktivieren" type="submit" class="fabutton" style="background:none;padding:0px;border:none;">
+                                          <i class="fas fa-power-off fa-fw" style="color:green;"></i>
+                                        </button>
+                                      </form>
+                                    {else}
+                                      <form method="post" action="clientarea.php?action=productdetails">
+                                        <input type="hidden" name="id" value="{$serviceid}" />
+                                        <input type="hidden" name="modop" value="custom" />
+                                        <input type="hidden" name="a" value="infoDNS" />
+                                        <input type="hidden" name="d" value="{$domain.domain}" />
+                                        <button title="DNS Info" type="submit" class="fabutton" style="background:none;padding:0px;border:none;">
+                                          <i class="fas fa-power-off fa-fw" style="color:green;"></i>
+                                        </button>
+                                      </form>
+                                    {/if}  
+                                  {else}
+                                    {if $domain.domainNS == 'self'}
+                                      <form method="post" action="clientarea.php?action=productdetails">
+                                        <input type="hidden" name="id" value="{$serviceid}" />
+                                        <input type="hidden" name="modop" value="custom" />
+                                        <input type="hidden" name="a" value="setDNSConfirm" />
+                                        <input type="hidden" name="d" value="{$domain.domain}" />
+                                        <button title="DNS aktivieren" type="submit" class="fabutton" style="background:none;padding:0px;border:none;">
+                                          <i class="fas fa-power-off fa-fw"></i>
+                                        </button>
+                                      </form>
+                                    {else}
+                                      <form method="post" action="clientarea.php?action=productdetails">
+                                        <input type="hidden" name="id" value="{$serviceid}" />
+                                        <input type="hidden" name="modop" value="custom" />
+                                        <input type="hidden" name="a" value="infoDNS" />
+                                        <input type="hidden" name="d" value="{$domain.domain}" />
+                                        <button title="DNS Info" type="submit" class="fabutton" style="background:none;padding:0px;border:none;">
+                                          <i class="fas fa-power-off fa-fw" style="color:red;"></i>
+                                        </button>
+                                      </form>
+                                    {/if}
+                                  {/if}
+                                </td>
+                                <td style="text-align:center;padding:5px;border-left:1px dotted black;">
+                                  {if $domain.ssl == 1}
+                                    <form method="post" action="clientarea.php?action=productdetails">
+                                      <input type="hidden" name="id" value="{$serviceid}" />
+                                      <input type="hidden" name="modop" value="custom" />
+                                      <input type="hidden" name="a" value="renewSSLConfirm" />
+                                      <input type="hidden" name="d" value="{$domain.domain}" />
+                                      <button title="Zertifikat erneuern" type="submit" class="fabutton" style="background:none;padding:0px;border:none;">
+                                        <i class="fas fa-repeat fa-fw" style="color:green;"></i>
+                                      </button>
+                                    </form>
+                                  {else}
+                                    {if $domain.DNS == 1}
+                                    <form method="post" action="clientarea.php?action=productdetails">
+                                      <input type="hidden" name="id" value="{$serviceid}" />
+                                      <input type="hidden" name="modop" value="custom" />
+                                      <input type="hidden" name="a" value="enableSSLConfirm" />
+                                      <input type="hidden" name="d" value="{$domain.domain}" />
+                                      <button title="SSL aktivieren" type="submit" class="fabutton" style="background:none;padding:0px;border:none;">
+                                        <i class="fas fa-power-off fa-fw"></i>
+                                      </button>
+                                    </form>
+                                    {else}
+                                      <form method="post" action="clientarea.php?action=productdetails">
+                                        <input type="hidden" name="id" value="{$serviceid}" />
+                                        <input type="hidden" name="modop" value="custom" />
+                                        <input type="hidden" name="a" value="infoSSL" />
+                                        <input type="hidden" name="d" value="{$domain.domain}" />
+                                        <button title="SSL Info" type="submit" class="fabutton" style="background:none;padding:0px;border:none;">
+                                          <i class="fas fa-power-off fa-fw" style="color:red;"></i>
+                                        </button>
+                                      </form>
+                                    {/if}
+                                  {/if}
+                                </td>
+                                <td style="text-align:center;padding:5px;" title="Zertifikat ist noch {$domain.sslexpire} Tage gültig">
+                                  {if $domain.ssl == 1}
+                                    {$domain.sslexpire}
+                                  {/if}
+                                </td>
+                              </tr>
+                              {if $domain.subdomains}
+                                {foreach $domain.subdomains as $subdomain}
+                                  <tr>
+                                    <td style="width:25%;text-align:left;padding:5px;font-size:90%">
+                                      {if $subdomain.DNS == 1}<a class="btn-link" href="http{if $subdomain.ssl == 1}s{/if}://{$subdomain.subdomain}.{$subdomain.domain}" target="_blank">{/if}
+                                      &nbsp;{$subdomain.subdomain}.{$subdomain.domain}
+                                      {if $subdomain.DNS == 1}</a>{/if}
+                                    </td>
+                                    <td style="min-width:50px;text-align:left;padding:5px;">
+                                      <form method="post" action="clientarea.php?action=productdetails">
+                                        <input type="hidden" name="id" value="{$serviceid}" />
+                                        <input type="hidden" name="modop" value="custom" />
+                                        <input type="hidden" name="a" value="delSubdomainConfirm" />
+                                        <input type="hidden" name="d" value="{$subdomain.subdomain}.{$subdomain.domain}" />
+                                        <button title="Subdomain löschen" type="submit" class="fabutton" style="background:none;padding:0px;border:none;">
+                                          <i class="fas fa-trash fa-fw"></i>
+                                        </button>
+                                      </form>
+                                    </td>
+                                    <td style="width:50%;text-align:left;padding:5px;">
+                                      {$subdomain.relpath}
+                                    </td>
+                                    <td style="min-width:50px;text-align:center;padding:5px;border-left:1px dotted black;">
+                                      {if $subdomain.DNS == 1}
+                                        <form method="post" action="clientarea.php?action=productdetails">
+                                          <input type="hidden" name="id" value="{$serviceid}" />
+                                          <input type="hidden" name="modop" value="custom" />
+                                          <input type="hidden" name="a" value="unsetDNSConfirm" />
+                                          <input type="hidden" name="d" value="{$subdomain.domain}" />
+                                          <input type="hidden" name="s" value="{$subdomain.subdomain}" />
+                                          <button title="DNS deaktivieren" type="submit" class="fabutton" style="background:none;padding:0px;border:none;">
+                                            <i class="fas fa-power-off fa-fw" style="color:green;"></i>
+                                          </button>
+                                        </form>
+                                      {else}
+                                        {if $domain.domainNS == 'self'}
+                                          <form method="post" action="clientarea.php?action=productdetails">
+                                            <input type="hidden" name="id" value="{$serviceid}" />
+                                            <input type="hidden" name="modop" value="custom" />
+                                            <input type="hidden" name="a" value="setDNSConfirm" />
+                                            <input type="hidden" name="d" value="{$subdomain.domain}" />
+                                            <input type="hidden" name="s" value="{$subdomain.subdomain}" />
+                                            <button title="DNS aktivieren" type="submit" class="fabutton" style="background:none;padding:0px;border:none;">
+                                              <i class="fas fa-power-off fa-fw"></i>
+                                            </button>
+                                          </form>
+                                        {else}
+                                          <form method="post" action="clientarea.php?action=productdetails">
+                                            <input type="hidden" name="id" value="{$serviceid}" />
+                                            <input type="hidden" name="modop" value="custom" />
+                                            <input type="hidden" name="a" value="infoDNS" />
+                                            <input type="hidden" name="d" value="{$subdomain.domain}" />
+                                            <button title="DNS Info" type="submit" class="fabutton" style="background:none;padding:0px;border:none;">
+                                              <i class="fas fa-power-off fa-fw" style="color:red;"></i>
+                                            </button>
+                                          </form>
+                                        {/if}
+                                      {/if}
+                                    </td>
+                                    <td style="min-width:50px;text-align:center;padding:5px;border-left:1px dotted black;">
+                                      {if $subdomain.ssl == 1}
+                                        <form method="post" action="clientarea.php?action=productdetails">
+                                          <input type="hidden" name="id" value="{$serviceid}" />
+                                          <input type="hidden" name="modop" value="custom" />
+                                          <input type="hidden" name="a" value="renewSSLConfirm" />
+                                          <input type="hidden" name="d" value="{$subdomain.subdomain}.{$subdomain.domain}" />
+                                          <button title="Zertifikat erneuern" type="submit" class="fabutton" style="background:none;padding:0px;border:none;">
+                                            <i class="fas fa-repeat fa-fw" style="color:green;"></i>
+                                          </button>
+                                        </form>
+                                      {else}
+                                        {if $subdomain.DNS == 1}
+                                          <form method="post" action="clientarea.php?action=productdetails">
+                                            <input type="hidden" name="id" value="{$serviceid}" />
+                                            <input type="hidden" name="modop" value="custom" />
+                                            <input type="hidden" name="a" value="enableSSLConfirm" />
+                                            <input type="hidden" name="d" value="{$subdomain.subdomain}.{$subdomain.domain}" />
+                                            <button title="SSL aktivieren" type="submit" class="fabutton" style="background:none;padding:0px;border:none;">
+                                              <i class="fas fa-power-off fa-fw"></i>
+                                            </button>
+                                          </form>
+                                        {else}
+                                          <form method="post" action="clientarea.php?action=productdetails">
+                                            <input type="hidden" name="id" value="{$serviceid}" />
+                                            <input type="hidden" name="modop" value="custom" />
+                                            <input type="hidden" name="a" value="infoSSL" />
+                                            <input type="hidden" name="d" value="{$subdomain.subdomain}.{$subdomain.domain}" />
+                                            <button title="SSL Info" type="submit" class="fabutton" style="background:none;padding:0px;border:none;">
+                                              <i class="fas fa-power-off fa-fw" style="color:red;"></i>
+                                            </button>
+                                          </form>
+                                        {/if}
+                                      {/if}
+                                    </td>
+                                    <td style="min-width:50px;text-align:center;padding:5px;">
+                                      {if $subdomain.ssl == 1}
+                                        {$subdomain.sslexpire}
+                                      {/if}
+                                    </td>
+                                  </tr>
+                                {/foreach}
+                              {/if}
+                              <tr>
+                                <td colspan=6 style="border-top:1px solid grey;">
+                                  <form method="post" action="clientarea.php?action=productdetails">
+                                    <input type="hidden" name="id" value="{$serviceid}" />
+                                    <input type="hidden" name="modop" value="custom" />
+                                    <input type="hidden" name="a" value="newSubdomain" />
+                                    <input type="hidden" name="d" value="{$domain.domain}" />
+                                    <button type="submit" class="fabutton" style="background:none;border:none;font-size:75%;" {if $subdomainlimit == 1}disabled="disabled" title="Subdomain Limit erreicht!"{else}title="Neue Subdomain"{/if}>
+                                      <i class="fas fa-plus fa-fw"></i> Neue Subdomain
+                                    </button>
+                                  </form>
+                                </td>
+                              </tr>
+                            </table>
+                          {/foreach}
+                        {/if}
+                        <form method="post" action="clientarea.php?action=productdetails">
+                          <input type="hidden" name="id" value="{$serviceid}" />
+                          <input type="hidden" name="modop" value="custom" />
+                          <input type="hidden" name="a" value="newDomain" />
+                          <button type="submit" class="btn btn-primary" style="margin-top:20px;" {if $domainlimit == 1}disabled="disabled" title="Domain Limit erreicht!"{else}title="Neue Domain"{/if}>
+                            <i class="fas fa-plus fa-fw"></i> Neue Domain
+                          </button>
+                        </form>
+                      </div>
+                    </div>
+                  {/if}
+                  <div class="tab-pane fade" role="tabpanel" id="resourceusage" align="center">
+                    <table>
+                      <tr>
+                        <td class="col-sm-6 text-sm-center">
+                          <h4>Domains</h4>
+                          <input type="text" value="{$addons_domains_used}" class="dial-usage" data-width="100"
+                            data-height="100" data-min="0" data-max="{$addons_domains}" data-readOnly="true" />
+                          <p>{$addons_domains_used} / {$addons_domains}</p>
+                        </td>
+                        <td class="col-sm-6 text-sm-center">
+                          <h4>Subdomains</h4>
+                          <input type="text" value="{$sub_domains_used}" class="dial-usage" data-width="100"
+                            data-height="100" data-min="0" data-max="{$sub_domains}" data-readOnly="true" />
+                          <p>{$sub_domains_used} / {$sub_domains}</p>
+                        </td>
+                      </tr>
+                      <tr>
+                        <td class="col-sm-6 text-sm-center">
+                          <h4>{lang key='diskSpace'}</h4>
+                          <input type="text" value="{$diskpercent|substr:0:-1}" class="dial-usage" data-width="100"
+                            data-height="100" data-min="0" data-readOnly="true" />
+                          <p>{($space_usage / 1024)|round:1} GB / {($space_disk / 1024)|round:1} GB</p>
+                        </td>
+                        <td class="col-sm-6 text-sm-center">
+                          <h4>{lang key='bandwidth'}</h4>
+                          <input type="text" value="{$bwpercent|substr:0:-1}" class="dial-usage" data-width="100"
+                            data-height="100" data-min="0" data-readOnly="true" />
+                          <p>{($bandwidth_used / 1024)|round:1} GB / {($bandwidth / 1024)|round:1} GB</p>
+                        </td>
+                      </tr>
+                      {*
+                      <tr>
+                        <td class="col-sm-6 text-sm-center">
+                          <h4>Datenbanken</h4>
+                          <input type="text" value="{$db_used}" class="dial-usage" data-width="100"
+                            data-height="100" data-min="0" data-max="{$db_max}" data-readOnly="true" />
+                          <p>{$db_used} / {$db_max}</p>
+                        </td>
+                        <td class="col-sm-6 text-sm-center">
+                          <h4>FTP Accounts</h4>
+                          <input type="text" value="{$ftp_accounts_used}" class="dial-usage" data-width="100"
+                            data-height="100" data-min="0" data-max="{$ftp_accounts}" data-readOnly="true" />
+                          <p>{$ftp_accounts_used} / {$ftp_accounts}</p>
+                        </td>
+                      </tr> 
+                    *}
+                    </table>
+                    <div class="clearfix">
+                    </div>
+                    <script src="{$BASE_PATH_JS}/jquery.knob.js"></script>
+                    <script>
+                      jQuery(function() {
+                        jQuery(".dial-usage").knob({
+                          'format': function(v) {
+                            alert(v);
+                          }
+                        });
+                      });
+                    </script>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+        {/if}
+      {else}
+        <div class="alert-lg no-data">
+          <div class="icon">
+            <i class="fas fa-exclamation-triangle"></i>
+          </div>
+          <div class="text">
+            {if $suspendreason}
+              <strong>{$suspendreason}</strong><br />
+            {/if}
+            {$LANG.cPanel.packageNotActive} {$status}.<br />
+            {if $systemStatus eq "Pending"}
+              {$LANG.cPanel.statusPendingNotice}
+            {elseif $systemStatus eq "Suspended"}
+              {$LANG.cPanel.statusSuspendedNotice}
+            {/if}
+          </div>
+        </div>
+      {/if}
+    {/if}
+  </div>
+  <div class="tab-pane fade in" id="tabChangepw">
+    <div class="section">
+      <div class="section-header">
+        <h3>{$LANG.serverchangepassword}</h3>
+        <p class="desc">Hier können Sie Ihr Passwort für {$mailaddress} ändern</p>
+      </div>
+      <div class="section-body">
+        <div class="row">
+          <div class="col-sm-7">
+            <form class=" using-password-strength" method="post"
+              action="{$smarty.server.PHP_SELF}?action=productdetails&id={$id}" role="form">
+              <input type="hidden" name="id" value="{$id}" />
+              <input type="hidden" name="modulechangepassword" value="true" />
+              <div class="TM-card">
+                <div id="newPassword1" class="form-group has-feedback">
+                  <label for="inputNewPassword1" class="control-label">{$LANG.newpassword}</label>
+                  <input type="password" class="form-control" id="inputNewPassword1" name="newpw" autocomplete="off" />
+                  <span class="form-control-feedback glyphicon"></span>
+                  {include file="$template/thurdata/thurpwcheck.tpl"}
+                </div>
+                <div class="alert alert-info">
+                  <div id='hints'>
+                    <strong id='hint2Head'></strong>
+                    <div id='hintLength'></div>
+                    <div id='hintNumeric'></div>
+                    <div id='hintSymbols'></div>
+                    <div id='hintUpperLower'></div>
+                  </div>
+                </div>
+                <div id="newPassword2" class="form-group has-feedback">
+                  <label for="inputNewPassword2" class="control-label">{$LANG.confirmnewpassword}</label>
+                  <input type="password" class="form-control" id="inputNewPassword2" name="confirmpw"
+                    autocomplete="off" />
+                  <span class="form-control-feedback glyphicon"></span>
+                  <div id="inputNewPassword2Msg">
+                  </div>
+                </div>
+              </div>
+              <div class="form-actions">
+                <input class="btn btn-primary" type="submit" value="{$LANG.clientareasavechanges}" />
+              </div>
+            </form>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>

+ 23 - 0
composer.json

@@ -0,0 +1,23 @@
+{
+    "name": "Thurdata/cwp7",
+    "description": "cwp7 Provisioing Module",
+    "version": "2.0.0",
+    "type": "project",
+    "license": "EULA",
+    "homepage": "http://www.thurdata.ch",
+    "support":
+            {
+                "email": "info@thurdata.ch",
+                "issues": "http://support.thurdata.ch",
+                "forum": "http://forum.thurdata.ch"
+            },
+    "authors": [
+	{
+	    "name": "Andre Genrich"
+	}
+    ],
+    "require":
+            {
+                "php": ">=7.1.0"
+            }
+}

+ 28 - 0
whmcs.json

@@ -0,0 +1,28 @@
+{
+  "schema": "1.0",
+  "type": "whmcs-provisioning",
+  "name": "cwp7",
+  "license": "GPL",
+  "category": "provisioning",
+  "description": {
+    "name": "cwp7",
+    "tagline": "cwp7 Provisioning Module for WHMCS.",
+    "short": "cwp7 users can be easily provoked with this module. The customer can also reset his Seafcwp7ile password.",
+    "long": "The module allows single-user provisioning of cwp7 accounts. It implements a simple seaficwp7le hosting."
+  },
+  "logo": {
+    "filename": "logo.png"
+  },
+  "support": {
+    "homepage": "https://www.thurdata.ch/whmcs",
+    "learn_more": "https://www.thurdata.ch/whmcs/#features",
+    "support_url": "https://www.thurdata.ch/support",
+    "docs_url": "https://www.thudata.ch/whmcs/docs"
+  },
+  "authors": [
+    {
+      "name": "Thurdata GmbH",
+      "homepage": "https://www.thurdata.ch/"
+    }
+  ]
+}