merge commit

This commit is contained in:
robvde 2014-11-03 10:47:49 +08:00
commit 0b7831549d
41 changed files with 7095 additions and 4821 deletions

View 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 &quot;one-click login&quot; is now a POST form instead of a link. Credentials are no longer passed through a standard HREF link</li>
<li>Admin area &quot;one-click login&quot; is now a link directly to the WebsitePanel account rather than a login link to WebsitePanel</li>
</ul>
</body>
</html>

View file

@ -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

View 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>

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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');

View file

@ -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

View file

@ -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');

View file

@ -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

View file

@ -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>

View file

@ -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);
}
}

View file

@ -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;
}

View file

@ -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';

View file

@ -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());
}
}
}

View file

@ -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;
}

View file

@ -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.

View file

@ -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

View file

@ -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)
{

View file

@ -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

View file

@ -419,6 +419,9 @@ namespace WebsitePanel.EnterpriseServer
};
PackageController.AddPackageItem(orgDomain);
ExchangeServerController.CreateOrganizationRootPublicFolder(itemId);
}
catch (Exception ex)
{

View file

@ -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);

View file

@ -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]

View file

@ -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)

View file

@ -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)

View file

@ -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,

View file

@ -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();
}

View file

@ -1240,6 +1240,7 @@ namespace WebsitePanel.Providers.Web
//
site.SiteState = GetSiteState(srvman, siteId);
//
site.SniEnabled = false;
}
return site;
}

View file

@ -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)
{

View file

@ -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;
}
}
}

View file

@ -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;
}
}
}
}

View file

@ -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.

View file

@ -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

View file

@ -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;}

View file

@ -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>

View file

@ -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;
}
}
/*

View file

@ -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>

View file

@ -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;
}

View file

@ -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);