merge commit
This commit is contained in:
commit
0b7831549d
41 changed files with 7095 additions and 4821 deletions
38
WebsitePanel.WHMCSModule/changelog.html
Normal file
38
WebsitePanel.WHMCSModule/changelog.html
Normal file
|
@ -0,0 +1,38 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>WHMCS WebsitePanel Server Module / Addons</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>WHMCS WebsitePanel Server Module</h1>
|
||||
<p style="color: #FF0000">DO NOT CONTACT WHMCS FOR SUPPORT WITH THIS MODULE</p>
|
||||
<h3>Changelog / Updates</h3>
|
||||
<p>10-25-2014 (v3.0.4)</p>
|
||||
<ul>
|
||||
<li>Updated the bandwidth / diskspace usage - Incorrect query data resulted in calculation being incomplete or incorrect</li>
|
||||
</ul>
|
||||
<p>2-24-2014 (v3.0.3)</p>
|
||||
<ul>
|
||||
<li>Added: WHMCS module log debug calls.
|
||||
<ul>
|
||||
<li>See <a href="http://docs.whmcs.com/Troubleshooting_Module_Problems" target="new">http://docs.whmcs.com/Troubleshooting_Module_Problems</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<p>2-23-2014 (v3.0.2)</p>
|
||||
<ul>
|
||||
<li>HTTP communications now support GZIP compression (enabled by default)</li>
|
||||
</ul>
|
||||
<p>2-22-2014 (v3.0.1)</p>
|
||||
<ul>
|
||||
<li>Usage calculation now works with multiple WebsitePanel ES installations</li>
|
||||
<li>Large amount of refactoring</li>
|
||||
<li>Addon hooks (WSP Addons and WSP Client Sync) now execute only when the addon is activated</li>
|
||||
<li>Improved logging</li>
|
||||
<li>Client area "one-click login" is now a POST form instead of a link. Credentials are no longer passed through a standard HREF link</li>
|
||||
<li>Admin area "one-click login" is now a link directly to the WebsitePanel account rather than a login link to WebsitePanel</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
|
@ -1,6 +0,0 @@
|
|||
04/16/2013 (1.3)
|
||||
* Some refactoring done
|
||||
|
||||
01/29/2013 (1.2)
|
||||
* WebsitePanel addons no longer require the storage of the Enterprise Server credentials
|
||||
* Error codes are not properly resolved to their text responses
|
14
WebsitePanel.WHMCSModule/how-to-upgrade.html
Normal file
14
WebsitePanel.WHMCSModule/how-to-upgrade.html
Normal file
|
@ -0,0 +1,14 @@
|
|||
<title>WHMCS WebsitePanel Server Module / Addons</title>
|
||||
<h1>WHMCS WebsitePanel Server Module</h1>
|
||||
<p style="color: #FF0000">DO NOT CONTACT WHMCS FOR SUPPORT WITH THIS MODULE</p>
|
||||
<h3>Update from the previous available version... (The version prior to 2-23-2014)</h3>
|
||||
<ol>
|
||||
<li><strong>Backup all files / directories before deleting!!</strong></li>
|
||||
<li> Delete includes/hooks/websitepanel_sync.php</li>
|
||||
<li>Delete includes/hooks/websitepanel_addons.php</li>
|
||||
<li> Delete modules/servers/websitepanel</li>
|
||||
<li>Delete modules/addons/websitepanel_sync</li>
|
||||
<li>Delete modules/addons/websitepanel_addons</li>
|
||||
<li>Upload the contents of the ZIP to your WHMCS root</li>
|
||||
</ol>
|
||||
<p>All new files should have version 3.x.x listed in their headers</p>
|
|
@ -1,137 +0,0 @@
|
|||
<?php if (!defined('WHMCS')) exit('ACCESS DENIED');
|
||||
// Copyright (c) 2012, Outercurve Foundation.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// - Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//
|
||||
// - Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// - Neither the name of the Outercurve Foundation nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/**
|
||||
* WebsitePanel Addons Hook
|
||||
*
|
||||
* @author Christopher York
|
||||
* @package WebsitePanel Addons Hook
|
||||
* @version v1.0
|
||||
* @link http://www.websitepanel.net/
|
||||
*/
|
||||
|
||||
/**
|
||||
* websitepanel_addons_AddonActivation
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
function websitepanel_addons_AddonActivation($params)
|
||||
{
|
||||
// Sanity check to make sure the associated service is WebsitePanel based product
|
||||
// And that the addon purchased has an associated WebsitePanel addon
|
||||
$results = full_query("SELECT h.id AS `id` FROM `tblhosting` AS h, `mod_wspaddons` AS w, `tblservers` AS s WHERE h.id = {$params['serviceid']} AND h.server = s.id AND s.type = 'websitepanel' AND w.whmcs_id = {$params['addonid']}");
|
||||
if (mysql_num_rows($results) > 0)
|
||||
{
|
||||
// Include the WebsitePanel ES Class
|
||||
require_once(ROOTDIR . '/modules/servers/websitepanel/websitepanel.class.php');
|
||||
require_once(ROOTDIR . '/modules/servers/websitepanel/websitepanel.functions.php');
|
||||
|
||||
// Retrieve the WebsitePanel Addons module settings
|
||||
$modSettings = websitepanel_addons_GetSettings();
|
||||
$srvSettings = websitepanel_GetServerSettings();
|
||||
if (empty($modSettings['serverhost']) || empty($modSettings['serverport']) || empty($srvSettings['username']) || empty($srvSettings['password']))
|
||||
{
|
||||
// The module is disabled or has not yet been configured - stop
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the associated WebsitePanel username from WHMCS
|
||||
$results = select_query('tblhosting', 'username', array('id' => $params['serviceid']));
|
||||
$username = mysql_fetch_array($results);
|
||||
$username = $username['username'];
|
||||
if (empty($username))
|
||||
{
|
||||
// The username is required - if missing we cannot continue
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the WebsitePanel object instance
|
||||
$wsp = new WebsitePanel($srvSettings['username'], $srvSettings['password'], $modSettings['serverhost'], $modSettings['serverport'], (($modSettings['serversecured']) == 'on' ? TRUE : FALSE));
|
||||
|
||||
// Grab the user's details from WebsitePanel in order to get the user's id
|
||||
$user = $wsp->getUserByUsername($username);
|
||||
if (empty($user))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the user's current WebsitePanel hosting space Id (Hosting Plan)
|
||||
$package = $wsp->getUserPackages($user['UserId']);
|
||||
$packageId = $package['PackageId'];
|
||||
if (empty($packageId))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the associated WebsitePanel addon id
|
||||
$results = select_query('mod_wspaddons', 'wsp_id,is_ipaddress', array('whmcs_id' => $params['addonid']));
|
||||
$addon = mysql_fetch_array($results);
|
||||
$addonPlanId = $addon['wsp_id'];
|
||||
$addonIsIpAddress = $addon['is_ipaddress'];
|
||||
|
||||
// Add the Addon Plan to the customer's WebsitePanel package / hosting space
|
||||
$results = $wsp->addPackageAddonById($packageId, $addonPlanId);
|
||||
|
||||
// Check the results to verify that the addon has been successfully allocated
|
||||
if ($results['Result'] > 0)
|
||||
{
|
||||
// If this addon is an IP address addon - attempt to randomly allocate an IP address to the customer's hosting space
|
||||
if ($addonIsIpAddress)
|
||||
{
|
||||
$wsp->packageAllocateIpAddress($packageId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Addon Activation - WebsitePanel */
|
||||
add_hook('AddonActivation', 1, 'websitepanel_addons_AddonActivation');
|
||||
|
||||
/* Addon Activation - WebsitePanel */
|
||||
add_hook('AddonActivated', 1, 'websitepanel_addons_AddonActivation');
|
||||
|
||||
/**
|
||||
* websitepanel_addons_GetSettings
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
function websitepanel_addons_GetSettings()
|
||||
{
|
||||
$settings = array();
|
||||
|
||||
// Retrieve the settings from the modules configuration table
|
||||
$results = select_query('tbladdonmodules', 'setting,value', array('module' => 'websitepanel_addons'));
|
||||
while (($row = mysql_fetch_array($results)) != false)
|
||||
{
|
||||
$settings[$row[0]] = $row[1];
|
||||
}
|
||||
return $settings;
|
||||
}
|
|
@ -1,114 +0,0 @@
|
|||
<?php if (!defined('WHMCS')) exit('ACCESS DENIED');
|
||||
// Copyright (c) 2012, Outercurve Foundation.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// - Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//
|
||||
// - Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// - Neither the name of the Outercurve Foundation nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/**
|
||||
* WebsitePanel Sync Hook
|
||||
*
|
||||
* @author Christopher York
|
||||
* @package WebsitePanel Sync Hook
|
||||
* @version v1.0
|
||||
* @link http://www.websitepanel.net/
|
||||
*/
|
||||
|
||||
/**
|
||||
* websitepanel_sync_ClientEdit
|
||||
*
|
||||
* @access public
|
||||
* @param array $params
|
||||
*/
|
||||
function websitepanel_sync_ClientEdit($params)
|
||||
{
|
||||
// Sanity check - Check if client has any active WebsitePanel hosting packages
|
||||
$results = full_query("SELECT h.userid AS `userid` FROM `tblhosting` AS h, `tblservers` AS s WHERE h.userid = {$params['userid']} AND h.server = s.id AND s.type = 'websitepanel'");
|
||||
if (mysql_num_rows($results) > 0)
|
||||
{
|
||||
// Include the WebsitePanel ES Class
|
||||
require_once(ROOTDIR . '/modules/servers/websitepanel/websitepanel.class.php');
|
||||
require_once(ROOTDIR . '/modules/servers/websitepanel/websitepanel.functions.php');
|
||||
|
||||
// Retrieve the WebsitePanel Addons module settings
|
||||
$modSettings = websitepanel_sync_GetSettings();
|
||||
$srvSettings = websitepanel_GetServerSettings();
|
||||
if (empty($modSettings['serverhost']) || empty($modSettings['serverport']) || empty($srvSettings['username']) || empty($srvSettings['password']))
|
||||
{
|
||||
// The module is disabled or has not yet been configured - stop
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the WebsitePanel object instance
|
||||
$wsp = new WebsitePanel($srvSettings['username'], $srvSettings['password'], $modSettings['serverhost'], $modSettings['serverport'], (($modSettings['serversecured']) == 'on' ? TRUE : FALSE));
|
||||
|
||||
// Get all WSP users with the old email
|
||||
$items = (array)$wsp->getUsersPagedRecursive(1, 'Email', $params['olddata']['email'], 0, 0, '');
|
||||
|
||||
// Load / parse the XML response
|
||||
$xml = simplexml_load_string($items['any']);
|
||||
$rootPath = $xml->NewDataSet;
|
||||
|
||||
// Total number of elements to update
|
||||
$total = $rootPath->Table->Column1;
|
||||
|
||||
// Begin updating WebsitePanel accounts
|
||||
for ($i = 0; $i < $total; $i++)
|
||||
{
|
||||
// Set the current root element and get the users details from WebsitePanel
|
||||
// We cannot use the details provided by the get_users_paged_recursive method as it does not return all the required elements to fully update the user
|
||||
$currentRoot = $rootPath->Table1->$i;
|
||||
$userDetails = (array)$wsp->getUserByUsername($currentRoot->Username);
|
||||
|
||||
// Update the current user
|
||||
$wsp->updateUserDetails($userDetails['RoleId'], (($userDetails['RoleId'] == 2) ? 'Reseller' : 'User'), $userDetails['StatusId'], $userDetails['Status'], $userDetails['LoginStatusId'], $userDetails['LoginStatus'], $userDetails['FailedLogins'], $userDetails['UserId'], $userDetails['OwnerId'], $userDetails['Created'], $userDetails['Changed'], $userDetails['IsDemo'], $userDetails['IsPeer'], $currentRoot->Comments, $userDetails['Username'], $userDetails['Password'], $params['firstname'], $params['lastname'], $params['email'], $params['phonenumber'], $params['postcode'], '', '', '', '', $params['country'], $params['address1'] . (!empty($params['address2']) ? " {$params['address2']}" : ''), $params['city'], $params['state'], TRUE, $params['companyname'], (($userDetails['RoleId'] == 2) ? TRUE : FALSE));
|
||||
|
||||
// Add log entry to client log
|
||||
logactivity("WebsitePanel Sync - Account {$currentRoot->Username} contact details updated successfully", $params['userid']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Update Client Contact Details - WebsitePanel */
|
||||
add_hook('ClientEdit', 1, 'websitepanel_sync_ClientEdit');
|
||||
|
||||
/**
|
||||
* websitepanel_addons_GetSettings
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
function websitepanel_sync_GetSettings()
|
||||
{
|
||||
$settings = array();
|
||||
|
||||
// Retrieve the settings from the modules configuration table
|
||||
$results = select_query('tbladdonmodules', 'setting,value', array('module' => 'websitepanel_sync'));
|
||||
while (($row = mysql_fetch_array($results)) != false)
|
||||
{
|
||||
$settings[$row['setting']] = $row['value'];
|
||||
}
|
||||
return $settings;
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
<?php if (!defined('WHMCS')) exit('ACCESS DENIED');
|
||||
// Copyright (c) 2012, Outercurve Foundation.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// - Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//
|
||||
// - Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// - Neither the name of the Outercurve Foundation nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// WebsitePanel server module core files
|
||||
require_once(ROOTDIR. '/modules/servers/websitepanel/enterpriseserver.php');
|
||||
|
||||
/**
|
||||
* WebsitePanel Enterprise Server Client
|
||||
*
|
||||
* @author Christopher York
|
||||
* @link http://www.websitepanel.net/
|
||||
* @access public
|
||||
* @name websitepanel_EnterpriseServer
|
||||
* @version 3.0.4
|
||||
* @package WHMCS
|
||||
* @final
|
||||
*/
|
||||
|
||||
/**
|
||||
* Handles activating and adding client addons to WebsitePanel
|
||||
*
|
||||
* @access public
|
||||
* @param array $params WHMCS parameters
|
||||
* @throws Exception
|
||||
*/
|
||||
function websitepanel_addons_AddonActivation($params)
|
||||
{
|
||||
// WHMCS server parameters & package parameters
|
||||
$userId = $params['userid'];
|
||||
$serviceId = $params['serviceid'];
|
||||
$addonId = $params['addonid'];
|
||||
|
||||
$result = full_query("SELECT h.username AS username, s.ipaddress AS serverip, s.hostname AS serverhostname, s.secure AS serversecure, s.username AS serverusername, s.password AS serverpassword, p.configoption6 AS configoption6, h.id AS serviceid FROM `tblhosting` AS h, `tblservers` AS s, `tblproducts` AS p, `mod_wspaddons` AS w WHERE h.packageid = p.id AND w.whmcs_id = {$addonId} AND h.id = {$serviceId} AND h.server = s.id AND s.type = 'websitepanel'");
|
||||
if (mysql_num_rows($result) > 0)
|
||||
{
|
||||
// Get the results of the query
|
||||
$row = mysql_fetch_assoc($result);
|
||||
|
||||
// Start processing the users addon
|
||||
$username = $row['username'];
|
||||
$serverUsername = $row['serverusername'];
|
||||
$serverPassword = decrypt($row['serverpassword']);
|
||||
$serverPort = $row['configoption6'];
|
||||
$serverHost = empty($row['serverhostname']) ? $row['serverip'] : $row['serverhostname'];
|
||||
$serverSecure = $row['serversecure'] == 'on' ? TRUE : FALSE;
|
||||
|
||||
try
|
||||
{
|
||||
// Create the WebsitePanel Enterprise Server Client object instance
|
||||
$wsp = new websitepanel_EnterpriseServer($serverUsername, $serverPassword, $serverHost, $serverPort, $serverSecure);
|
||||
|
||||
// Get the user's details from WebsitePanel - We need the UserId
|
||||
$user = $wsp->getUserByUsername($username);
|
||||
if (empty($user))
|
||||
{
|
||||
throw new Exception("User {$username} does not exist - Cannot allocate addon for unknown user");
|
||||
}
|
||||
|
||||
// Get the user's package details from WebsitePanel - We need the PackageId
|
||||
$package = $wsp->getUserPackages($user['UserId']);
|
||||
$packageId = $package['PackageId'];
|
||||
|
||||
// Get the associated WebsitePanel addon id
|
||||
$results = select_query('mod_wspaddons', 'wsp_id,is_ipaddress', array('whmcs_id' => $addonId));
|
||||
$addon = mysql_fetch_array($results);
|
||||
$addonPlanId = $addon['wsp_id'];
|
||||
$addonIsIpAddress = $addon['is_ipaddress'];
|
||||
|
||||
// Add the Addon Plan to the customer's WebsitePanel package / hosting space
|
||||
$results = $wsp->addPackageAddonById($packageId, $addonPlanId);
|
||||
|
||||
// Check the results to verify that the addon has been successfully allocated
|
||||
if ($results['Result'] > 0)
|
||||
{
|
||||
// If this addon is an IP address addon - attempt to randomly allocate an IP address to the customer's hosting space
|
||||
if ($addonIsIpAddress)
|
||||
{
|
||||
$wsp->allocatePackageIPAddresses($packageId);
|
||||
}
|
||||
|
||||
// Add log entry to client log
|
||||
logactivity("WebsitePanel Addon - Account {$username} addon successfully completed - Addon ID: {$addonId}", $userId);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add log entry to client log
|
||||
throw new Exception("Unknown", $results['Result']);
|
||||
}
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
// Error message to log / return
|
||||
$errorMessage = "websitepanel_addons_AddonActivation Fault: (Code: {$e->getCode()}, Message: {$e->getMessage()}, Service ID: {$serviceId})";
|
||||
|
||||
// Log to WHMCS
|
||||
logactivity($errorMessage, $userId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Addon Activation - WebsitePanel */
|
||||
add_hook('AddonActivation', 1, 'websitepanel_addons_AddonActivation');
|
|
@ -28,12 +28,16 @@
|
|||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/**
|
||||
* WebsitePanel Addons Addon Module
|
||||
* WebsitePanel Enterprise Server Client
|
||||
* For the ASPnix WebsitePanel system only - Only tested against the ASPnix WebsitePanel system
|
||||
*
|
||||
* @author Christopher York
|
||||
* @package WebsitePanel Addons Addon Module
|
||||
* @version v1.0
|
||||
* @link http://www.websitepanel.net/
|
||||
* @access public
|
||||
* @name websitepanel_EnterpriseServer
|
||||
* @version 3.0.4
|
||||
* @package WHMCS
|
||||
* @final
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -44,16 +48,10 @@
|
|||
*/
|
||||
function websitepanel_addons_config()
|
||||
{
|
||||
$configarray = array('name' => 'WebsitePanel Addons Automation',
|
||||
'description' => 'Automates WHMCS product addons with WebsitePanel',
|
||||
'version' => '1.2',
|
||||
'author' => 'Christopher York',
|
||||
'fields' => array('serverhost' => array('FriendlyName', 'Enterprise Server Host', 'Type' => 'text', 'Size' => 25, 'Description' => 'Enterprise Server hostname / IP address', 'Default' => '127.0.0.1'),
|
||||
'serverport' => array('FriendlyName', 'Enterprise Server Port', 'Type' => 'text', 'Size' => 4, 'Description' => 'Enterprise Server port', 'Default' => 9002),
|
||||
'serversecured' => array('FriendlyName', 'Use Secured Connection', 'Type' => 'yesno', 'Description' => 'Tick to use SSL secured connection'),
|
||||
)
|
||||
);
|
||||
return $configarray;
|
||||
return array('name' => 'WebsitePanel Addons Automation',
|
||||
'description' => 'Automates WHMCS product addons with WebsitePanel Addons',
|
||||
'version' => '3.0.4',
|
||||
'author' => 'Christopher York');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -65,10 +63,10 @@ function websitepanel_addons_config()
|
|||
function websitepanel_addons_activate()
|
||||
{
|
||||
// Create the WebsitePanel Addons table
|
||||
$query = "CREATE TABLE `mod_wspaddons` (
|
||||
$query = "CREATE TABLE IF NOT EXISTS `mod_wspaddons` (
|
||||
`whmcs_id` int(11) NOT NULL,
|
||||
`wsp_id` int(11) NOT NULL,
|
||||
`is_ipaddress` bit(1) NOT NULL DEFAULT 0,
|
||||
`is_ipaddress` bit(1) NOT NULL DEFAULT b'0',
|
||||
PRIMARY KEY (`whmcs_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;";
|
||||
$result = full_query($query);
|
||||
|
@ -115,7 +113,7 @@ function websitepanel_addons_deactivate()
|
|||
*/
|
||||
function websitepanel_addons_upgrade($vars)
|
||||
{
|
||||
|
||||
// Module versions
|
||||
$version = $vars['version'];
|
||||
|
||||
// Adjust the table name and remove the WebsitePanel credentials
|
||||
|
@ -128,7 +126,7 @@ function websitepanel_addons_upgrade($vars)
|
|||
}
|
||||
|
||||
/**
|
||||
* websitepanel_addons_output
|
||||
* Displays the WebsitePanel Addons module output
|
||||
*
|
||||
* @access public
|
||||
* @return mixed
|
||||
|
|
|
@ -0,0 +1,136 @@
|
|||
<?php if (!defined('WHMCS')) exit('ACCESS DENIED');
|
||||
// Copyright (c) 2012, Outercurve Foundation.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// - Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//
|
||||
// - Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// - Neither the name of the Outercurve Foundation nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// WebsitePanel server module core files
|
||||
require_once(ROOTDIR. '/modules/servers/websitepanel/enterpriseserver.php');
|
||||
|
||||
/**
|
||||
* WebsitePanel WHMCS WebsitePanel / WHMCS Client Contact Details Sync
|
||||
*
|
||||
* @author Christopher York
|
||||
* @link http://www.websitepanel.net/
|
||||
* @access public
|
||||
* @name websitepanel
|
||||
* @version 3.0.4
|
||||
* @package WHMCS
|
||||
*/
|
||||
|
||||
/**
|
||||
* Handles updating WebsitePanel account details when a client or administrator updates a client's details
|
||||
*
|
||||
* @access public
|
||||
* @param array $params WHMCS parameters
|
||||
* @throws Exception
|
||||
*/
|
||||
function websitepanel_sync_ClientEdit($params)
|
||||
{
|
||||
// WHMCS server parameters & package parameters
|
||||
$userId = $params['userid'];
|
||||
$serviceId = 0;
|
||||
|
||||
// Query for the users WebsitePanel accounts - If they do not have any, just ignore the request
|
||||
$result = full_query("SELECT h.username AS username, s.ipaddress AS serverip, s.hostname AS serverhostname, s.secure AS serversecure, s.username AS serverusername, s.password AS serverpassword, p.configoption6 AS configoption6, h.id AS serviceid FROM `tblhosting` AS h, `tblservers` AS s, `tblproducts` AS p WHERE h.userid = {$userId} AND h.packageid = p.id AND h.server = s.id AND s.type = 'websitepanel' AND h.domainstatus IN ('Active', 'Suspended')");
|
||||
while (($row = mysql_fetch_array($result)) != false)
|
||||
{
|
||||
// Start updating the users account details
|
||||
$serviceId = $row['serviceid'];
|
||||
$username = $row['username'];
|
||||
$serverUsername = $row['serverusername'];
|
||||
$serverPassword = decrypt($row['serverpassword']);
|
||||
$serverPort = $row['configoption6'];
|
||||
$serverHost = empty($row['serverhostname']) ? $row['serverip'] : $row['serverhostname'];
|
||||
$serverSecure = $row['serversecure'] == 'on' ? TRUE : FALSE;
|
||||
$clientsDetails = $params;
|
||||
|
||||
try
|
||||
{
|
||||
// Create the WebsitePanel Enterprise Server Client object instance
|
||||
$wsp = new websitepanel_EnterpriseServer($serverUsername, $serverPassword, $serverHost, $serverPort, $serverSecure);
|
||||
|
||||
// Get the user's details from WebsitePanel - We need the username
|
||||
$user = $wsp->getUserByUsername($username);
|
||||
if (empty($user))
|
||||
{
|
||||
throw new Exception("User {$username} does not exist - Cannot update account details for unknown user");
|
||||
}
|
||||
|
||||
// Update the user's account details using the previous details + WHMCS's details (address, city, state etc.)
|
||||
$userParams = array('RoleId' => $user['RoleId'],
|
||||
'Role' => $user['Role'],
|
||||
'StatusId' => $user['StatusId'],
|
||||
'Status' => $user['Status'],
|
||||
'LoginStatusId' => $user['LoginStatusId'],
|
||||
'LoginStatus' => $user['LoginStatus'],
|
||||
'FailedLogins' => $user['FailedLogins'],
|
||||
'UserId' => $user['UserId'],
|
||||
'OwnerId' => $user['OwnerId'],
|
||||
'IsPeer' => $user['IsPeer'],
|
||||
'Created' => $user['Created'],
|
||||
'Changed' => $user['Changed'],
|
||||
'IsDemo' => $user['IsDemo'],
|
||||
'Comments' => $user['Comments'],
|
||||
'LastName' => $clientsDetails['lastname'],
|
||||
'Username' => $user['Username'],
|
||||
'Password' => $user['Password'],
|
||||
'FirstName' => $clientsDetails['firstname'],
|
||||
'Email' => $clientsDetails['email'],
|
||||
'PrimaryPhone' => $clientsDetails['phonenumber'],
|
||||
'Zip' => $clientsDetails['postcode'],
|
||||
'InstantMessenger' => '',
|
||||
'Fax' => '',
|
||||
'SecondaryPhone' => '',
|
||||
'SecondaryEmail' => '',
|
||||
'Country' => $clientsDetails['country'],
|
||||
'Address' => $clientsDetails['address1'],
|
||||
'City' => $clientsDetails['city'],
|
||||
'State' => $clientsDetails['state'],
|
||||
'HtmlMail' => $user['HtmlMail'],
|
||||
'CompanyName' => $clientsDetails['companyname'],
|
||||
'EcommerceEnabled' => $user['EcommerceEnabled'],
|
||||
'SubscriberNumber' => '');
|
||||
|
||||
// Execute the UpdateUserDetails method
|
||||
$wsp->updateUserDetails($userParams);
|
||||
|
||||
// Add log entry to client log
|
||||
logactivity("WebsitePanel Sync - Account {$username} contact details updated successfully", $userId);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
// Error message to log / return
|
||||
$errorMessage = "websitepanel_sync_ClientEdit Fault: (Code: {$e->getCode()}, Message: {$e->getMessage()}, Service ID: {$serviceId})";
|
||||
|
||||
// Log to WHMCS
|
||||
logactivity($errorMessage, $userId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Update Client Contact Details - WebsitePanel */
|
||||
add_hook('ClientEdit', 1, 'websitepanel_sync_ClientEdit');
|
|
@ -28,44 +28,40 @@
|
|||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/**
|
||||
* WebsitePanel Sync Addon Module
|
||||
* WebsitePanel WHMCS WebsitePanel / WHMCS Client Contact Details Sync
|
||||
*
|
||||
* @author Christopher York
|
||||
* @package WebsitePanel Sync Addon Module
|
||||
* @version v1.0
|
||||
* @link http://www.websitepanel.net/
|
||||
* @access public
|
||||
* @name websitepanel
|
||||
* @version 3.0.4
|
||||
* @package WHMCS
|
||||
*/
|
||||
|
||||
/**
|
||||
* websitepanel_sync_config
|
||||
* Returns the WebsitePanel Sync configuration options
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
function websitepanel_sync_config()
|
||||
{
|
||||
$configarray = array('name' => 'WebsitePanel Sync Automation',
|
||||
'description' => 'Syncs WHMCS client details / contact changes with WebsitePanel',
|
||||
'version' => '1.2',
|
||||
'author' => 'Christopher York',
|
||||
'fields' => array('serverhost' => array('FriendlyName', 'Enterprise Server Host', 'Type' => 'text', 'Size' => 25, 'Description' => 'Enterprise Server hostname / IP address', 'Default' => '127.0.0.1'),
|
||||
'serverport' => array('FriendlyName', 'Enterprise Server Port', 'Type' => 'text', 'Size' => 4, 'Description' => 'Enterprise Server port', 'Default' => 9002),
|
||||
'serversecured' => array('FriendlyName', 'Use Secured Connection', 'Type' => 'yesno', 'Description' => 'Tick to use SSL secured connection'),
|
||||
)
|
||||
);
|
||||
return $configarray;
|
||||
return array('name' => 'WebsitePanel Sync Automation',
|
||||
'description' => 'Syncs WHMCS client details / contact changes with WebsitePanel accounts',
|
||||
'version' => '3.0.4',
|
||||
'author' => 'Christopher York');
|
||||
}
|
||||
|
||||
/**
|
||||
* websitepanel_addons_upgrade
|
||||
* Returns the WebsitePanel Sync configuration options
|
||||
*
|
||||
* @param $vars array
|
||||
* @param $vars array WHMCS parameters
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
function websitepanel_sync_upgrade($vars)
|
||||
{
|
||||
|
||||
// Module version
|
||||
$version = $vars['version'];
|
||||
|
||||
// Remove the WebsitePanel credentials
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
<br />
|
||||
<form action="{$websitepanel_url}/default.aspx?pid=Login" method="POST" target="_blank"><input type="hidden" value="{$username}" name="user"><input type="hidden" value="{$password}" name="password"><input type="submit" value="{$LANG.websitepanel_clientarea_oneclicklogin}"></form>
|
|
@ -0,0 +1,502 @@
|
|||
<?php if (!defined('WHMCS')) exit('ACCESS DENIED');
|
||||
// Copyright (c) 2012, Outercurve Foundation.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// - Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//
|
||||
// - Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// - Neither the name of the Outercurve Foundation nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/**
|
||||
* WebsitePanel Enterprise Server Client
|
||||
* For the ASPnix WebsitePanel system only - Only tested against the ASPnix WebsitePanel system
|
||||
*
|
||||
* @author Christopher York
|
||||
* @link http://www.websitepanel.net/
|
||||
* @access public
|
||||
* @name websitepanel_EnterpriseServer
|
||||
* @version 3.0.4
|
||||
* @package WHMCS
|
||||
* @final
|
||||
*/
|
||||
final class websitepanel_EnterpriseServer
|
||||
{
|
||||
/**
|
||||
* WebsitePanel user account statuses / states
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
const USERSTATUS_ACTIVE = 'Active';
|
||||
const USERSTATUS_SUSPENDED = 'Suspended';
|
||||
const USERSTATUS_CANCELLED = 'Cancelled';
|
||||
const USERSTATUS_PENDING = 'Pending';
|
||||
|
||||
/**
|
||||
* WebsitePanel usage calculation types
|
||||
*
|
||||
* @access public
|
||||
* @var int
|
||||
*/
|
||||
const USAGE_DISKSPACE = 0;
|
||||
const USAGE_BANDWIDTH = 1;
|
||||
|
||||
/**
|
||||
* Enterprise Server username
|
||||
*
|
||||
* @access private
|
||||
* @var string
|
||||
*/
|
||||
private $_username;
|
||||
|
||||
/**
|
||||
* Enterprise Server password
|
||||
*
|
||||
* @access private
|
||||
* @var string
|
||||
*/
|
||||
private $_password;
|
||||
|
||||
/**
|
||||
* Enterprise Server URL / address (without the port)
|
||||
*
|
||||
* @access private
|
||||
* @var string
|
||||
*/
|
||||
private $_host;
|
||||
|
||||
/**
|
||||
* Enterprise Server TCP port
|
||||
*
|
||||
* @access private
|
||||
* @var int
|
||||
*/
|
||||
private $_port;
|
||||
|
||||
/**
|
||||
* Use SSL (HTTPS) for Enterprise Server communications
|
||||
*
|
||||
* @access private
|
||||
* @var boolean
|
||||
*/
|
||||
private $_secured;
|
||||
|
||||
/**
|
||||
* SoapClient WSDL caching
|
||||
*
|
||||
* @access private
|
||||
* @var boolean
|
||||
*/
|
||||
private $_caching;
|
||||
|
||||
/**
|
||||
* SoapClient HTTP compression
|
||||
*
|
||||
* @access private
|
||||
* @var boolean
|
||||
*/
|
||||
private $_compression;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* @access public
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param string $host
|
||||
* @param int $port
|
||||
* @param boolean $secured
|
||||
* @param boolean $caching
|
||||
* @param boolean $compression
|
||||
*/
|
||||
function __construct($username, $password, $host, $port = 9002, $secured = FALSE, $caching = FALSE, $compression = TRUE)
|
||||
{
|
||||
$this->_username = $username;
|
||||
$this->_password = $password;
|
||||
$this->_host = $host;
|
||||
$this->_port = $port;
|
||||
$this->_secured = $secured;
|
||||
$this->_caching = $caching;
|
||||
$this->_compression = $compression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the "CreateUserWizard" method
|
||||
*
|
||||
* @param array $params CreateUserWizard method parameters
|
||||
* @throws Exception
|
||||
* @return int
|
||||
*/
|
||||
public function createUserWizard($params)
|
||||
{
|
||||
try
|
||||
{
|
||||
return $this->execute('esPackages.asmx', 'CreateUserWizard', $params)->CreateUserWizardResult;
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
throw new Exception("ChangeUserStatus Fault: (Code: {$e->getCode()}, Message: {$e->getMessage()}", $e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the "UpdateUser" method
|
||||
*
|
||||
* @access private
|
||||
* @param array $params
|
||||
* @throws Exception
|
||||
* @return int
|
||||
*/
|
||||
public function updateUserDetails($params)
|
||||
{
|
||||
try
|
||||
{
|
||||
return $this->execute('esUsers.asmx', 'UpdateUser', array('user' => $params))->UpdateUserResult;
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
throw new Exception("UpdateUser Fault: (Code: {$e->getCode()}, Message: {$e->getMessage()}", $e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the "DeleteUser" method
|
||||
*
|
||||
* @access public
|
||||
* @param int $userId User's WebsitePanel userId
|
||||
* @throws Exception
|
||||
* @return int
|
||||
*/
|
||||
public function deleteUser($userId)
|
||||
{
|
||||
try
|
||||
{
|
||||
return $this->execute('esUsers.asmx', 'DeleteUser', array('userId' => $userId))->DeleteUserResult;
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
throw new Exception("ChangeUserStatus Fault: (Code: {$e->getCode()}, Message: {$e->getMessage()}", $e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the "GetUserByUsername" method
|
||||
*
|
||||
* @access public
|
||||
* @param string $username Websitepanel username
|
||||
* @throws Exception
|
||||
* @return array
|
||||
*/
|
||||
public function getUserByUsername($username)
|
||||
{
|
||||
try
|
||||
{
|
||||
return $this->convertArray($this->execute('esUsers.asmx', 'GetUserByUsername', array('username' => $username))->GetUserByUsernameResult);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
throw new Exception("GetUserByUsername Fault: (Code: {$e->getCode()}, Message: {$e->getMessage()})", $e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the "ChangeUserStatus" method
|
||||
*
|
||||
* @access public
|
||||
* @param int $userId User's WebsitePanel userId
|
||||
* @param string $status Account status (Active, Suspended, Cancelled, Pending)
|
||||
* @throws Exception
|
||||
* @return int
|
||||
*/
|
||||
public function changeUserStatus($userId, $status)
|
||||
{
|
||||
try
|
||||
{
|
||||
return $this->execute('esUsers.asmx', 'ChangeUserStatus', array('userId' => $userId, 'status' => $status))->ChangeUserStatusResult;
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
throw new Exception("ChangeUserStatus Fault: (Code: {$e->getCode()}, Message: {$e->getMessage()}", $e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the "ChangeUserPassword" method
|
||||
*
|
||||
* @access public
|
||||
* @param int $userId User's WebsitePanel userId
|
||||
* @param string $password User's new password
|
||||
* @throws Exception
|
||||
* @return int
|
||||
*/
|
||||
public function changeUserPassword($userId, $password)
|
||||
{
|
||||
try
|
||||
{
|
||||
return $this->execute('esUsers.asmx', 'ChangeUserPassword', array('userId' => $userId, 'password' => $password))->ChangeUserPasswordResult;
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
throw new Exception("ChangeUserPassword Fault: (Code: {$e->getCode()}, Message: {$e->getMessage()}", $e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the "GetMyPackages" method
|
||||
*
|
||||
* @access public
|
||||
* @param int $userId User's WebsitePanel userId
|
||||
* @throws Exception
|
||||
* @return array
|
||||
*/
|
||||
public function getUserPackages($userId)
|
||||
{
|
||||
try
|
||||
{
|
||||
return $this->convertArray($this->execute('esPackages.asmx', 'GetMyPackages', array('userId' => $userId))->GetMyPackagesResult->PackageInfo);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
throw new Exception("GetMyPackages Fault: (Code: {$e->getCode()}, Message: {$e->getMessage()}", $e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the "GetUsersPagedRecursive" method
|
||||
*
|
||||
* @access public
|
||||
* @param unknown $userId Users's WebsitePanel userId
|
||||
* @param unknown $filterColumn Column value to filter against
|
||||
* @param unknown $filterValue Filter value
|
||||
* @param unknown $statusId Users's account status id
|
||||
* @param unknown $roleId User's account role id
|
||||
* @param unknown $sortColumn Column value to sort against
|
||||
* @param number $startRow Start value
|
||||
* @param string $maximumRows Maximum rows to return
|
||||
* @throws Exception
|
||||
* @return object
|
||||
*/
|
||||
public function getUsersPagedRecursive($userId, $filterColumn, $filterValue, $statusId, $roleId, $sortColumn, $startRow = 0, $maximumRows = PHP_INT_MAX)
|
||||
{
|
||||
try
|
||||
{
|
||||
$result = (array)$this->execute('esUsers.asmx', 'GetUsersPagedRecursive', array('userId' => $userId, 'filterColumn' => $filterColumn, 'filterValue' => $filterValue, 'statusId' => $statusId, 'roleId' => $roleId, 'sortColumn' => $sortColumn, 'startRow' => $startRow, 'maximumRows' => $maximumRows))->GetUsersPagedRecursiveResult;
|
||||
return $this->convertArray($result['any'], TRUE);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
throw new Exception("GetUsersPagedRecursive Fault: (Code: {$e->getCode()}, Message: {$e->getMessage()}", $e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the "UpdatePackageLiteral" method
|
||||
*
|
||||
* @access public
|
||||
* @param int $packageId Package's WebsitePanel packageId
|
||||
* @param int $statusId Package's status id
|
||||
* @param int $planId Package's WebsitePanel planid
|
||||
* @param string $purchaseDate Package's purchase date
|
||||
* @param string $packageName Package's name
|
||||
* @param string $packageComments Package's comments
|
||||
* @throws Exception
|
||||
* @return array
|
||||
*/
|
||||
public function updatePackageLiteral($packageId, $statusId, $planId, $purchaseDate, $packageName, $packageComments)
|
||||
{
|
||||
try
|
||||
{
|
||||
return $this->convertArray($this->execute('esPackages.asmx', 'UpdatePackageLiteral', array('packageId' => $packageId, 'statusId' => $statusId, 'planId' => $planId, 'purchaseDate' => $purchaseDate, 'packageName' => $packageName, 'packageComments' => $packageComments))->UpdatePackageLiteralResult);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
throw new Exception("UpdatePackageLiteral Fault: (Code: {$e->getCode()}, Message: {$e->getMessage()}", $e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the "AddPackageAddonById" method
|
||||
*
|
||||
* @access public
|
||||
* @param unknown $packageId WebsitePanel package Id
|
||||
* @param unknown $addonPlanId WebsitePanel addon id
|
||||
* @param number $quantity Number of addons to add :)
|
||||
* @throws Exception
|
||||
* @return array
|
||||
*/
|
||||
public function addPackageAddonById($packageId, $addonPlanId, $quantity = 1)
|
||||
{
|
||||
try
|
||||
{
|
||||
return $this->convertArray($this->execute('esPackages.asmx', 'AddPackageAddonById', array('packageId' => $packageId, 'addonPlanId' => $addonPlanId, 'quantity' => $quantity))->AddPackageAddonByIdResult);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
throw new Exception("AddPackageAddonById Fault: (Code: {$e->getCode()}, Message: {$e->getMessage()}", $e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the "GetPackageBandwidth" method
|
||||
*
|
||||
* @access public
|
||||
* @param unknown $packageId WebsitePanel package id
|
||||
* @param unknown $startDate Calculation start date
|
||||
* @param unknown $endDate Calculation end date
|
||||
* @throws Exception
|
||||
* @return object
|
||||
*/
|
||||
public function getPackageBandwidthUsage($packageId, $startDate, $endDate)
|
||||
{
|
||||
try
|
||||
{
|
||||
$result = (array)$this->execute('esPackages.asmx', 'GetPackageBandwidth', array('packageId' => $packageId, 'startDate' => $startDate, 'endDate' => $endDate))->GetPackageBandwidthResult;
|
||||
return $this->convertArray($result['any'], TRUE);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
throw new Exception("GetPackageBandwidth Fault: (Code: {$e->getCode()}, Message: {$e->getMessage()}", $e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the "GetPackageDiskspace" method
|
||||
*
|
||||
* @access public
|
||||
* @param unknown $packageId WebsitePanel package id
|
||||
* @throws Exception
|
||||
* @return object
|
||||
*/
|
||||
public function getPackageDiskspaceUsage($packageId)
|
||||
{
|
||||
try
|
||||
{
|
||||
$result = (array)$this->execute('esPackages.asmx', 'GetPackageDiskspace', array('packageId' => $packageId))->GetPackageDiskspaceResult;
|
||||
return $this->convertArray($result['any'], TRUE);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
throw new Exception("GetPackageDiskspace Fault: (Code: {$e->getCode()}, Message: {$e->getMessage()}", $e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the "AllocatePackageIPAddresses" method
|
||||
*
|
||||
* @access public
|
||||
* @param int $packageId WebsitePanel package id
|
||||
* @param string $groupName WebsitePanel IP address group name
|
||||
* @param string $pool WebsitePanel IP address pool
|
||||
* @param int $addressesNumber Number of IP addresses to allocate
|
||||
* @param string $allocateRandom Allocate randomly
|
||||
* @throws Exception
|
||||
* @return object
|
||||
*/
|
||||
public function allocatePackageIPAddresses($packageId, $groupName = 'Web', $pool = 'WebSites', $addressesNumber = 1, $allocateRandom = TRUE)
|
||||
{
|
||||
try
|
||||
{
|
||||
return $this->convertArray($this->execute('esServers.asmx', 'AllocatePackageIPAddresses', array('packageId' => $packageId, 'groupName' => $groupName, 'pool' => $pool, 'addressesNumber' => $addressesNumber, 'allocateRandom' => $allocateRandom))->AllocatePackageIPAddressesResult);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
throw new Exception("AllocatePackageIPAddresses Fault: (Code: {$e->getCode()}, Message: {$e->getMessage()}", $e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the WebsitePanel error code to a friendly human-readable message
|
||||
*
|
||||
* @access public
|
||||
* @param int $code WebsitePanel error code
|
||||
* @return string
|
||||
*/
|
||||
public static function getFriendlyError($code)
|
||||
{
|
||||
$errors = array(-100 => 'Username not available, already in use',
|
||||
-101 => 'Username not found, invalid username',
|
||||
-102 => 'User\'s account has child accounts',
|
||||
-300 => 'Hosting package could not be found',
|
||||
-301 => 'Hosting package has child hosting spaces',
|
||||
-501 => 'The sub-domain belongs to an existing hosting space that does not allow sub-domains to be created',
|
||||
-502 => 'The domain or sub-domain exists in another hosting space / user account',
|
||||
-511 => 'Instant alias is enabled, but not configured',
|
||||
-601 => 'The website already exists on the target hosting space or server',
|
||||
-700 => 'The email domain already exists on the target hosting space or server',
|
||||
-1100 => 'User already exists');
|
||||
|
||||
// Find the error and return it, else a general error will do!
|
||||
if (array_key_exists($code, $errors))
|
||||
{
|
||||
return $errors[$code];
|
||||
}
|
||||
else
|
||||
{
|
||||
return "An unknown error occured (Code: {$code}). Please reference WebsitePanel BusinessErrorCodes for further information";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the request on the Enterprise Server and returns the results
|
||||
*
|
||||
* @param unknown $service
|
||||
* @param unknown $method
|
||||
* @param unknown $params
|
||||
* @throws Exception
|
||||
*/
|
||||
private function execute($service, $method, $params)
|
||||
{
|
||||
// Set the Enterprise Server full URL
|
||||
$host = (($this->_secured) ? 'https' : 'http') . "://{$this->_host}:{$this->_port}/{$service}?WSDL";
|
||||
try
|
||||
{
|
||||
// Create the SoapClient
|
||||
$client = new SoapClient($host, array('login' => $this->_username, 'password' => $this->_password, 'compression' => (($this->_compression) ? (SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP) : ''), 'cache_wsdl' => ($this->_caching) ? 1 : 0));
|
||||
|
||||
// Execute the request and process the results
|
||||
return call_user_func(array($client, $method), $params);
|
||||
}
|
||||
catch (SoapFault $e)
|
||||
{
|
||||
throw new Exception("SOAP Fault: (Code: {$e->getCode()}, Message: {$e->getMessage()})");
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
throw new Exception("General Fault: (Code: {$e->getCode()}, Message: {$e->getMessage()})");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an object or an XML string to an array
|
||||
*
|
||||
* @access private
|
||||
* @param mixed $value Object or an XML string
|
||||
* @param boolean $loadXml Loads the string into the SimpleXML object
|
||||
* @return array
|
||||
*/
|
||||
private function convertArray($value, $loadXml = FALSE)
|
||||
{
|
||||
// This is silly, but it works, and it works very well for what we are doing :)
|
||||
return json_decode(json_encode(($loadXml ? simplexml_load_string($value) : $value)), TRUE);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
<?php if (!defined('WHMCS')) exit('ACCESS DENIED');
|
||||
// Copyright (c) 2012, Outercurve Foundation.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// - Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//
|
||||
// - Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// - Neither the name of the Outercurve Foundation nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/**
|
||||
* WebsitePanel WHMCS Server Module Shared Funcitons
|
||||
*
|
||||
* @author Christopher York
|
||||
* @link http://www.websitepanel.net/
|
||||
* @access public
|
||||
* @name websitepanel
|
||||
* @version 3.0.4
|
||||
* @package WHMCS
|
||||
*/
|
||||
|
||||
/**
|
||||
* Calculate the bandwidth calculation starting date based on when the customer signed up
|
||||
*
|
||||
* @access public
|
||||
* @param string $startDate Customer registration date (starting date)
|
||||
* @return string
|
||||
*/
|
||||
function websitepanel_CreateBandwidthDate($startDate)
|
||||
{
|
||||
$dateExploded = explode('-', $startDate);
|
||||
$currentYear = date('Y');
|
||||
$currentMonth = date('m');
|
||||
$newDate = "{$currentYear}-{$currentMonth}-{$dateExploded[2]}";
|
||||
|
||||
$dateDiff = time() - strtotime('+1 hour', strtotime($newDate));
|
||||
$fullDays = floor($dateDiff / (60 * 60 * 24));
|
||||
if ($fullDays < 0)
|
||||
{
|
||||
return date('Y-m-d', strtotime('-1 month', strtotime($newDate)));
|
||||
}
|
||||
else
|
||||
{
|
||||
return $newDate;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the total usage of the provided WebsitePanel usage tables
|
||||
* Each websitepanel provider / service calculates its own disk and bandwidth usage, total all provided tables and return
|
||||
*
|
||||
* @access public
|
||||
* @param array $usageTables Usage tables (each service provides its own usage breakdown)
|
||||
* @param int $usageType WebsitePanel usage type (websitepanel_EnterpriseServer::USAGE_*)
|
||||
* @return int
|
||||
*/
|
||||
function websitepanel_CalculateUsage($usageTables, $usageType)
|
||||
{
|
||||
$totalUsage = 0;
|
||||
foreach ($usageTables['NewDataSet']['Table'] as $table)
|
||||
{
|
||||
switch ($usageType)
|
||||
{
|
||||
case websitepanel_EnterpriseServer::USAGE_BANDWIDTH:
|
||||
$totalUsage += $table['MegaBytesTotal'];
|
||||
break;
|
||||
|
||||
case websitepanel_EnterpriseServer::USAGE_DISKSPACE:
|
||||
$totalUsage += $table['Diskspace'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $totalUsage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the WebsitePanel language file
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function websitepanel_LoadClientLanguage()
|
||||
{
|
||||
global $CONFIG, $_LANG, $smarty;
|
||||
|
||||
// Attempt to load the client's language
|
||||
$selectedLanguage = !empty($_SESSION['Language']) ? $_SESSION['Language'] : $CONFIG['Language'];
|
||||
|
||||
// For the admin area
|
||||
if (defined('ADMINAREA'))
|
||||
{
|
||||
$result = select_query('tbladmins', 'language', array('id' => (int)$_SESSION['adminid']));
|
||||
$results = mysql_fetch_assoc($result);
|
||||
$selectedLanguage = !empty($results['language']) ? $results['language'] : 'english';
|
||||
}
|
||||
|
||||
// Load the language file
|
||||
$languageFile = dirname(__FILE__) . "/lang/{$selectedLanguage}.php";
|
||||
if (file_exists($languageFile))
|
||||
{
|
||||
require_once($languageFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Load the default (English) language file
|
||||
require_once(dirname(__FILE__) . '/lang/english.php');
|
||||
}
|
||||
|
||||
// Process the module language entries
|
||||
if (is_array($_MOD_LANG))
|
||||
{
|
||||
foreach ($_MOD_LANG as $key => $value)
|
||||
{
|
||||
if (empty($_LANG[$key]))
|
||||
{
|
||||
$_LANG[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add to the template
|
||||
if (isset($smarty))
|
||||
{
|
||||
$smarty->assign('LANG', $_LANG);
|
||||
}
|
||||
|
||||
return $_MOD_LANG;
|
||||
}
|
|
@ -27,34 +27,16 @@
|
|||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/**
|
||||
* WebsitePanel Server Module - WebsitePanel Business Error Codes
|
||||
*
|
||||
* @author Christopher York
|
||||
* @package WebsitePanel Server Module - WebsitePanel Business Error Codes
|
||||
* @version v1.0
|
||||
* @link http://www.websitepanel.net/
|
||||
*/
|
||||
|
||||
/**
|
||||
* Common error codes encountered while using the WebsitePanel Server Module
|
||||
* These are not all the Enterprise Server error codes, only the ones I have encountered using the API
|
||||
* WebsitePanel WHMCS Server Module Client Area Language
|
||||
*
|
||||
* @author Christopher York
|
||||
* @link http://www.websitepanel.net/
|
||||
* @access public
|
||||
* @return array
|
||||
* @name websitepanel
|
||||
* @version 3.0.0
|
||||
* @package WHMCS
|
||||
*/
|
||||
function websitepanel_GetEnterpriseServerErrors()
|
||||
{
|
||||
$esErrorCodes = array(-100 => 'User already exists',
|
||||
-101 => 'User not found',
|
||||
-102 => 'User has child user accounts',
|
||||
-300 => 'Hosting package could not be found',
|
||||
-301 => 'Hosting package has child hosting spaces',
|
||||
-501 => 'The sub-domain belongs to an existing hosting space that does not allow sub-domains to be created',
|
||||
-502 => 'The domain or sub-domain exists within another hosting space',
|
||||
-511 => 'Instant alias is enabled, but not configured',
|
||||
-601 => 'The website already exists on the target hosting space',
|
||||
-700 => 'The email domain already exists on the target hosting space',
|
||||
-1100 => 'User already exists');
|
||||
return $esErrorCodes;
|
||||
}
|
||||
$_MOD_LANG['websitepanel_clientarea_oneclicklogin'] = 'Login to Control Panel (One-Click Login)';
|
||||
$_MOD_LANG['websitepanel_adminarea_gotowebsitepanelaccount'] = 'View Account in WebsitePanel';
|
|
@ -1,438 +0,0 @@
|
|||
<?php if (!defined('WHMCS')) exit('ACCESS DENIED');
|
||||
// Copyright (c) 2012, Outercurve Foundation.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// - Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//
|
||||
// - Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// - Neither the name of the Outercurve Foundation nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/**
|
||||
* WebsitePanel Server Module - Enterprise Server Wrapper
|
||||
*
|
||||
* @author Christopher York
|
||||
* @package WebsitePanel Server Module - WebsitePanel Enterprise Server Wrapper
|
||||
* @version v1.0
|
||||
* @link http://www.websitepanel.net/
|
||||
*/
|
||||
|
||||
class WebsitePanel
|
||||
{
|
||||
/**
|
||||
* WebsitePanel Enteprise Server service file names
|
||||
*
|
||||
* @access private
|
||||
* @var string
|
||||
*/
|
||||
const SERVICEFILE_PACKAGES = 'esPackages.asmx';
|
||||
const SERVICEFILE_USERS = 'esUsers.asmx';
|
||||
const SERVICEFILE_SERVERS = 'esServers.asmx';
|
||||
|
||||
/**
|
||||
* WebsitePanel account states
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
const USERSTATUS_ACTIVE = 'Active';
|
||||
const USERSTATUS_SUSPENDED = 'Suspended';
|
||||
const USERSTATUS_CANCELLED = 'Cancelled';
|
||||
const USERSTATUS_PENDING = 'Pending';
|
||||
|
||||
/**
|
||||
* WebsitePanel usage calculation
|
||||
*
|
||||
* @access public
|
||||
* @var int
|
||||
*/
|
||||
const USAGE_DISKSPACE = 0;
|
||||
const USAGE_BANDWIDTH = 1;
|
||||
|
||||
/**
|
||||
* WebsitePanel IP address pools
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
const IPADDRESS_POOL_WEB = 'Web';
|
||||
|
||||
/**
|
||||
* WebsitePanel IP address groups
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
const IPADDRESS_GROUP_WEBSITES = 'WebSites';
|
||||
|
||||
/**
|
||||
* Enterprise Server username
|
||||
*
|
||||
* @access private
|
||||
* @var string
|
||||
*/
|
||||
private $_esUsername = 'serveradmin';
|
||||
|
||||
/**
|
||||
* Enterprise Server password
|
||||
*
|
||||
* @access private
|
||||
* @var string
|
||||
*/
|
||||
private $_esPassword;
|
||||
|
||||
/**
|
||||
* Enterprise Server URL / address (without the port)
|
||||
*
|
||||
* @access private
|
||||
* @var string
|
||||
*/
|
||||
private $_esServerUrl;
|
||||
|
||||
/**
|
||||
* Enterprise Server TCP port
|
||||
*
|
||||
* @access private
|
||||
* @var int
|
||||
*/
|
||||
private $_esServerPort = 9002;
|
||||
|
||||
/**
|
||||
* Use SSL (HTTPS) for Enterprise Server communications
|
||||
*
|
||||
* @access private
|
||||
* @var boolean
|
||||
*/
|
||||
private $_esUseSsl = false;
|
||||
|
||||
/**
|
||||
* WebsitePanel class constructor
|
||||
*
|
||||
* @access public
|
||||
* @param string $esUsername Enterprise Server username
|
||||
* @param string $esPassword Enterprise Server password
|
||||
* @param string $esServerUrl Enterprise Server URL / address (without the port)
|
||||
* @param int $esServerPort Enterprise Server TCP port
|
||||
* @param boolean $useSsl Use SSL (HTTPS) for Enterprise Server communications
|
||||
*/
|
||||
public function __construct($esUsername, $esPassword, $esServerUrl, $esServerPort = 9002, $useSsl = FALSE)
|
||||
{
|
||||
$this->_esUsername = $esUsername;
|
||||
$this->_esPassword = $esPassword;
|
||||
$this->_esServerUrl = $esServerUrl;
|
||||
$this->_esServerPort = $esServerPort;
|
||||
$this->_esUseSsl = $useSsl;
|
||||
}
|
||||
|
||||
/**
|
||||
* WebsitePanel::CreateAccount()
|
||||
*
|
||||
* @param string $username Account username
|
||||
* @param string $password Account password
|
||||
* @param string $roleId Account role id
|
||||
* @param string $firstName Account holders firstname
|
||||
* @param string $lastName Account holders lastname
|
||||
* @param string $email Account holders email address
|
||||
* @param string $planId WebsitePanel plan id
|
||||
* @param integer $parentPackageId Parent space / package id
|
||||
* @param string $domainName Account domain name
|
||||
* @param string $hostName Website hostname (if createWebsite is TRUE)
|
||||
* @param bool $htmlMail Send HTML email
|
||||
* @param bool $sendAccountLetter Send WebsitePanel "Account Summary" letter
|
||||
* @param bool $sendPackageLetter Send WebsitePanel "Hosting Space Summary" letter
|
||||
* @param bool $createPackage Create hostingspace / package on user creation
|
||||
* @param bool $tempDomain Create temporary domain on hostingspace / package creation
|
||||
* @param bool $createWebSite Create Website on hostingspace / package creation
|
||||
* @param bool $createFtpAccount Create FTP account on hostingspace / package creation
|
||||
* @param string $ftpAcountName FTP account name to create (if createFtpAccount is TRUE)
|
||||
* @param bool $createMailAccount Create default mail account on hostingspace / package creation
|
||||
* @param bool $createZoneRecord Create domain DNS zone record (if createMailAccount OR createWebSite are TRUE)
|
||||
* @return int
|
||||
*/
|
||||
public function createUserWizard($username, $password, $roleId, $firstName, $lastName, $email, $planId, $parentPackageId, $domainName, $hostName, $htmlMail = TRUE, $sendAccountLetter = TRUE, $sendPackageLetter = TRUE, $createPackage = TRUE, $tempDomain = FALSE, $createWebSite = FALSE, $createFtpAccount = FALSE, $ftpAcountName = '', $createMailAccount = FALSE, $createZoneRecord = FALSE)
|
||||
{
|
||||
$params = array();
|
||||
foreach (get_defined_vars() as $key => $value)
|
||||
{
|
||||
if ($key == 'params')
|
||||
continue;
|
||||
|
||||
$params[$key] = $value;
|
||||
}
|
||||
return $this->executeServerMethod(WebsitePanel::SERVICEFILE_PACKAGES, 'CreateUserWizard', $params)->CreateUserWizardResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* WebsitePanel::UpdateUserDetails()
|
||||
*
|
||||
* @access public
|
||||
* @param int $RoleId Account role id
|
||||
* @param string $Role Account role
|
||||
* @param int $StatusId Account status id
|
||||
* @param string $Status Account status
|
||||
* @param int $UserId Account user id
|
||||
* @param int $OwnerId Account owner id
|
||||
* @param string $Created Account creation date
|
||||
* @param string $Changed Account changed date
|
||||
* @param bool $IsDemo Demo account
|
||||
* @param bool $IsPeer Peer account
|
||||
* @param string $Comments Account comments
|
||||
* @param string $Username Account username
|
||||
* @param string $Password Account password
|
||||
* @param string $FirstName Account holders firstname
|
||||
* @param string $LastName Account holders lastname
|
||||
* @param string $Email Account holders email address
|
||||
* @param string $PrimaryPhone Account holders phone number
|
||||
* @param string $Zip Account holders postal code
|
||||
* @param string $InstantMessenger Account holders IM
|
||||
* @param string $Fax Account holders fax number
|
||||
* @param string $SecondaryPhone Account holders secondary phone number
|
||||
* @param string $SecondaryEmail Account holders secondary email
|
||||
* @param string $Country Account holders country
|
||||
* @param string $Address Account holders physical address
|
||||
* @param string $City Account holders city
|
||||
* @param string $State Account holders state
|
||||
* @param bool $HtmlMail Send HTML email
|
||||
* @param string $CompanyName Account holders Company name
|
||||
* @param bool $EcommerceEnabled Ecommerce enabled
|
||||
* @return void
|
||||
*/
|
||||
public function updateUserDetails($RoleId, $Role, $StatusId, $Status, $LoginStatusId, $LoginStatus, $FailedLogins, $UserId, $OwnerId, $Created, $Changed, $IsDemo, $IsPeer, $Comments, $Username, $Password, $FirstName, $LastName, $Email, $PrimaryPhone, $Zip, $InstantMessenger, $Fax, $SecondaryPhone, $SecondaryEmail, $Country, $Address, $City, $State, $HtmlMail, $CompanyName, $EcommerceEnabled)
|
||||
{
|
||||
$params = array();
|
||||
foreach (get_defined_vars() as $key => $value)
|
||||
{
|
||||
if ($key == 'params')
|
||||
continue;
|
||||
|
||||
$params[$key] = $value;
|
||||
}
|
||||
return $this->executeServerMethod(WebsitePanel::SERVICEFILE_USERS, 'UpdateUser', array('user' => $params))->UpdateUserResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* WebsitePanel::DeleteUser()
|
||||
*
|
||||
* @access public
|
||||
* @param int $userid User id
|
||||
* @return int
|
||||
*/
|
||||
public function deleteUser($userId)
|
||||
{
|
||||
return $this->executeServerMethod(WebsitePanel::SERVICEFILE_USERS, 'DeleteUser', array('userId' => $userId))->DeleteUserResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* WebsitePanel::GetUserByUsername()
|
||||
*
|
||||
* @access public
|
||||
* @param string $username Username
|
||||
* @return array
|
||||
*/
|
||||
public function getUserByUsername($username)
|
||||
{
|
||||
return (array)$this->executeServerMethod(WebsitePanel::SERVICEFILE_USERS, 'GetUserByUsername', array('username' => $username))->GetUserByUsernameResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* WebsitePanel::ChangeUserStatus()
|
||||
*
|
||||
* @param int $userId User id
|
||||
* @param string $status Account status (Active, Suspended, Cancelled, Pending)
|
||||
* @return int
|
||||
*/
|
||||
public function changeUserStatus($userId, $status)
|
||||
{
|
||||
return $this->executeServerMethod(WebsitePanel::SERVICEFILE_USERS, 'ChangeUserStatus', array('userId' => $userId, 'status' => $status))->ChangeUserStatusResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* WebsitePanel::ChangeUserPassword()
|
||||
*
|
||||
* @access public
|
||||
* @param int $userId User id
|
||||
* @param string $password New password
|
||||
* @return int
|
||||
*/
|
||||
public function changeUserPassword($userId, $password)
|
||||
{
|
||||
return $this->executeServerMethod(WebsitePanel::SERVICEFILE_USERS, 'ChangeUserPassword', array('userId' => $userId, 'password' => $password))->ChangeUserPasswordResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* WebsitePanel::GetUserPackages()
|
||||
*
|
||||
* @access public
|
||||
* @param int $userid User id
|
||||
* @return array
|
||||
*/
|
||||
public function getUserPackages($userid)
|
||||
{
|
||||
return (array)$this->executeServerMethod(WebsitePanel::SERVICEFILE_PACKAGES, 'GetMyPackages', array('userId' => $userid))->GetMyPackagesResult->PackageInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* WebsitePanel::getUsersPagedRecursive()
|
||||
*
|
||||
* @param int $userId User id
|
||||
* @param string $filterColumn Column name to filter on
|
||||
* @param string $filterValue Filter value
|
||||
* @param int $statusId Status id
|
||||
* @param int $roleId Role id
|
||||
* @param string $sortColumn Column name to sort on
|
||||
* @param int $startRow Row to start at
|
||||
* @param int $maximumRows Maximum rows to return
|
||||
*/
|
||||
public function getUsersPagedRecursive($userId, $filterColumn, $filterValue, $statusId, $roleId, $sortColumn, $startRow = 0, $maximumRows = 999)
|
||||
{
|
||||
$params = array();
|
||||
foreach (get_defined_vars() as $key => $value)
|
||||
{
|
||||
if ($key == 'params')
|
||||
continue;
|
||||
|
||||
$params[$key] = $value;
|
||||
}
|
||||
return $this->executeServerMethod(WebSitePanel::SERVICEFILE_USERS, 'GetUsersPagedRecursive', $params)->GetUsersPagedRecursiveResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* WebsitePanel::UpdatePackageLiteral()
|
||||
*
|
||||
* @access public
|
||||
* @param int $packageId Package id
|
||||
* @param int $statusId Status id
|
||||
* @param int $planId Plan id
|
||||
* @param string $purchaseDate Purchase date
|
||||
* @param string $packageName Package name
|
||||
* @param string $packageComments Package comments
|
||||
* @return array
|
||||
*/
|
||||
public function updatePackageLiteral($packageId, $statusId, $planId, $purchaseDate, $packageName, $packageComments)
|
||||
{
|
||||
$params = array();
|
||||
foreach (get_defined_vars() as $key => $value)
|
||||
{
|
||||
if ($key == 'params')
|
||||
continue;
|
||||
|
||||
$params[$key] = $value;
|
||||
}
|
||||
return (array)$this->executeServerMethod(WebsitePanel::SERVICEFILE_PACKAGES, 'UpdatePackageLiteral', $params)->UpdatePackageLiteralResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* WebsitePanel::addPackageAddonById()
|
||||
*
|
||||
* @access public
|
||||
* @param mixed $packageId Package id
|
||||
* @param mixed $addonPlanId Addon plan od
|
||||
* @param integer $quantity Quantity
|
||||
* @return array
|
||||
*/
|
||||
public function addPackageAddonById($packageId, $addonPlanId, $quantity = 1)
|
||||
{
|
||||
return (array)$this->executeServerMethod(WebsitePanel::SERVICEFILE_PACKAGES, 'AddPackageAddonById', array('packageId' => $packageId, 'addonPlanId' => $addonPlanId, 'quantity' => $quantity))->AddPackageAddonByIdResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* WebsitePanel::GetSpaceBandwidthUsage()
|
||||
*
|
||||
* @access public
|
||||
* @param int $packageId Package id
|
||||
* @param string $startDate Start date
|
||||
* @param string $endDate Ending date
|
||||
* @return object
|
||||
*/
|
||||
public function getSpaceBandwidthUsage($packageId, $startDate, $endDate)
|
||||
{
|
||||
return $this->executeServerMethod(WebsitePanel::SERVICEFILE_PACKAGES, 'GetPackageBandwidth', array('packageId' => $packageId, 'startDate' => $startDate, 'endDate' => $endDate))->GetPackageBandwidthResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* WebsitePanel::GetSpaceDiskspaceUsage()
|
||||
*
|
||||
* @access private
|
||||
* @param int $packageId Package Id
|
||||
* @return object
|
||||
*/
|
||||
public function getSpaceDiskspaceUsage($packageId)
|
||||
{
|
||||
return $this->executeServerMethod(WebsitePanel::SERVICEFILE_PACKAGES, 'GetPackageDiskspace', array('packageId' => $packageId))->GetPackageDiskspaceResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* WebsitePanel::packageAllocateIpAddress()
|
||||
*
|
||||
* @param mixed $packageId Package id
|
||||
* @param mixed $groupName Group name
|
||||
* @param mixed $pool Address pool
|
||||
* @param integer $addressesNumber Number of IP addresses
|
||||
* @param bool $allocateRandom Allocate IP addresses randomly
|
||||
* @return object
|
||||
*/
|
||||
public function packageAllocateIpAddress($packageId, $groupName = WebsitePanel::IPADDRESS_POOL_WEB, $pool = WebsitePanel::IPADDRESS_GROUP_WEBSITES, $addressesNumber = 1, $allocateRandom = TRUE)
|
||||
{
|
||||
$params = array();
|
||||
foreach (get_defined_vars() as $key => $value)
|
||||
{
|
||||
if ($key == 'params')
|
||||
continue;
|
||||
|
||||
$params[$key] = $value;
|
||||
}
|
||||
return $this->executeServerMethod(WebsitePanel::SERVICEFILE_SERVERS, 'AllocatePackageIPAddresses', $params)->AllocatePackageIPAddressesResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the requested Enterprise Server method / parameters and returns the results
|
||||
*
|
||||
* @access private
|
||||
* @param string $serviceFile Enterprise Server service filename
|
||||
* @param string $serviceMethod Enterprise Server service method name
|
||||
* @param array $methodParameters Method parameters
|
||||
* @throws Exception
|
||||
* @return object
|
||||
*/
|
||||
private function executeServerMethod($serviceFile, $serviceMethod, $methodParameters = array())
|
||||
{
|
||||
$esUrl = (($this->_esUseSsl ? "https" : "http") . "://{$this->_esServerUrl}:{$this->_esServerPort}/{$serviceFile}?WSDL");
|
||||
$soapParams = array('login' => $this->_esUsername,
|
||||
'password' => $this->_esPassword,
|
||||
'cache_wsdl' => WSDL_CACHE_NONE // WSDL caching is an annoying nightmare - we will disable it
|
||||
);
|
||||
try
|
||||
{
|
||||
$client = new SoapClient($esUrl, $soapParams);
|
||||
$result = $client->$serviceMethod($methodParameters);
|
||||
if (is_soap_fault($result))
|
||||
{
|
||||
throw new Exception($result->faultstring);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
throw new Exception($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,197 +0,0 @@
|
|||
<?php if (!defined('WHMCS')) exit('ACCESS DENIED');
|
||||
// Copyright (c) 2012, Outercurve Foundation.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// - Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//
|
||||
// - Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// - Neither the name of the Outercurve Foundation nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/**
|
||||
* websitepanel Server Module - websitepanel Helper Functions
|
||||
*
|
||||
* @author Christopher York
|
||||
* @package websitepanel Server Module - websitepanel Helper Functions
|
||||
* @version v1.0
|
||||
* @link http://www.websitepanel.net/
|
||||
*/
|
||||
|
||||
/**
|
||||
* websitepanel_GetErrorMessage()
|
||||
*
|
||||
* @access public
|
||||
* @param int $code
|
||||
* @return mixed
|
||||
*/
|
||||
function websitepanel_GetErrorMessage($code)
|
||||
{
|
||||
// Error codes
|
||||
$esErrorCodes = array();
|
||||
|
||||
// Include the common / known error codes
|
||||
require_once(ROOTDIR . '/modules/servers/websitepanel/websitepanel.errorcodes.php');
|
||||
$esErrorCodes = websitepanel_GetEnterpriseServerErrors();
|
||||
|
||||
// Check if the error code exists, if not return the code
|
||||
if (array_key_exists($code, $esErrorCodes))
|
||||
{
|
||||
return $esErrorCodes[$code];
|
||||
}
|
||||
else
|
||||
{
|
||||
return $code;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* websitepanel_CreateBandwidthDate()
|
||||
*
|
||||
* @access public
|
||||
* @param mixed $date
|
||||
* @return date
|
||||
*/
|
||||
function websitepanel_CreateBandwidthDate($date)
|
||||
{
|
||||
$dateExploded = explode('-', $date);
|
||||
$currentYear = date('Y');
|
||||
$currentMonth = date('m');
|
||||
$newDate = "{$currentYear}-{$currentMonth}-{$dateExploded[2]}";
|
||||
|
||||
$dateDiff = time() - strtotime('+1 hour', strtotime($newDate));
|
||||
$fullDays = floor($dateDiff / (60 * 60 * 24));
|
||||
if ($fullDays < 0)
|
||||
{
|
||||
return date('Y-m-d', strtotime('-1 month', strtotime($newDate)));
|
||||
}
|
||||
else
|
||||
{
|
||||
return $newDate;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* websitepanel_CalculateBandwidthUsage()
|
||||
*
|
||||
* @access public
|
||||
* @param mixed $params
|
||||
* @param mixed $packageId
|
||||
* @param mixed $startDate
|
||||
* @return int
|
||||
*/
|
||||
function websitepanel_CalculateBandwidthUsage($params, $packageId, $startDate)
|
||||
{
|
||||
// Create the ASPnix websitepanel_EnterpriseServer class object
|
||||
$wsp = new WebsitePanel($params['serverusername'], $params['serverpassword'], $params['serverip'], $params['configoption6'], $params['serversecure']);
|
||||
|
||||
try
|
||||
{
|
||||
$result = $wsp->getSpaceBandwidthUsage($packageId, $startDate, date('Y-m-d', time()));
|
||||
return websitepanel_CalculateUsage($result, WebsitePanel::USAGE_BANDWIDTH);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
// Do nothing, just catch the Exception to keep PHP from exploding :)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* websitepanel_CalculateDiskspaceUsage()
|
||||
*
|
||||
* @access public
|
||||
* @param mixed $params
|
||||
* @param mixed $packageId
|
||||
* @return int
|
||||
*/
|
||||
function websitepanel_CalculateDiskspaceUsage($params, $packageId)
|
||||
{
|
||||
// Create the ASPnix websitepanel_EnterpriseServer class object
|
||||
$wsp = new WebsitePanel($params['serverusername'], $params['serverpassword'], $params['serverip'], $params['configoption6'], $params['serversecure']);
|
||||
|
||||
try
|
||||
{
|
||||
$result = $wsp->getSpaceDiskspaceUsage($packageId);
|
||||
return websitepanel_CalculateUsage($result, WebsitePanel::USAGE_DISKSPACE);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
// Do nothing, just catch the Exception to keep PHP from exploding :)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* websitepanel_CalculateUsage()
|
||||
*
|
||||
* @access public
|
||||
* @param mixed $result
|
||||
* @param int $usageType
|
||||
* @return int
|
||||
*/
|
||||
function websitepanel_CalculateUsage($result, $usageType)
|
||||
{
|
||||
// Process results
|
||||
$xml = simplexml_load_string($result->any);
|
||||
$total = 0;
|
||||
if (count($xml->NewDataSet->Table) > 0)
|
||||
{
|
||||
foreach ($xml->NewDataSet->Table as $table)
|
||||
{
|
||||
switch ($usageType)
|
||||
{
|
||||
case WebsitePanel::USAGE_BANDWIDTH:
|
||||
$total = $total + $table[0]->MegaBytesTotal;
|
||||
break;
|
||||
|
||||
case WebsitePanel::USAGE_DISKSPACE:
|
||||
$total = $total + $table[0]->Diskspace;
|
||||
break;
|
||||
|
||||
default:
|
||||
$total = $total + $table[0]->MegaBytesTotal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $total;
|
||||
}
|
||||
|
||||
/**
|
||||
* websitepanel_GetServerSettings
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
function websitepanel_GetServerSettings()
|
||||
{
|
||||
$settings = array('username' => '', 'password' => '');
|
||||
|
||||
// Retrieve the settings from the modules configuration table
|
||||
$results = select_query('tblservers', 'username,password', array('type' => 'websitepanel'));
|
||||
if (mysql_num_rows($results) != 0)
|
||||
{
|
||||
$row = mysql_fetch_array($results, MYSQL_ASSOC);
|
||||
$settings['username'] = $row['username'];
|
||||
$settings['password'] = decrypt($row['password']);
|
||||
}
|
||||
return $settings;
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,19 +0,0 @@
|
|||
Extract the "includes" and "modules" directories into the root of your WHMCS installation
|
||||
Overwrite any files that already exists
|
||||
|
||||
To enable addon automation...
|
||||
1. WHMCS Admin -> Setup -> Addon Modules -> "WebsitePanel Addons Automation" -> Activate
|
||||
2. Select "Configure"
|
||||
3. Enter your WebsitePanel Enterprise Server details
|
||||
4. WHMCS Admin -> Addons -> "WebsitePanel Addons"
|
||||
5. Enter your addons here. You can get the WHMCS addon ID by clicking the edit icon on the product addon and extracting the &id=x from the URL (x being the WHMCS Addon ID)
|
||||
You can retrieve your WebsitePanel addon ID by clicking the hosting addon and extracting the PlanID=x from the URL (x being the WebsitePanel Addon ID)
|
||||
6. If this is a Dedicated IP address addon, check the Dedicated IP Address box to allow the module to auto-allocate an IP address.
|
||||
|
||||
What does not work?
|
||||
- Quantities, only a single addon => addon can be allocated
|
||||
- Terminating / Suspending Addons, I've ran out of time on what I can do currently
|
||||
- When an IP address is allocated WebsitePanel does not return back what IP was allocated, so WHMCS is not updated which what IP has been allocated to his / her package at this time.
|
||||
- A single user => single package is the only way the WebsitePanel server module works. I have no plans on making this work any other way.
|
||||
|
||||
DO NOT CONTACT WHMCS FOR SUPPORT WITH THIS MODULE - THIS IS NOT DEVELOPED BY WHMCS AND HAS NO AFFILIATION WITH WHMCS OR WHMCS.COM.
|
|
@ -5376,6 +5376,48 @@ AS
|
|||
END
|
||||
GO
|
||||
|
||||
|
||||
|
||||
-- IIS80 Provider update for SNI and CCS support
|
||||
-- Add default serviceproperties for all existing IIS80 Services (if any). These properties are used as markers in the IIS70 Controls in WebPortal to know the version of the IIS Provider
|
||||
declare c cursor read_only for
|
||||
select ServiceID from Services where ProviderID in(select ProviderID from Providers where ProviderName='IIS80')
|
||||
|
||||
declare @ServiceID int
|
||||
|
||||
open c
|
||||
|
||||
fetch next from c
|
||||
into @ServiceID
|
||||
|
||||
while @@FETCH_STATUS = 0
|
||||
begin
|
||||
if not exists(select null from ServiceProperties where ServiceID = @ServiceID and PropertyName = 'sslccscommonpassword')
|
||||
insert into ServiceProperties(ServiceID, PropertyName, PropertyValue)
|
||||
values(@ServiceID, 'sslccscommonpassword', '')
|
||||
|
||||
if not exists(select null from ServiceProperties where ServiceID = @ServiceID and PropertyName = 'sslccsuncpath')
|
||||
insert into ServiceProperties(ServiceID, PropertyName, PropertyValue)
|
||||
values(@ServiceID, 'sslccsuncpath', '')
|
||||
|
||||
if not exists(select null from ServiceProperties where ServiceID = @ServiceID and PropertyName = 'ssluseccs')
|
||||
insert into ServiceProperties(ServiceID, PropertyName, PropertyValue)
|
||||
values(@ServiceID, 'ssluseccs', 'False')
|
||||
|
||||
if not exists(select null from ServiceProperties where ServiceID = @ServiceID and PropertyName = 'ssluseccs')
|
||||
insert into ServiceProperties(ServiceID, PropertyName, PropertyValue)
|
||||
values(@ServiceID, 'sslusesni', 'False')
|
||||
|
||||
fetch next from c
|
||||
into @ServiceID
|
||||
end
|
||||
|
||||
close c
|
||||
|
||||
deallocate c
|
||||
|
||||
GO
|
||||
|
||||
-- Hyper-V 2012 R2
|
||||
IF NOT EXISTS (SELECT * FROM [dbo].[Providers] WHERE [ProviderName] = 'HyperV2012R2')
|
||||
BEGIN
|
||||
|
|
Binary file not shown.
|
@ -193,9 +193,9 @@ namespace WebsitePanel.EnterpriseServer
|
|||
{
|
||||
TaskManager.StartTask("ENTERPRISE_STORAGE", taskName, org.PackageId);
|
||||
|
||||
EnterpriseStorageController.SetFRSMQuotaOnFolder(itemId, folder.Name, quota, quotaType);
|
||||
EnterpriseStorageController.SetDirectoryBrowseEnabled(itemId, folder.Url, directoyBrowsingEnabled);
|
||||
EnterpriseStorageController.SetFolderPermission(itemId, folder.Name, permissions);
|
||||
EnterpriseStorageController.SetFRSMQuotaOnFolder(itemId, folder.Name, quota, quotaType);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
|
@ -586,6 +586,7 @@ namespace WebsitePanel.EnterpriseServer
|
|||
List<ExchangeDomainName> acceptedDomains = GetOrganizationDomains(itemId);
|
||||
|
||||
int exchangeServiceId = GetExchangeServiceID(org.PackageId);
|
||||
|
||||
ExchangeServer exchange = GetExchangeServer(exchangeServiceId, org.ServiceId);
|
||||
|
||||
bool successful = exchange.DeleteOrganization(
|
||||
|
@ -599,6 +600,18 @@ namespace WebsitePanel.EnterpriseServer
|
|||
org.AddressBookPolicy,
|
||||
acceptedDomains.ToArray());
|
||||
|
||||
// delete public folders
|
||||
if (successful)
|
||||
{
|
||||
List<ExchangeAccount> folders = GetAccounts(itemId, ExchangeAccountType.PublicFolder);
|
||||
folders.Sort(delegate(ExchangeAccount f1, ExchangeAccount f2) { return f2.AccountId.CompareTo(f1.AccountId);});
|
||||
|
||||
foreach(ExchangeAccount folder in folders)
|
||||
DeletePublicFolder(itemId, folder.AccountId);
|
||||
|
||||
exchange.DeletePublicFolder(org.OrganizationId, "\\" + org.OrganizationId);
|
||||
}
|
||||
|
||||
|
||||
return successful ? 0 : BusinessErrorCodes.ERROR_EXCHANGE_DELETE_SOME_PROBLEMS;
|
||||
}
|
||||
|
@ -1782,7 +1795,9 @@ namespace WebsitePanel.EnterpriseServer
|
|||
//GetServiceSettings
|
||||
StringDictionary primSettings = ServerController.GetServiceSettings(exchangeServiceId);
|
||||
|
||||
string samAccount = exchange.CreateMailEnableUser(email, org.OrganizationId, org.DistinguishedName, accountType, primSettings["mailboxdatabase"],
|
||||
string samAccount = exchange.CreateMailEnableUser(email, org.OrganizationId, org.DistinguishedName,
|
||||
org.SecurityGroup, org.DefaultDomain,
|
||||
accountType, primSettings["mailboxdatabase"],
|
||||
org.OfflineAddressBook,
|
||||
org.AddressBookPolicy,
|
||||
retUser.SamAccountName,
|
||||
|
@ -5317,6 +5332,54 @@ namespace WebsitePanel.EnterpriseServer
|
|||
TaskManager.CompleteTask();
|
||||
}
|
||||
}
|
||||
|
||||
public static string CreateOrganizationRootPublicFolder(int itemId)
|
||||
{
|
||||
string res = null;
|
||||
|
||||
// place log record
|
||||
TaskManager.StartTask("EXCHANGE", "CREATE_ORG_PUBLIC_FOLDER", itemId);
|
||||
|
||||
try
|
||||
{
|
||||
// load organization
|
||||
Organization org = GetOrganization(itemId);
|
||||
if (org == null)
|
||||
return null;
|
||||
|
||||
// get mailbox settings
|
||||
int exchangeServiceId = GetExchangeServiceID(org.PackageId);
|
||||
|
||||
if (exchangeServiceId <= 0)
|
||||
return null;
|
||||
|
||||
ExchangeServer exchange = GetExchangeServer(exchangeServiceId, org.ServiceId);
|
||||
|
||||
if (exchange == null)
|
||||
return null;
|
||||
|
||||
//Create Exchange Organization
|
||||
if (string.IsNullOrEmpty(org.GlobalAddressList))
|
||||
{
|
||||
ExtendToExchangeOrganization(ref org);
|
||||
|
||||
PackageController.UpdatePackageItem(org);
|
||||
}
|
||||
|
||||
res = exchange.CreateOrganizationRootPublicFolder(org.OrganizationId, org.DistinguishedName, org.SecurityGroup, org.DefaultDomain);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw TaskManager.WriteError(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
TaskManager.CompleteTask();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Helpers
|
||||
|
|
|
@ -419,6 +419,9 @@ namespace WebsitePanel.EnterpriseServer
|
|||
};
|
||||
|
||||
PackageController.AddPackageItem(orgDomain);
|
||||
|
||||
ExchangeServerController.CreateOrganizationRootPublicFolder(itemId);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
|
@ -37,7 +37,9 @@ namespace WebsitePanel.Providers.HostedSolution
|
|||
bool CheckAccountCredentials(string username, string password);
|
||||
// Organizations
|
||||
|
||||
string CreateMailEnableUser(string upn, string organizationId, string organizationDistinguishedName, ExchangeAccountType accountType,
|
||||
string CreateMailEnableUser(string upn, string organizationId, string organizationDistinguishedName,
|
||||
string securityGroup, string organizationDomain,
|
||||
ExchangeAccountType accountType,
|
||||
string mailboxDatabase, string offlineAddressBook, string addressBookPolicy,
|
||||
string accountName, bool enablePOP, bool enableIMAP,
|
||||
bool enableOWA, bool enableMAPI, bool enableActiveSync,
|
||||
|
@ -74,6 +76,8 @@ namespace WebsitePanel.Providers.HostedSolution
|
|||
void SetMailboxPermissions(string organizationId, string accountName, string[] sendAsAccounts, string[] fullAccessAccounts);
|
||||
ExchangeMailbox GetMailboxPermissions(string organizationId, string accountName);
|
||||
ExchangeMailboxStatistics GetMailboxStatistics(string accountName);
|
||||
string[] SetDefaultPublicFolderMailbox(string id, string organizationId, string organizationDistinguishedName);
|
||||
|
||||
|
||||
// Contacts
|
||||
void CreateContact(string organizationId, string organizationDistinguishedName, string contactDisplayName, string contactAccountName, string contactEmail, string defaultOrganizationDomain);
|
||||
|
@ -113,6 +117,8 @@ namespace WebsitePanel.Providers.HostedSolution
|
|||
ExchangeItemStatistics[] GetPublicFoldersStatistics(string organizationId, string[] folders);
|
||||
string[] GetPublicFoldersRecursive(string organizationId, string parent);
|
||||
long GetPublicFolderSize(string organizationId, string folder);
|
||||
string CreateOrganizationRootPublicFolder(string organizationId, string organizationDistinguishedName, string securityGroup, string organizationDomain);
|
||||
|
||||
|
||||
//ActiveSync
|
||||
void CreateOrganizationActiveSyncPolicy(string organizationId);
|
||||
|
|
|
@ -63,6 +63,7 @@ namespace WebsitePanel.Providers.Web
|
|||
private bool heliconApeInstalled;
|
||||
private bool heliconApeEnabled;
|
||||
private HeliconApeStatus heliconApeStatus;
|
||||
private bool sniEnabled;
|
||||
|
||||
public WebSite()
|
||||
{
|
||||
|
@ -187,6 +188,12 @@ namespace WebsitePanel.Providers.Web
|
|||
get { return this.heliconApeStatus; }
|
||||
set { this.heliconApeStatus = value; }
|
||||
}
|
||||
|
||||
public bool SniEnabled
|
||||
{
|
||||
get { return this.sniEnabled; }
|
||||
set { this.sniEnabled = value; }
|
||||
}
|
||||
}
|
||||
|
||||
[Flags]
|
||||
|
|
|
@ -1871,14 +1871,18 @@ namespace WebsitePanel.Providers.HostedSolution
|
|||
}
|
||||
|
||||
|
||||
public string CreateMailEnableUser(string upn, string organizationId, string organizationDistinguishedName, ExchangeAccountType accountType,
|
||||
public string CreateMailEnableUser(string upn, string organizationId, string organizationDistinguishedName,
|
||||
string securityGroup, string organizationDomain,
|
||||
ExchangeAccountType accountType,
|
||||
string mailboxDatabase, string offlineAddressBook, string addressBookPolicy,
|
||||
string accountName, bool enablePOP, bool enableIMAP,
|
||||
bool enableOWA, bool enableMAPI, bool enableActiveSync,
|
||||
long issueWarningKB, long prohibitSendKB, long prohibitSendReceiveKB, int keepDeletedItemsDays,
|
||||
int maxRecipients, int maxSendMessageSizeKB, int maxReceiveMessageSizeKB, bool hideFromAddressBook, bool IsConsumer, bool enabledLitigationHold, long recoverabelItemsSpace, long recoverabelItemsWarning)
|
||||
{
|
||||
return CreateMailEnableUserInternal(upn, organizationId, organizationDistinguishedName, accountType,
|
||||
return CreateMailEnableUserInternal(upn, organizationId, organizationDistinguishedName,
|
||||
securityGroup, organizationDomain,
|
||||
accountType,
|
||||
mailboxDatabase, offlineAddressBook, addressBookPolicy,
|
||||
accountName, enablePOP, enableIMAP,
|
||||
enableOWA, enableMAPI, enableActiveSync,
|
||||
|
@ -1886,7 +1890,9 @@ namespace WebsitePanel.Providers.HostedSolution
|
|||
keepDeletedItemsDays, maxRecipients, maxSendMessageSizeKB, maxReceiveMessageSizeKB, hideFromAddressBook, IsConsumer, enabledLitigationHold, recoverabelItemsSpace, recoverabelItemsWarning);
|
||||
}
|
||||
|
||||
internal virtual string CreateMailEnableUserInternal(string upn, string organizationId, string organizationDistinguishedName, ExchangeAccountType accountType,
|
||||
internal virtual string CreateMailEnableUserInternal(string upn, string organizationId, string organizationDistinguishedName,
|
||||
string securityGroup, string organizationDomain,
|
||||
ExchangeAccountType accountType,
|
||||
string mailboxDatabase, string offlineAddressBook, string addressBookPolicy,
|
||||
string accountName, bool enablePOP, bool enableIMAP,
|
||||
bool enableOWA, bool enableMAPI, bool enableActiveSync,
|
||||
|
@ -1955,8 +1961,19 @@ namespace WebsitePanel.Providers.HostedSolution
|
|||
|
||||
transaction.RegisterEnableMailbox(id);
|
||||
|
||||
// default public folder
|
||||
string orgCanonicalName = ConvertADPathToCanonicalName(organizationDistinguishedName);
|
||||
|
||||
//create organization public folder mailbox if required
|
||||
CheckOrganizationPublicFolderMailbox(runSpace, orgCanonicalName, organizationId, organizationDomain);
|
||||
|
||||
//create organization root folder if required
|
||||
CheckOrganizationRootFolder(runSpace, organizationId, securityGroup, orgCanonicalName, organizationId);
|
||||
|
||||
string windowsEmailAddress = ObjToString(GetPSObjectProperty(result[0], "WindowsEmailAddress"));
|
||||
|
||||
string defaultPublicFolderMailbox = orgCanonicalName + "/" + GetPublicFolderMailboxName(organizationId);
|
||||
|
||||
//update mailbox
|
||||
cmd = new Command("Set-Mailbox");
|
||||
cmd.Parameters.Add("Identity", id);
|
||||
|
@ -1987,6 +2004,8 @@ namespace WebsitePanel.Providers.HostedSolution
|
|||
cmd.Parameters.Add("RecoverableItemsWarningQuota", ConvertKBToUnlimited(recoverabelItemsWarning));
|
||||
}
|
||||
|
||||
cmd.Parameters.Add("DefaultPublicFolderMailbox", defaultPublicFolderMailbox);
|
||||
|
||||
ExecuteShellCommand(runSpace, cmd);
|
||||
|
||||
//Litigation Hold
|
||||
|
@ -4441,8 +4460,6 @@ namespace WebsitePanel.Providers.HostedSolution
|
|||
ExchangeLog.LogEnd("CheckOrganizationPublicFolderMailbox");
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void CheckOrganizationRootFolder(Runspace runSpace, string folder, string user, string orgCanonicalName, string organizationId)
|
||||
{
|
||||
ExchangeLog.LogStart("CheckOrganizationRootFolder");
|
||||
|
@ -4467,6 +4484,48 @@ namespace WebsitePanel.Providers.HostedSolution
|
|||
ExchangeLog.LogEnd("CheckOrganizationRootFolder");
|
||||
}
|
||||
|
||||
private void CheckOrganizationRootPublicFolderPermission(Runspace runSpace, string organizationId)
|
||||
{
|
||||
string rootFolder = "\\" + organizationId;
|
||||
|
||||
// exchange transport needs access to create new items in order to deliver email
|
||||
AddPublicFolderClientPermission(runSpace, rootFolder, "Anonymous", "CreateItems");
|
||||
}
|
||||
|
||||
public string CreateOrganizationRootPublicFolder(string organizationId, string organizationDistinguishedName, string securityGroup, string organizationDomain)
|
||||
{
|
||||
ExchangeLog.LogStart("CreateOrganizationRootPublicFolder");
|
||||
|
||||
string res = null;
|
||||
|
||||
Runspace runSpace = null;
|
||||
try
|
||||
{
|
||||
runSpace = OpenRunspace();
|
||||
|
||||
// default public folder
|
||||
string orgCanonicalName = ConvertADPathToCanonicalName(organizationDistinguishedName);
|
||||
|
||||
//create organization public folder mailbox if required
|
||||
CheckOrganizationPublicFolderMailbox(runSpace, orgCanonicalName, organizationId, organizationDomain);
|
||||
|
||||
//create organization root folder if required
|
||||
CheckOrganizationRootFolder(runSpace, organizationId, securityGroup, orgCanonicalName, organizationId);
|
||||
|
||||
res = orgCanonicalName + "/" + GetPublicFolderMailboxName(organizationId);
|
||||
|
||||
CheckOrganizationRootPublicFolderPermission(runSpace, organizationId);
|
||||
}
|
||||
finally
|
||||
{
|
||||
CloseRunspace(runSpace);
|
||||
}
|
||||
|
||||
ExchangeLog.LogEnd("CreateOrganizationRootPublicFolder");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private string AddPublicFolder(Runspace runSpace, string name, string path, string mailbox)
|
||||
{
|
||||
ExchangeLog.LogStart("CreatePublicFolder");
|
||||
|
@ -4697,9 +4756,7 @@ namespace WebsitePanel.Providers.HostedSolution
|
|||
System.Threading.Thread.Sleep(5000);
|
||||
}
|
||||
|
||||
// exchange transport needs access to create new items in order to deliver email
|
||||
AddPublicFolderClientPermission(runSpace, folder, "Anonymous", "CreateItems");
|
||||
|
||||
CheckOrganizationRootPublicFolderPermission(runSpace, organizationId);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -5209,6 +5266,54 @@ namespace WebsitePanel.Providers.HostedSolution
|
|||
return size;
|
||||
}
|
||||
|
||||
public string[] SetDefaultPublicFolderMailbox(string id, string organizationId, string organizationDistinguishedName)
|
||||
{
|
||||
ExchangeLog.LogStart("SetDefaultPublicFolderMailbox");
|
||||
|
||||
List<string> res = new List<string>();
|
||||
|
||||
Runspace runSpace = null;
|
||||
try
|
||||
{
|
||||
runSpace = OpenRunspace();
|
||||
|
||||
Command cmd = new Command("Get-Mailbox");
|
||||
cmd.Parameters.Add("Identity", id);
|
||||
Collection<PSObject> result = ExecuteShellCommand(runSpace, cmd);
|
||||
|
||||
string oldValue = "";
|
||||
|
||||
if (result != null && result.Count > 0)
|
||||
{
|
||||
oldValue = ObjToString(GetPSObjectProperty(result[0], "DefaultPublicFolderMailbox"));
|
||||
}
|
||||
|
||||
res.Add(oldValue);
|
||||
|
||||
string orgCanonicalName = ConvertADPathToCanonicalName(organizationDistinguishedName);
|
||||
|
||||
string newValue = orgCanonicalName + "/" + GetPublicFolderMailboxName(organizationId);
|
||||
|
||||
if (newValue != oldValue)
|
||||
{
|
||||
cmd = new Command("Set-Mailbox");
|
||||
cmd.Parameters.Add("Identity", id);
|
||||
cmd.Parameters.Add("DefaultPublicFolderMailbox", newValue);
|
||||
|
||||
res.Add(newValue);
|
||||
}
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
CloseRunspace(runSpace);
|
||||
}
|
||||
|
||||
ExchangeLog.LogEnd("SetDefaultPublicFolderMailbox");
|
||||
return res.ToArray();
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Address Lists (GAL, AL, RAL, OAB, ABP)
|
||||
|
|
|
@ -1784,7 +1784,9 @@ namespace WebsitePanel.Providers.HostedSolution
|
|||
}
|
||||
|
||||
|
||||
public string CreateMailEnableUser(string upn, string organizationId, string organizationDistinguishedName, ExchangeAccountType accountType,
|
||||
public string CreateMailEnableUser(string upn, string organizationId, string organizationDistinguishedName,
|
||||
string securityGroup, string organizationDomain,
|
||||
ExchangeAccountType accountType,
|
||||
string mailboxDatabase, string offlineAddressBook, string addressBookPolicy,
|
||||
string accountName, bool enablePOP, bool enableIMAP,
|
||||
bool enableOWA, bool enableMAPI, bool enableActiveSync,
|
||||
|
@ -4852,6 +4854,19 @@ namespace WebsitePanel.Providers.HostedSolution
|
|||
return size;
|
||||
}
|
||||
|
||||
public string CreateOrganizationRootPublicFolder(string organizationId, string organizationDistinguishedName, string securityGroup, string organizationDomain)
|
||||
{
|
||||
// not implemented
|
||||
return null;
|
||||
}
|
||||
|
||||
public string[] SetDefaultPublicFolderMailbox(string id, string organizationId, string organizationDistinguishedName)
|
||||
{
|
||||
// not implemented
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Address Lists (GAL, AL, RAL, OAB, ABP)
|
||||
|
|
|
@ -325,7 +325,8 @@ namespace WebsitePanel.Providers.HostedSolution
|
|||
#endregion
|
||||
|
||||
#region Mailbox
|
||||
internal override string CreateMailEnableUserInternal(string upn, string organizationId, string organizationDistinguishedName, ExchangeAccountType accountType,
|
||||
internal override string CreateMailEnableUserInternal(string upn, string organizationId, string organizationDistinguishedName,
|
||||
ExchangeAccountType accountType,
|
||||
string mailboxDatabase, string offlineAddressBook, string addressBookPolicy,
|
||||
string accountName, bool enablePOP, bool enableIMAP,
|
||||
bool enableOWA, bool enableMAPI, bool enableActiveSync,
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace WebsitePanel.Providers.Web.Iis.Common
|
|||
/// We'll use it in the future to implement management of web farm with shared configuration enabled
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal ServerManager GetServerManager()
|
||||
protected internal ServerManager GetServerManager()
|
||||
{
|
||||
return new ServerManager();
|
||||
}
|
||||
|
|
|
@ -1240,6 +1240,7 @@ namespace WebsitePanel.Providers.Web
|
|||
//
|
||||
site.SiteState = GetSiteState(srvman, siteId);
|
||||
//
|
||||
site.SniEnabled = false;
|
||||
}
|
||||
return site;
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ using WebsitePanel.Providers.Web.Iis.WebObjects;
|
|||
|
||||
namespace WebsitePanel.Providers.Web.Iis
|
||||
{
|
||||
internal sealed class SSLModuleService : ConfigurationModuleService
|
||||
public class SSLModuleService : ConfigurationModuleService
|
||||
{
|
||||
public void GenerateCsr(SSLCertificate cert)
|
||||
{
|
||||
|
|
|
@ -26,18 +26,84 @@
|
|||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
using Microsoft.Web.Administration;
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using WebsitePanel.Providers.Common;
|
||||
using WebsitePanel.Providers.Web.Iis;
|
||||
|
||||
namespace WebsitePanel.Providers.Web
|
||||
{
|
||||
public class IIs80 : IIs70, IWebServer
|
||||
public class IIs80 : IIs70
|
||||
{
|
||||
public IIs80() : base()
|
||||
private SslFlags SSLFlags {
|
||||
get
|
||||
{
|
||||
return (UseSni ? SslFlags.Sni : SslFlags.None) | (UseCcs ? SslFlags.CentralCertStore : SslFlags.None);
|
||||
}
|
||||
}
|
||||
|
||||
public string CCSUncPath {
|
||||
get { return ProviderSettings["SSLCCSUNCPath"]; }
|
||||
}
|
||||
|
||||
public string CCSCommonPassword {
|
||||
get { return ProviderSettings["SSLCCSCommonPassword"]; }
|
||||
}
|
||||
|
||||
public bool UseSni {
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return Convert.ToBoolean(ProviderSettings["SSLUseSNI"]);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool UseCcs
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return Convert.ToBoolean(ProviderSettings["SSLUseCCS"]);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override SettingPair[] GetProviderDefaultSettings()
|
||||
{
|
||||
var allSettings = new List<SettingPair>();
|
||||
allSettings.AddRange(base.GetProviderDefaultSettings());
|
||||
|
||||
// Add these to get som default values in. These are also used a marker in the IIS70_Settings.ascx.cs to know that it is the IIS80 provider that is used
|
||||
allSettings.Add(new SettingPair("SSLUseCCS", false.ToString()));
|
||||
allSettings.Add(new SettingPair("SSLUseSNI", false.ToString()));
|
||||
allSettings.Add(new SettingPair("SSLCCSUNCPath", ""));
|
||||
allSettings.Add(new SettingPair("SSLCCSCommonPassword", ""));
|
||||
|
||||
return allSettings.ToArray();
|
||||
}
|
||||
|
||||
public override string[] Install()
|
||||
{
|
||||
var messages = new List<string>();
|
||||
|
||||
messages.AddRange(base.Install());
|
||||
|
||||
// TODO: Setup ccs
|
||||
|
||||
return messages.ToArray();
|
||||
}
|
||||
|
||||
public override bool IsIISInstalled()
|
||||
|
@ -58,5 +124,70 @@ namespace WebsitePanel.Providers.Web
|
|||
{
|
||||
return IsIISInstalled();
|
||||
}
|
||||
|
||||
public override bool CheckCertificate(WebSite webSite)
|
||||
{
|
||||
var sslObjectService = new SSLModuleService80(SSLFlags, CCSUncPath, CCSCommonPassword);
|
||||
|
||||
return sslObjectService.CheckCertificate(webSite);
|
||||
}
|
||||
|
||||
public override ResultObject DeleteCertificate(SSLCertificate certificate, WebSite website)
|
||||
{
|
||||
var sslObjectService = new SSLModuleService80(SSLFlags, CCSUncPath, CCSCommonPassword);
|
||||
|
||||
return sslObjectService.DeleteCertificate(certificate, website);
|
||||
}
|
||||
|
||||
public override SSLCertificate installPFX(byte[] certificate, string password, WebSite website)
|
||||
{
|
||||
var sslObjectService = new SSLModuleService80(SSLFlags, CCSUncPath, CCSCommonPassword);
|
||||
|
||||
return sslObjectService.InstallPfx(certificate, password, website);
|
||||
}
|
||||
|
||||
public override SSLCertificate ImportCertificate(WebSite website)
|
||||
{
|
||||
var sslObjectService = new SSLModuleService80(SSLFlags, CCSUncPath, CCSCommonPassword);
|
||||
|
||||
return sslObjectService.ImportCertificate(website);
|
||||
}
|
||||
|
||||
public override byte[] exportCertificate(string serialNumber, string password)
|
||||
{
|
||||
var sslObjectService = new SSLModuleService80(SSLFlags, CCSUncPath, CCSCommonPassword);
|
||||
|
||||
return sslObjectService.ExportPfx(serialNumber, password);
|
||||
}
|
||||
|
||||
public override SSLCertificate generateCSR(SSLCertificate certificate)
|
||||
{
|
||||
var sslObjectService = new SSLModuleService80(SSLFlags, CCSUncPath, CCSCommonPassword);
|
||||
|
||||
sslObjectService.GenerateCsr(certificate);
|
||||
|
||||
return certificate;
|
||||
}
|
||||
|
||||
public override List<SSLCertificate> getServerCertificates()
|
||||
{
|
||||
var sslObjectService = new SSLModuleService80(SSLFlags, CCSUncPath, CCSCommonPassword);
|
||||
|
||||
return sslObjectService.GetServerCertificates();
|
||||
}
|
||||
|
||||
public override SSLCertificate installCertificate(SSLCertificate certificate, WebSite website)
|
||||
{
|
||||
var sslObjectService = new SSLModuleService80(SSLFlags, CCSUncPath, CCSCommonPassword);
|
||||
|
||||
return sslObjectService.InstallCertificate(certificate, website);
|
||||
}
|
||||
|
||||
public override WebSite GetSite(string siteId)
|
||||
{
|
||||
var site = base.GetSite(siteId);
|
||||
site.SniEnabled = UseSni;
|
||||
return site;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,508 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using CertEnrollInterop;
|
||||
using WebsitePanel.Providers.Common;
|
||||
using WebsitePanel.Server.Utils;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using Microsoft.Web.Administration;
|
||||
|
||||
namespace WebsitePanel.Providers.Web.Iis
|
||||
{
|
||||
public class SSLModuleService80 : SSLModuleService
|
||||
{
|
||||
private const string CertificateStoreName = "WebHosting";
|
||||
|
||||
public bool UseSNI { get; private set; }
|
||||
public bool UseCCS { get; private set; }
|
||||
public string CCSUncPath { get; private set; }
|
||||
public string CCSCommonPassword { get; private set; }
|
||||
|
||||
public SSLModuleService80(SslFlags sslFlags, string ccsUncPath, string ccsCommonPassword)
|
||||
{
|
||||
UseSNI = sslFlags.HasFlag(SslFlags.Sni);
|
||||
UseCCS = sslFlags.HasFlag(SslFlags.CentralCertStore);
|
||||
CCSUncPath = ccsUncPath;
|
||||
CCSCommonPassword = ccsCommonPassword;
|
||||
}
|
||||
|
||||
public new SSLCertificate InstallCertificate(SSLCertificate cert, WebSite website)
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = Activator.CreateInstance(Type.GetTypeFromProgID("X509Enrollment.CX509Enrollment", true)) as CX509Enrollment;
|
||||
if (response == null)
|
||||
{
|
||||
throw new Exception("Cannot create instance of X509Enrollment.CX509Enrollment");
|
||||
}
|
||||
|
||||
response.Initialize(X509CertificateEnrollmentContext.ContextMachine);
|
||||
response.InstallResponse(
|
||||
InstallResponseRestrictionFlags.AllowUntrustedRoot,
|
||||
cert.Certificate, EncodingType.XCN_CRYPT_STRING_BASE64HEADER,
|
||||
null
|
||||
);
|
||||
|
||||
// At this point, certificate has been installed into "Personal" store
|
||||
// We need to move it into "WebHosting" store
|
||||
// Get certificate
|
||||
var servercert = GetServerCertificates(StoreName.My.ToString()).Single(c => c.FriendlyName == cert.FriendlyName);
|
||||
if (UseCCS)
|
||||
{
|
||||
// Delete existing certificate, if any. This is needed to install a new binding
|
||||
if (CheckCertificate(website))
|
||||
{
|
||||
DeleteCertificate(GetCurrentSiteCertificate(website), website);
|
||||
}
|
||||
}
|
||||
|
||||
// Get certificate data - the one we just added to "Personal" store
|
||||
var storeMy = new X509Store(StoreName.My, StoreLocation.LocalMachine);
|
||||
storeMy.Open(OpenFlags.MaxAllowed);
|
||||
X509CertificateCollection existCerts2 = storeMy.Certificates.Find(X509FindType.FindBySerialNumber, servercert.SerialNumber, false);
|
||||
var certData = existCerts2[0].Export(X509ContentType.Pfx);
|
||||
storeMy.Close();
|
||||
|
||||
if (UseCCS)
|
||||
{
|
||||
// Revert to InstallPfx to install new certificate - this also adds binding
|
||||
InstallPfx(certData, string.Empty, website);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add new certificate to "WebHosting" store
|
||||
var store = new X509Store(CertificateStoreName, StoreLocation.LocalMachine);
|
||||
var x509Cert = new X509Certificate2(certData);
|
||||
store.Open(OpenFlags.ReadWrite);
|
||||
store.Add(x509Cert);
|
||||
store.Close();
|
||||
}
|
||||
|
||||
// Remove certificate from "Personal" store
|
||||
storeMy.Open(OpenFlags.MaxAllowed);
|
||||
X509CertificateCollection existCerts = storeMy.Certificates.Find(X509FindType.FindBySerialNumber, servercert.SerialNumber, false);
|
||||
storeMy.Remove((X509Certificate2)existCerts[0]);
|
||||
storeMy.Close();
|
||||
// Fill object with certificate data
|
||||
cert.SerialNumber = servercert.SerialNumber;
|
||||
cert.ValidFrom = servercert.ValidFrom;
|
||||
cert.ExpiryDate = servercert.ExpiryDate;
|
||||
cert.Hash = servercert.Hash;
|
||||
cert.DistinguishedName = servercert.DistinguishedName;
|
||||
|
||||
if (!UseCCS)
|
||||
{
|
||||
if (CheckCertificate(website))
|
||||
{
|
||||
DeleteCertificate(GetCurrentSiteCertificate(website), website);
|
||||
}
|
||||
|
||||
AddBinding(cert, website);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.WriteError("Error adding SSL certificate", ex);
|
||||
cert.Success = false;
|
||||
}
|
||||
|
||||
return cert;
|
||||
}
|
||||
|
||||
public new List<SSLCertificate> GetServerCertificates()
|
||||
{
|
||||
// Use Web Hosting store - new for IIS 8.0
|
||||
return GetServerCertificates(CertificateStoreName);
|
||||
}
|
||||
|
||||
public new SSLCertificate ImportCertificate(WebSite website)
|
||||
{
|
||||
SSLCertificate certificate;
|
||||
|
||||
try
|
||||
{
|
||||
certificate = GetCurrentSiteCertificate(website);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
certificate = new SSLCertificate
|
||||
{
|
||||
Success = false,
|
||||
Certificate = ex.ToString()
|
||||
};
|
||||
}
|
||||
|
||||
return certificate;
|
||||
}
|
||||
|
||||
public new SSLCertificate InstallPfx(byte[] certificate, string password, WebSite website)
|
||||
{
|
||||
SSLCertificate newcert, oldcert = null;
|
||||
|
||||
// Ensure we perform operations safely and preserve the original state during all manipulations, save the oldcert if one is used
|
||||
if (CheckCertificate(website))
|
||||
{
|
||||
oldcert = GetCurrentSiteCertificate(website);
|
||||
}
|
||||
|
||||
X509Certificate2 x509Cert;
|
||||
var store = new X509Store(CertificateStoreName, StoreLocation.LocalMachine);
|
||||
|
||||
if (UseCCS)
|
||||
{
|
||||
// We need to use this constructor or we won't be able to export this certificate
|
||||
x509Cert = new X509Certificate2(certificate, password, X509KeyStorageFlags.Exportable);
|
||||
|
||||
var certData = x509Cert.Export(X509ContentType.Pfx);
|
||||
var convertedCert = new X509Certificate2(certData, string.Empty, X509KeyStorageFlags.Exportable);
|
||||
|
||||
// Attempts to move certificate to CCS UNC path
|
||||
try
|
||||
{
|
||||
// Create a stream out of that new certificate
|
||||
certData = convertedCert.Export(X509ContentType.Pfx, CCSCommonPassword);
|
||||
|
||||
// Open UNC path and set path to certificate subject
|
||||
var filename = (CCSUncPath.EndsWith("/") ? CCSUncPath: CCSUncPath + "/") + x509Cert.GetNameInfo(X509NameType.SimpleName, false) + ".pfx";
|
||||
var writer = new BinaryWriter(File.Open(filename, FileMode.Create));
|
||||
writer.Write(certData);
|
||||
writer.Flush();
|
||||
writer.Close();
|
||||
// Certificated saved
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Log error
|
||||
Log.WriteError("SSLModuleService could not save certificate to Centralized Certificate Store", ex);
|
||||
// Re-throw
|
||||
throw;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
x509Cert = new X509Certificate2(certificate, password);
|
||||
|
||||
// Step 1: Register X.509 certificate in the store
|
||||
// Trying to keep X.509 store open as less as possible
|
||||
try
|
||||
{
|
||||
store.Open(OpenFlags.ReadWrite);
|
||||
|
||||
store.Add(x509Cert);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.WriteError(String.Format("SSLModuleService could not import PFX into X509Store('{0}', '{1}')", store.Name, store.Location), ex);
|
||||
// Re-throw error
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
store.Close();
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2: Instantiate a copy of new X.509 certificate
|
||||
try
|
||||
{
|
||||
store.Open(OpenFlags.ReadWrite);
|
||||
newcert = GetSSLCertificateFromX509Certificate2(x509Cert);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (!UseCCS)
|
||||
{
|
||||
// Rollback X.509 store changes
|
||||
store.Remove(x509Cert);
|
||||
}
|
||||
// Log error
|
||||
Log.WriteError("SSLModuleService could not instantiate a copy of new X.509 certificate. All previous changes have been rolled back.", ex);
|
||||
// Re-throw
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
store.Close();
|
||||
}
|
||||
|
||||
if (!UseCCS)
|
||||
{
|
||||
// Step 3: Remove old certificate from the web site if any
|
||||
try
|
||||
{
|
||||
store.Open(OpenFlags.ReadWrite);
|
||||
// Check if certificate already exists, remove it.
|
||||
if (oldcert != null)
|
||||
DeleteCertificate(oldcert, website);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Rollback X.509 store changes
|
||||
store.Remove(x509Cert);
|
||||
// Log the error
|
||||
Log.WriteError(
|
||||
String.Format("SSLModuleService could not remove existing certificate from '{0}' web site. All changes have been rolled back.", website.Name), ex);
|
||||
// Re-throw
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
store.Close();
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: Register new certificate with HTTPS binding on the web site
|
||||
try
|
||||
{
|
||||
//if (!UseCCS)
|
||||
//{
|
||||
// store.Open(OpenFlags.ReadWrite);
|
||||
//}
|
||||
|
||||
AddBinding(newcert, website);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (!UseCCS)
|
||||
{
|
||||
// Install old certificate back if any
|
||||
store.Open(OpenFlags.ReadWrite);
|
||||
if (oldcert != null)
|
||||
InstallCertificate(oldcert, website);
|
||||
// Rollback X.509 store changes
|
||||
store.Remove(x509Cert);
|
||||
store.Close();
|
||||
}
|
||||
// Log the error
|
||||
Log.WriteError(
|
||||
String.Format("SSLModuleService could not add new X.509 certificate to '{0}' web site. All changes have been rolled back.", website.Name), ex);
|
||||
// Re-throw
|
||||
throw;
|
||||
}
|
||||
|
||||
return newcert;
|
||||
}
|
||||
|
||||
public new byte[] ExportPfx(string serialNumber, string password)
|
||||
{
|
||||
if (UseCCS)
|
||||
{
|
||||
// This is not a good way to do it
|
||||
// Find cert by somehow perhaps first looking in the database? There vi kan lookup the serialnumber and find the hostname needed to create the path to the cert in CCS and then we can load the certdata into a cert and do a export with new password.
|
||||
// Another solution would be to look through all SSL-bindings on all sites until we found the site with the binding that has this serialNumber. But serialNumber is not good enough, we need hash that is unique and present in bindingInfo
|
||||
// A third solution is to iterate over all files in CCS, load them into memory and find the one with the correct serialNumber, but that cannot be good if there are thousands of files...
|
||||
foreach (var file in Directory.GetFiles(CCSUncPath))
|
||||
{
|
||||
var fileStream = File.OpenRead(file);
|
||||
|
||||
// Read certificate data from file
|
||||
var certData = new byte[fileStream.Length];
|
||||
fileStream.Read(certData, 0, (int) fileStream.Length);
|
||||
var convertedCert = new X509Certificate2(certData, CCSCommonPassword, X509KeyStorageFlags.Exportable);
|
||||
|
||||
fileStream.Close();
|
||||
|
||||
if (convertedCert.SerialNumber == serialNumber)
|
||||
{
|
||||
return convertedCert.Export(X509ContentType.Pfx, password);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var store = new X509Store(CertificateStoreName, StoreLocation.LocalMachine);
|
||||
store.Open(OpenFlags.ReadOnly);
|
||||
var cert = store.Certificates.Find(X509FindType.FindBySerialNumber, serialNumber, false)[0];
|
||||
var exported = cert.Export(X509ContentType.Pfx, password);
|
||||
return exported;
|
||||
}
|
||||
|
||||
|
||||
public new void AddBinding(SSLCertificate certificate, WebSite website)
|
||||
{
|
||||
using (var srvman = GetServerManager())
|
||||
{
|
||||
var store = new X509Store(CertificateStoreName, StoreLocation.LocalMachine);
|
||||
store.Open(OpenFlags.ReadOnly);
|
||||
|
||||
// Look for dedicated ip
|
||||
var dedicatedIp = SiteHasBindingWithDedicatedIp(srvman, website);
|
||||
|
||||
var bindingInformation = string.Format("{0}:443:{1}", website.SiteIPAddress, dedicatedIp ? "" : certificate.Hostname);
|
||||
|
||||
Binding siteBinding = UseCCS ?
|
||||
srvman.Sites[website.SiteId].Bindings.Add(bindingInformation, "https") :
|
||||
srvman.Sites[website.SiteId].Bindings.Add(bindingInformation, certificate.Hash, store.Name);
|
||||
|
||||
if (UseSNI)
|
||||
{
|
||||
siteBinding.SslFlags |= SslFlags.Sni;
|
||||
}
|
||||
if (UseCCS)
|
||||
{
|
||||
siteBinding.SslFlags |= SslFlags.CentralCertStore;
|
||||
}
|
||||
|
||||
store.Close();
|
||||
|
||||
srvman.CommitChanges();
|
||||
}
|
||||
}
|
||||
|
||||
public new ResultObject DeleteCertificate(SSLCertificate certificate, WebSite website)
|
||||
{
|
||||
var result = new ResultObject() { IsSuccess = true };
|
||||
|
||||
if (certificate == null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Regardless of the CCS setting on the server, we try to find and remove the certificate from both CCS and WebHosting Store.
|
||||
// This is because we don't know how this was set when the certificate was added
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(CCSUncPath) && Directory.Exists(CCSUncPath))
|
||||
{
|
||||
// This is where it will be if CCS is used
|
||||
var path = GetCCSPath(certificate.Hostname);
|
||||
if (File.Exists(path))
|
||||
{
|
||||
File.Delete(path);
|
||||
}
|
||||
}
|
||||
|
||||
// Now delete all certs with the same serialnumber in WebHosting Store
|
||||
var store = new X509Store(CertificateStoreName, StoreLocation.LocalMachine);
|
||||
store.Open(OpenFlags.MaxAllowed);
|
||||
|
||||
var certs = store.Certificates.Find(X509FindType.FindBySerialNumber, certificate.SerialNumber, false);
|
||||
foreach (var cert in certs)
|
||||
{
|
||||
store.Remove(cert);
|
||||
}
|
||||
|
||||
store.Close();
|
||||
|
||||
// Remove binding from site
|
||||
if (CheckCertificate(website))
|
||||
{
|
||||
RemoveBinding(certificate, website);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.WriteError(String.Format("Unable to delete certificate for website {0}", website.Name), ex);
|
||||
result.IsSuccess = false;
|
||||
result.AddError("", ex);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public new SSLCertificate GetCurrentSiteCertificate(WebSite website)
|
||||
{
|
||||
using (var srvman = GetServerManager())
|
||||
{
|
||||
var site = srvman.Sites[website.SiteId];
|
||||
var sslBinding = site.Bindings.First(b => b.Protocol == "https");
|
||||
|
||||
X509Certificate2 cert = null;
|
||||
|
||||
// If the certificate is in the central store
|
||||
if (((SslFlags)Enum.Parse(typeof(SslFlags), sslBinding["sslFlags"].ToString())).HasFlag(SslFlags.CentralCertStore))
|
||||
{
|
||||
// Let's try to match binding host and certificate filename
|
||||
var path = GetCCSPath(sslBinding.Host);
|
||||
if (File.Exists(path))
|
||||
{
|
||||
var fileStream = File.OpenRead(path);
|
||||
|
||||
// Read certificate data from file
|
||||
var certData = new byte[fileStream.Length];
|
||||
fileStream.Read(certData, 0, (int) fileStream.Length);
|
||||
cert = new X509Certificate2(certData, CCSCommonPassword);
|
||||
fileStream.Close();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var currentHash = sslBinding.CertificateHash;
|
||||
var store = new X509Store(CertificateStoreName, StoreLocation.LocalMachine);
|
||||
store.Open(OpenFlags.ReadOnly);
|
||||
|
||||
cert = store.Certificates.Cast<X509Certificate2>().Single(c => Convert.ToBase64String(c.GetCertHash()) == Convert.ToBase64String(currentHash));
|
||||
|
||||
store.Close();
|
||||
}
|
||||
|
||||
return GetSSLCertificateFromX509Certificate2(cert);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<SSLCertificate> GetServerCertificates(string certificateStoreName)
|
||||
{
|
||||
var store = new X509Store(certificateStoreName, StoreLocation.LocalMachine);
|
||||
|
||||
List<SSLCertificate> certificates;
|
||||
|
||||
try
|
||||
{
|
||||
store.Open(OpenFlags.ReadOnly);
|
||||
certificates = store.Certificates.Cast<X509Certificate2>().Select(GetSSLCertificateFromX509Certificate2).ToList();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.WriteError(
|
||||
String.Format("SSLModuleService is unable to get certificates from X509Store('{0}', '{1}') and complete GetServerCertificates call", store.Name, store.Location), ex);
|
||||
// Re-throw exception
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
store.Close();
|
||||
}
|
||||
|
||||
return certificates;
|
||||
}
|
||||
|
||||
private string GetCCSPath(string bindingName)
|
||||
{
|
||||
return (CCSUncPath.EndsWith("/") ? CCSUncPath : CCSUncPath + "/") + bindingName + ".pfx";
|
||||
}
|
||||
|
||||
private static SSLCertificate GetSSLCertificateFromX509Certificate2(X509Certificate2 cert)
|
||||
{
|
||||
var certificate = new SSLCertificate
|
||||
{
|
||||
Hostname = cert.GetNameInfo(X509NameType.SimpleName, false),
|
||||
FriendlyName = cert.FriendlyName,
|
||||
CSRLength = Convert.ToInt32(cert.PublicKey.Key.KeySize.ToString(CultureInfo.InvariantCulture)),
|
||||
Installed = true,
|
||||
DistinguishedName = cert.Subject,
|
||||
Hash = cert.GetCertHash(),
|
||||
SerialNumber = cert.SerialNumber,
|
||||
ExpiryDate = DateTime.Parse(cert.GetExpirationDateString()),
|
||||
ValidFrom = DateTime.Parse(cert.GetEffectiveDateString()),
|
||||
Success = true
|
||||
};
|
||||
|
||||
return certificate;
|
||||
}
|
||||
|
||||
private static bool SiteHasBindingWithDedicatedIp(ServerManager srvman, WebSite website)
|
||||
{
|
||||
try
|
||||
{
|
||||
var bindings = srvman.Sites[website.SiteId].Bindings;
|
||||
return bindings.Any(b => string.IsNullOrEmpty(b.Host) && b.BindingInformation.Split(':')[1] != "*");
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,8 +9,9 @@
|
|||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>WebsitePanel.Providers.Web</RootNamespace>
|
||||
<AssemblyName>WebsitePanel.Providers.Web.IIs80</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -32,11 +33,7 @@
|
|||
<ItemGroup>
|
||||
<Reference Include="Microsoft.Web.Administration, Version=7.9.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\Lib\References\Microsoft\Microsoft.Web.Administration.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Web.Management, Version=7.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\Lib\References\Microsoft\Microsoft.Web.Management.dll</HintPath>
|
||||
<HintPath>..\..\Lib\References\Microsoft\Windows2012\Microsoft.Web.Administration.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
|
@ -51,6 +48,9 @@
|
|||
</Compile>
|
||||
<Compile Include="IIs80.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SSL\SSLModuleService80.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\WebsitePanel.Providers.Base\WebsitePanel.Providers.Base.csproj">
|
||||
|
@ -65,7 +65,12 @@
|
|||
<Project>{1b9dce85-c664-49fc-b6e1-86c63cab88d1}</Project>
|
||||
<Name>WebsitePanel.Providers.Web.IIs70</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\WebsitePanel.Server.Utils\WebsitePanel.Server.Utils.csproj">
|
||||
<Project>{e91e52f3-9555-4d00-b577-2b1dbdd87ca7}</Project>
|
||||
<Name>WebsitePanel.Server.Utils</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -90,7 +90,9 @@ namespace WebsitePanel.Server
|
|||
}
|
||||
|
||||
[WebMethod, SoapHeader("settings")]
|
||||
public string CreateMailEnableUser(string upn, string organizationId, string organizationDistinguishedName, ExchangeAccountType accountType,
|
||||
public string CreateMailEnableUser(string upn, string organizationId, string organizationDistinguishedName,
|
||||
string securityGroup, string organizationDomain,
|
||||
ExchangeAccountType accountType,
|
||||
string mailboxDatabase, string offlineAddressBook, string addressBookPolicy,
|
||||
string accountName, bool enablePOP, bool enableIMAP,
|
||||
bool enableOWA, bool enableMAPI, bool enableActiveSync,
|
||||
|
@ -100,7 +102,9 @@ namespace WebsitePanel.Server
|
|||
try
|
||||
{
|
||||
LogStart("CreateMailEnableUser");
|
||||
string ret = ES.CreateMailEnableUser(upn, organizationId, organizationDistinguishedName, accountType,
|
||||
string ret = ES.CreateMailEnableUser(upn, organizationId, organizationDistinguishedName,
|
||||
securityGroup, organizationDomain,
|
||||
accountType,
|
||||
mailboxDatabase, offlineAddressBook, addressBookPolicy,
|
||||
accountName, enablePOP, enableIMAP,
|
||||
enableOWA, enableMAPI, enableActiveSync,
|
||||
|
@ -556,6 +560,24 @@ namespace WebsitePanel.Server
|
|||
}
|
||||
}
|
||||
|
||||
[WebMethod, SoapHeader("settings")]
|
||||
public string[] SetDefaultPublicFolderMailbox(string id, string organizationId, string organizationDistinguishedName)
|
||||
{
|
||||
try
|
||||
{
|
||||
LogStart("SetDefaultPublicFolderMailbox");
|
||||
string[] ret = ES.SetDefaultPublicFolderMailbox(id, organizationId, organizationDistinguishedName);
|
||||
LogEnd("SetDefaultPublicFolderMailbox");
|
||||
return ret;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.WriteError("SetDefaultPublicFolderMailbox", ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Contacts
|
||||
|
@ -1085,6 +1107,23 @@ namespace WebsitePanel.Server
|
|||
}
|
||||
}
|
||||
|
||||
[WebMethod, SoapHeader("settings")]
|
||||
public string CreateOrganizationRootPublicFolder(string organizationId, string organizationDistinguishedName, string securityGroup, string organizationDomain)
|
||||
{
|
||||
try
|
||||
{
|
||||
LogStart("CreateOrganizationRootPublicFolder");
|
||||
string ret = ES.CreateOrganizationRootPublicFolder(organizationId, organizationDistinguishedName, securityGroup, organizationDomain);
|
||||
LogEnd("CreateOrganizationRootPublicFolder");
|
||||
return ret;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.WriteError("CreateOrganizationRootPublicFolder", ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
|
|
@ -140,7 +140,7 @@ table.BorderFillBox td .Brick {padding:0; line-height:normal; margin-bottom:9px;
|
|||
.CalendarWeekend {}
|
||||
.CalendarSelectedDate {color:#fff; font-weight:700; background:#ffd349 !important;}
|
||||
.MessageBox {padding:15px; margin:20px; color:#fff; font-size:14px; text-align:left; font-weight:600; line-height:16px;}
|
||||
.MessageBox.Green {}
|
||||
.MessageBox.Green {background: #008000}
|
||||
.MessageBox.Yellow {background:#f0ad4e;}
|
||||
.MessageBox.Red {background:#f25555;}
|
||||
input.Button1, input.Button2, input.Button3, input.SmallButton, input.LoginButton, input[type=submit] {font-family:'Segoe UI Light','Open Sans',Arial; color:#fff; border:1px solid #5e86aa; background:#6598c5; font-weight:300; text-align:center; vertical-align:middle; cursor:pointer; white-space:nowrap; padding:6px 12px; font-size:14px; line-height:1.428571429;}
|
||||
|
|
|
@ -499,6 +499,40 @@
|
|||
</uc5:EditDomainsList>
|
||||
</td>
|
||||
</tr>
|
||||
<tbody runat="server" ID="IIS80SSLSettings" Visible="False">
|
||||
<tr>
|
||||
<td width="200" class="Normal" valign="top">
|
||||
<asp:Label ID="lblUseSNI" runat="server" Text="Use SNI (Server Name Indication):"></asp:Label>
|
||||
</td>
|
||||
<td class="Normal" valign="top">
|
||||
<asp:CheckBox ID="cbUseSNI" runat="server" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="200" class="Normal" valign="top">
|
||||
<asp:Label ID="lblUseCCS" runat="server" Text="Use Centralized Certificate Store:"></asp:Label>
|
||||
</td>
|
||||
<td class="Normal" valign="top">
|
||||
<asp:CheckBox ID="cbUseCCS" runat="server" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="200" class="Normal" valign="top">
|
||||
<asp:Label ID="lblCCSUNCPath" runat="server" Text="Centralized Certificate Store UNC path :"></asp:Label>
|
||||
</td>
|
||||
<td class="Normal" valign="top">
|
||||
<asp:TextBox ID="txtCCSUNCPath" runat="server" CssClass="NormalTextBox" Width="400px"></asp:TextBox>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="200" class="Normal" valign="top">
|
||||
<asp:Label ID="lblCCSUNCCommonPassword" runat="server" Text="Centralized Certificate Store common password (blank for none):"></asp:Label>
|
||||
</td>
|
||||
<td class="Normal" valign="top">
|
||||
<asp:TextBox ID="txtCCSCommonPassword" runat="server" CssClass="NormalTextBox" Width="400px"></asp:TextBox>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tr>
|
||||
<td class="Normal" valign="top">
|
||||
<asp:Label ID="lblADIntegration" runat="server" meta:resourcekey="lblADIntegration" Text="Active Directory Integration:"></asp:Label>
|
||||
|
|
|
@ -225,6 +225,16 @@ namespace WebsitePanel.Portal.ProviderControls
|
|||
FilteredAppIds = settings["GalleryAppsFilter"];
|
||||
radioFilterAppsList.SelectedIndex = Utils.ParseInt(settings["GalleryAppsFilterMode"], 0);
|
||||
chkGalleryAppsAlwaysIgnoreDependencies.Checked = Utils.ParseBool(settings["GalleryAppsAlwaysIgnoreDependencies"], false);
|
||||
|
||||
// If any of these exists, we assume we are running against the IIS80 provider
|
||||
if (settings["SSLCCSCommonPassword"] != null || settings["SSLCCSUNCPath"] != null || settings["SSLUseCCS"] != null || settings["SSLUseSNI"] != null)
|
||||
{
|
||||
IIS80SSLSettings.Visible = true;
|
||||
cbUseCCS.Checked = Utils.ParseBool(settings["SSLUseCCS"], false);
|
||||
cbUseSNI.Checked = Utils.ParseBool(settings["SSLUseSNI"], false);
|
||||
txtCCSUNCPath.Text = settings["SSLCCSUNCPath"];
|
||||
txtCCSCommonPassword.Text = settings["SSLCCSCommonPassword"];
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveSettings(StringDictionary settings)
|
||||
|
@ -314,6 +324,15 @@ namespace WebsitePanel.Portal.ProviderControls
|
|||
settings["GalleryAppsFilter"] = GetAppsCatalogFilter();
|
||||
settings["GalleryAppsFilterMode"] = radioFilterAppsList.SelectedIndex.ToString();
|
||||
settings["GalleryAppsAlwaysIgnoreDependencies"] = chkGalleryAppsAlwaysIgnoreDependencies.Checked.ToString();
|
||||
|
||||
|
||||
if (IIS80SSLSettings.Visible)
|
||||
{
|
||||
settings["SSLUseCCS"] = cbUseCCS.Checked.ToString();
|
||||
settings["SSLUseSNI"] = cbUseSNI.Checked.ToString();
|
||||
settings["SSLCCSUNCPath"] = txtCCSUNCPath.Text;
|
||||
settings["SSLCCSCommonPassword"] = txtCCSCommonPassword.Text;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,31 +1,3 @@
|
|||
// Copyright (c) 2014, Outercurve Foundation.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// - Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//
|
||||
// - Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// - Neither the name of the Outercurve Foundation nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
|
@ -814,6 +786,87 @@ namespace WebsitePanel.Portal.ProviderControls {
|
|||
/// </remarks>
|
||||
protected global::WebsitePanel.Portal.UserControls.EditDomainsList sharedSslSites;
|
||||
|
||||
/// <summary>
|
||||
/// IIS80SSLSettings control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.HtmlControls.HtmlGenericControl IIS80SSLSettings;
|
||||
|
||||
/// <summary>
|
||||
/// lblUseSNI control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.Label lblUseSNI;
|
||||
|
||||
/// <summary>
|
||||
/// cbUseSNI control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.CheckBox cbUseSNI;
|
||||
|
||||
/// <summary>
|
||||
/// lblUseCCS control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.Label lblUseCCS;
|
||||
|
||||
/// <summary>
|
||||
/// cbUseCCS control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.CheckBox cbUseCCS;
|
||||
|
||||
/// <summary>
|
||||
/// lblCCSUNCPath control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.Label lblCCSUNCPath;
|
||||
|
||||
/// <summary>
|
||||
/// txtCCSUNCPath control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.TextBox txtCCSUNCPath;
|
||||
|
||||
/// <summary>
|
||||
/// lblCCSUNCCommonPassword control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.Label lblCCSUNCCommonPassword;
|
||||
|
||||
/// <summary>
|
||||
/// txtCCSCommonPassword control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.TextBox txtCCSCommonPassword;
|
||||
|
||||
/// <summary>
|
||||
/// lblADIntegration control.
|
||||
/// </summary>
|
||||
|
|
|
@ -76,10 +76,10 @@ namespace WebsitePanel.Portal
|
|||
set { ViewState["PackageId"] = value; }
|
||||
}
|
||||
|
||||
private bool IsDedicatedIP
|
||||
private bool AllowSsl
|
||||
{
|
||||
get { return (bool)ViewState["IsDedicatedIP"]; }
|
||||
set { ViewState["IsDedicatedIP"] = value; }
|
||||
get { return (bool)ViewState["AllowSsl"]; }
|
||||
set { ViewState["AllowSsl"] = value; }
|
||||
}
|
||||
|
||||
private bool IIs7
|
||||
|
@ -111,7 +111,7 @@ namespace WebsitePanel.Portal
|
|||
|
||||
// remove "SSL" tab for a site with dynamic IP
|
||||
var sslTab = filteredTabs.SingleOrDefault(t => t.Id == "SSL");
|
||||
if (!IsDedicatedIP && sslTab != null)
|
||||
if (!AllowSsl && sslTab != null)
|
||||
filteredTabs.Remove(sslTab);
|
||||
|
||||
|
||||
|
@ -277,15 +277,16 @@ namespace WebsitePanel.Portal
|
|||
webSitesCustomErrorsControl.BindWebItem(site);
|
||||
webSitesHeliconZooControl.BindWebItem(site);
|
||||
|
||||
if (site.IsDedicatedIP)
|
||||
// If SNI is enabled on the server, we do allow for SSL even if site not has dedicated Ip
|
||||
if (site.IsDedicatedIP || site.SniEnabled)
|
||||
{
|
||||
IsDedicatedIP = true;
|
||||
AllowSsl = true;
|
||||
WebsitesSSLControl.Visible = true;
|
||||
WebsitesSSLControl.BindWebItem(site);
|
||||
}
|
||||
else
|
||||
{
|
||||
IsDedicatedIP = false;
|
||||
AllowSsl = false;
|
||||
WebsitesSSLControl.Visible = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -102,13 +102,19 @@ namespace WebsitePanel.Portal
|
|||
// php
|
||||
if (PackagesHelper.CheckGroupQuotaEnabled(packageId, ResourceGroups.Web, Quotas.WEB_PHP4))
|
||||
ddlPhp.Items.Add("4");
|
||||
|
||||
var allowSingleValueInPhpDropDown = false;
|
||||
|
||||
if (PackagesHelper.CheckGroupQuotaEnabled(packageId, ResourceGroups.Web, Quotas.WEB_PHP5))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(item.Php5VersionsInstalled))
|
||||
{
|
||||
// Add items from list
|
||||
// Remove empty item. Not allows for PHP5 FastCGI. There is no way to disable a handler without removing it or removing some vital info. If we do that, the user can not choose to run PHP5 FastCGI later
|
||||
ddlPhp.Items.Remove(ddlPhp.Items.FindByValue(""));
|
||||
// Add items from list
|
||||
ddlPhp.Items.AddRange(item.Php5VersionsInstalled.Split('|').Select(v => new ListItem(v.Split(';')[1], "5|" + v.Split(';')[0])).OrderBy(i => i.Text).ToArray());
|
||||
|
||||
allowSingleValueInPhpDropDown = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -116,7 +122,7 @@ namespace WebsitePanel.Portal
|
|||
}
|
||||
}
|
||||
Utils.SelectListItem(ddlPhp, item.PhpInstalled);
|
||||
rowPhp.Visible = ddlPhp.Items.Count > 1;
|
||||
rowPhp.Visible = ddlPhp.Items.Count > 1 || allowSingleValueInPhpDropDown && ddlPhp.Items.Count > 0;
|
||||
|
||||
rowPerl.Visible = PackagesHelper.CheckGroupQuotaEnabled(packageId, ResourceGroups.Web, Quotas.WEB_PERL);
|
||||
rowCgiBin.Visible = PackagesHelper.CheckGroupQuotaEnabled(packageId, ResourceGroups.Web, Quotas.WEB_CGIBIN);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue