merge commit
This commit is contained in:
commit
484e7102b8
23 changed files with 313 additions and 1093 deletions
3
WebsitePanel.WHMCSModule/changelog.log
Normal file
3
WebsitePanel.WHMCSModule/changelog.log
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
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
|
|
@ -46,15 +46,17 @@ function websitepanel_addons_AddonActivation($params)
|
||||||
{
|
{
|
||||||
// Sanity check to make sure the associated service is WebsitePanel based product
|
// Sanity check to make sure the associated service is WebsitePanel based product
|
||||||
// And that the addon purchased has an associated WebsitePanel addon
|
// And that the addon purchased has an associated WebsitePanel addon
|
||||||
$results = full_query("SELECT h.id AS `id` FROM `tblhosting` AS h, `tblwspaddons` 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']}");
|
$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)
|
if (mysql_num_rows($results) > 0)
|
||||||
{
|
{
|
||||||
// Include the WebsitePanel ES Class
|
// Include the WebsitePanel ES Class
|
||||||
require_once(ROOTDIR . '/modules/servers/websitepanel/websitepanel.class.php');
|
require_once(ROOTDIR . '/modules/servers/websitepanel/websitepanel.class.php');
|
||||||
|
require_once(ROOTDIR . '/modules/servers/websitepanel/websitepanel.functions.php');
|
||||||
|
|
||||||
// Retrieve the WebsitePanel Addons module settings
|
// Retrieve the WebsitePanel Addons module settings
|
||||||
$modSettings = websitepanel_addons_GetSettings();
|
$modSettings = websitepanel_addons_GetSettings();
|
||||||
if (empty($modSettings['username']) || empty($modSettings['password']) || empty($modSettings['serverhost']) || empty($modSettings['serverport']))
|
$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
|
// The module is disabled or has not yet been configured - stop
|
||||||
return;
|
return;
|
||||||
|
@ -71,7 +73,7 @@ function websitepanel_addons_AddonActivation($params)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the WebsitePanel object instance
|
// Create the WebsitePanel object instance
|
||||||
$wsp = new WebsitePanel($modSettings['username'], $modSettings['password'], $modSettings['serverhost'], $modSettings['serverport'], (($modSettings['serversecured']) == 'on' ? TRUE : FALSE));
|
$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
|
// Grab the user's details from WebsitePanel in order to get the user's id
|
||||||
$user = $wsp->get_user_by_username($username);
|
$user = $wsp->get_user_by_username($username);
|
||||||
|
@ -89,7 +91,7 @@ function websitepanel_addons_AddonActivation($params)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the associated WebsitePanel addon id
|
// Get the associated WebsitePanel addon id
|
||||||
$results = select_query('tblwspaddons', 'wsp_id,is_ipaddress', array('whmcs_id' => $params['addonid']));
|
$results = select_query('mod_wspaddons', 'wsp_id,is_ipaddress', array('whmcs_id' => $params['addonid']));
|
||||||
$addon = mysql_fetch_array($results);
|
$addon = mysql_fetch_array($results);
|
||||||
$addonPlanId = $addon['wsp_id'];
|
$addonPlanId = $addon['wsp_id'];
|
||||||
$addonIsIpAddress = $addon['is_ipaddress'];
|
$addonIsIpAddress = $addon['is_ipaddress'];
|
||||||
|
@ -129,7 +131,7 @@ function websitepanel_addons_GetSettings()
|
||||||
$results = select_query('tbladdonmodules', 'setting,value', array('module' => 'websitepanel_addons'));
|
$results = select_query('tbladdonmodules', 'setting,value', array('module' => 'websitepanel_addons'));
|
||||||
while (($row = mysql_fetch_array($results)) != false)
|
while (($row = mysql_fetch_array($results)) != false)
|
||||||
{
|
{
|
||||||
$settings[$row['setting']] = $row['value'];
|
$settings[$row[0]] = $row[1];
|
||||||
}
|
}
|
||||||
return $settings;
|
return $settings;
|
||||||
}
|
}
|
|
@ -50,17 +50,19 @@ function websitepanel_sync_ClientEdit($params)
|
||||||
{
|
{
|
||||||
// Include the WebsitePanel ES Class
|
// Include the WebsitePanel ES Class
|
||||||
require_once(ROOTDIR . '/modules/servers/websitepanel/websitepanel.class.php');
|
require_once(ROOTDIR . '/modules/servers/websitepanel/websitepanel.class.php');
|
||||||
|
require_once(ROOTDIR . '/modules/servers/websitepanel/websitepanel.functions.php');
|
||||||
|
|
||||||
// Retrieve the WebsitePanel Addons module settings
|
// Retrieve the WebsitePanel Addons module settings
|
||||||
$modSettings = websitepanel_sync_GetSettings();
|
$modSettings = websitepanel_sync_GetSettings();
|
||||||
if (empty($modSettings['username']) || empty($modSettings['password']) || empty($modSettings['serverhost']) || empty($modSettings['serverport']))
|
$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
|
// The module is disabled or has not yet been configured - stop
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the WebsitePanel object instance
|
// Create the WebsitePanel object instance
|
||||||
$wsp = new WebsitePanel($modSettings['username'], $modSettings['password'], $modSettings['serverhost'], $modSettings['serverport'], (($modSettings['serversecured']) == 'on' ? TRUE : FALSE));
|
$wsp = new WebsitePanel($srvSettings['username'], $srvSettings['password'], $modSettings['serverhost'], $modSettings['serverport'], (($modSettings['serversecured']) == 'on' ? TRUE : FALSE));
|
||||||
|
|
||||||
// Get all WSP users with the old email
|
// Get all WSP users with the old email
|
||||||
$items = (array)$wsp->get_users_paged_recursive(1, 'Email', $params['olddata']['email'], 0, 0, '');
|
$items = (array)$wsp->get_users_paged_recursive(1, 'Email', $params['olddata']['email'], 0, 0, '');
|
||||||
|
|
|
@ -46,13 +46,11 @@ function websitepanel_addons_config()
|
||||||
{
|
{
|
||||||
$configarray = array('name' => 'WebsitePanel Addons Automation',
|
$configarray = array('name' => 'WebsitePanel Addons Automation',
|
||||||
'description' => 'Automates WHMCS product addons with WebsitePanel',
|
'description' => 'Automates WHMCS product addons with WebsitePanel',
|
||||||
'version' => '1.0',
|
'version' => '1.2',
|
||||||
'author' => 'Christopher York',
|
'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'),
|
'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),
|
'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'),
|
'serversecured' => array('FriendlyName', 'Use Secured Connection', 'Type' => 'yesno', 'Description' => 'Tick to use SSL secured connection'),
|
||||||
'username' => array('FriendlyName', 'Username', 'Type' => 'text', 'Size' => 25, 'Description' => 'Enterprise Server username', 'Default' => 'serveradmin'),
|
|
||||||
'password' => array('FriendlyName', 'Password', 'Type' => 'password', 'Size' => 25, 'Description' => 'Enterprise Server password')
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
return $configarray;
|
return $configarray;
|
||||||
|
@ -67,7 +65,7 @@ function websitepanel_addons_config()
|
||||||
function websitepanel_addons_activate()
|
function websitepanel_addons_activate()
|
||||||
{
|
{
|
||||||
// Create the WebsitePanel Addons table
|
// Create the WebsitePanel Addons table
|
||||||
$query = "CREATE TABLE `tblwspaddons` (
|
$query = "CREATE TABLE `mod_wspaddons` (
|
||||||
`whmcs_id` int(11) NOT NULL,
|
`whmcs_id` int(11) NOT NULL,
|
||||||
`wsp_id` int(11) NOT NULL,
|
`wsp_id` int(11) NOT NULL,
|
||||||
`is_ipaddress` bit(1) NOT NULL DEFAULT b'0',
|
`is_ipaddress` bit(1) NOT NULL DEFAULT b'0',
|
||||||
|
@ -94,9 +92,8 @@ function websitepanel_addons_activate()
|
||||||
*/
|
*/
|
||||||
function websitepanel_addons_deactivate()
|
function websitepanel_addons_deactivate()
|
||||||
{
|
{
|
||||||
// Create the WebsitePanel Addons table
|
// Drop the WebsitePanel Addons table
|
||||||
$query = 'DROP TABLE `tblwspaddons`';
|
$result = full_query('DROP TABLE `mod_wspaddons`');
|
||||||
$result = full_query($query);
|
|
||||||
|
|
||||||
// Check the results to verify that the table has been created properly
|
// Check the results to verify that the table has been created properly
|
||||||
if (!$result)
|
if (!$result)
|
||||||
|
@ -109,6 +106,27 @@ function websitepanel_addons_deactivate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* websitepanel_addons_upgrade
|
||||||
|
*
|
||||||
|
* @param $vars array
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
function websitepanel_addons_upgrade($vars)
|
||||||
|
{
|
||||||
|
|
||||||
|
$version = $vars['version'];
|
||||||
|
|
||||||
|
// Adjust the table name and remove the WebsitePanel credentials
|
||||||
|
if ($version < 1.2)
|
||||||
|
{
|
||||||
|
full_query('RENAME TABLE `tblwspaddons` TO `mod_wspaddons`');
|
||||||
|
full_query("DELETE FROM `tbladdonmodules` WHERE `module` = 'websitepanel_addons' AND `setting` = 'username'");
|
||||||
|
full_query("DELETE FROM `tbladdonmodules` WHERE `module` = 'websitepanel_addons' AND `setting` = 'password'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* websitepanel_addons_output
|
* websitepanel_addons_output
|
||||||
*
|
*
|
||||||
|
@ -120,24 +138,24 @@ function websitepanel_addons_output($params)
|
||||||
// Delete the requested WebsitePanel addon
|
// Delete the requested WebsitePanel addon
|
||||||
if (isset($_GET['action']) && $_GET['action'] == 'delete')
|
if (isset($_GET['action']) && $_GET['action'] == 'delete')
|
||||||
{
|
{
|
||||||
delete_query('tblwspaddons', array('whmcs_id' => $_GET['id']));
|
delete_query('mod_wspaddons', array('whmcs_id' => $_GET['id']));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the requested WebsitePanel addon
|
// Add the requested WebsitePanel addon
|
||||||
if ($_POST && isset($_POST['action']) && $_POST['action'] == 'add')
|
if ($_POST && isset($_POST['action']) && $_POST['action'] == 'add')
|
||||||
{
|
{
|
||||||
// Sanity check to make sure the WHMCS addon ID exists
|
// Sanity check to make sure the WHMCS addon ID exists
|
||||||
$results = select_query('tbladdons', 'id', array('id' => $_POST['whmcs_id']));
|
$results = select_query('mod_wspaddons', 'id', array('id' => $_POST['whmcs_id']));
|
||||||
if (mysql_num_rows($results) > 0)
|
if (mysql_num_rows($results) > 0)
|
||||||
{
|
{
|
||||||
$results = select_query('tblwspaddons', 'whmcs_id', array('whmcs_id' => $_POST['whmcs_id']));
|
$results = select_query('mod_wspaddons', 'whmcs_id', array('whmcs_id' => $_POST['whmcs_id']));
|
||||||
if (mysql_num_rows($results) > 0)
|
if (mysql_num_rows($results) > 0)
|
||||||
{
|
{
|
||||||
echo '<p><div style="margin:0 0 -5px 0;padding: 10px;background-color: #FBEEEB;border: 1px dashed #cc0000;font-weight: bold;color: #cc0000;font-size:14px;text-align: center;-moz-border-radius: 10px;-webkit-border-radius: 10px;-o-border-radius: 10px;border-radius: 10px;">Duplicate WHMCS Addon ID. The WHMCS Addon ID Is Assigned To Another WebsitePanel Addon.</div></p>';
|
echo '<p><div style="margin:0 0 -5px 0;padding: 10px;background-color: #FBEEEB;border: 1px dashed #cc0000;font-weight: bold;color: #cc0000;font-size:14px;text-align: center;-moz-border-radius: 10px;-webkit-border-radius: 10px;-o-border-radius: 10px;border-radius: 10px;">Duplicate WHMCS Addon ID. The WHMCS Addon ID Is Assigned To Another WebsitePanel Addon.</div></p>';
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
insert_query('tblwspaddons', array('whmcs_id' => $_POST['whmcs_id'], 'wsp_id' => $_POST['wsp_id'], 'is_ipaddress' => $_POST['is_ipaddress']));
|
insert_query('mod_wspaddons', array('whmcs_id' => $_POST['whmcs_id'], 'wsp_id' => $_POST['wsp_id'], 'is_ipaddress' => $_POST['is_ipaddress']));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -147,7 +165,7 @@ function websitepanel_addons_output($params)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all the assigned addons and display them to the user
|
// Get all the assigned addons and display them to the user
|
||||||
$results = full_query('SELECT a.name AS `name`, a.id AS `whmcs_id`, w.wsp_id AS `wsp_id` FROM `tbladdons` AS a, `tblwspaddons` AS w WHERE w.whmcs_id = a.id');
|
$results = full_query('SELECT a.name AS `name`, a.id AS `whmcs_id`, w.wsp_id AS `wsp_id` FROM `tbladdons` AS a, `mod_wspaddons` AS w WHERE w.whmcs_id = a.id');
|
||||||
|
|
||||||
// Build the table / data grid
|
// Build the table / data grid
|
||||||
echo '<div class="tablebg">';
|
echo '<div class="tablebg">';
|
||||||
|
|
|
@ -46,14 +46,32 @@ function websitepanel_sync_config()
|
||||||
{
|
{
|
||||||
$configarray = array('name' => 'WebsitePanel Sync Automation',
|
$configarray = array('name' => 'WebsitePanel Sync Automation',
|
||||||
'description' => 'Syncs WHMCS client details / contact changes with WebsitePanel',
|
'description' => 'Syncs WHMCS client details / contact changes with WebsitePanel',
|
||||||
'version' => '1.0',
|
'version' => '1.2',
|
||||||
'author' => 'Christopher York',
|
'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'),
|
'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),
|
'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'),
|
'serversecured' => array('FriendlyName', 'Use Secured Connection', 'Type' => 'yesno', 'Description' => 'Tick to use SSL secured connection'),
|
||||||
'username' => array('FriendlyName', 'Username', 'Type' => 'text', 'Size' => 25, 'Description' => 'Enterprise Server username', 'Default' => 'serveradmin'),
|
|
||||||
'password' => array('FriendlyName', 'Password', 'Type' => 'password', 'Size' => 25, 'Description' => 'Enterprise Server password')
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
return $configarray;
|
return $configarray;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* websitepanel_addons_upgrade
|
||||||
|
*
|
||||||
|
* @param $vars array
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
function websitepanel_sync_upgrade($vars)
|
||||||
|
{
|
||||||
|
|
||||||
|
$version = $vars['version'];
|
||||||
|
|
||||||
|
// Remove the WebsitePanel credentials
|
||||||
|
if ($version < 1.2)
|
||||||
|
{
|
||||||
|
full_query("DELETE FROM `tbladdonmodules` WHERE `module` = 'websitepanel_sync' AND `setting` = 'username'");
|
||||||
|
full_query("DELETE FROM `tbladdonmodules` WHERE `module` = 'websitepanel_sync' AND `setting` = 'password'");
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -39,15 +39,22 @@
|
||||||
/**
|
/**
|
||||||
* Common error codes encountered while using the WebsitePanel Server Module
|
* 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
|
* These are not all the Enterprise Server error codes, only the ones I have encountered using the API
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
*/
|
*/
|
||||||
$esErrorCodes = array(-100 => 'User already exists',
|
function websitepanel_GetEnterpriseServerErrors()
|
||||||
-101 => 'User not found',
|
{
|
||||||
-102 => 'User has child user accounts',
|
$esErrorCodes = array(-100 => 'User already exists',
|
||||||
-300 => 'Hosting package could not be found',
|
-101 => 'User not found',
|
||||||
-301 => 'Hosting package has child hosting spaces',
|
-102 => 'User has child user accounts',
|
||||||
-501 => 'The sub-domain belongs to an existing hosting space that does not allow sub-domains to be created',
|
-300 => 'Hosting package could not be found',
|
||||||
-502 => 'The domain or sub-domain exists within another hosting space',
|
-301 => 'Hosting package has child hosting spaces',
|
||||||
-511 => 'Instant alias is enabled, but not configured',
|
-501 => 'The sub-domain belongs to an existing hosting space that does not allow sub-domains to be created',
|
||||||
-601 => 'The website already exists on the target hosting space',
|
-502 => 'The domain or sub-domain exists within another hosting space',
|
||||||
-700 => 'The email domain already exists on the target hosting space',
|
-511 => 'Instant alias is enabled, but not configured',
|
||||||
-1100 => 'User already exists');
|
-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;
|
||||||
|
}
|
|
@ -45,8 +45,14 @@
|
||||||
*/
|
*/
|
||||||
function websitepanel_GetErrorMessage($code)
|
function websitepanel_GetErrorMessage($code)
|
||||||
{
|
{
|
||||||
global $esErrorCodes;
|
// 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))
|
if (array_key_exists($code, $esErrorCodes))
|
||||||
{
|
{
|
||||||
return $esErrorCodes[$code];
|
return $esErrorCodes[$code];
|
||||||
|
@ -167,4 +173,25 @@ function websitepanel_CalculateUsage($result, $usageType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $total;
|
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;
|
||||||
}
|
}
|
|
@ -13,7 +13,7 @@ To enable addon automation...
|
||||||
What does not work?
|
What does not work?
|
||||||
- Quantities, only a single addon => addon can be allocated
|
- Quantities, only a single addon => addon can be allocated
|
||||||
- Terminating / Suspending Addons, I've ran out of time on what I can do currently
|
- 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.
|
- When an IP address is allocated, WebsitePanel does not return back what IP was allocated, so WHMCS is not updated with which IP was assigned to the users hosting space
|
||||||
- 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.
|
- 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.
|
DO NOT CONTACT WHMCS FOR SUPPORT WITH THIS MODULE - THIS IS NOT DEVELOPED BY WHMCS AND HAS NO AFFILIATION WITH WHMCS OR WHMCS.COM.
|
|
@ -0,0 +1,13 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace WebsitePanel.EnterpriseServer.Base.Common
|
||||||
|
{
|
||||||
|
public class WebPlatformInstaller
|
||||||
|
{
|
||||||
|
public const string MAIN_FEED_URL = "https://www.microsoft.com/web/webpi/4.2/webproductlist.xml";
|
||||||
|
public const string ZOO_FEED = "http://www.helicontech.com/zoo/feed/wsp4";
|
||||||
|
}
|
||||||
|
}
|
|
@ -42,6 +42,10 @@ namespace WebsitePanel.EnterpriseServer
|
||||||
public const string BACKUP_SETTINGS = "BackupSettings";
|
public const string BACKUP_SETTINGS = "BackupSettings";
|
||||||
public const string SETUP_SETTINGS = "SetupSettings";
|
public const string SETUP_SETTINGS = "SetupSettings";
|
||||||
public const string WPI_SETTINGS = "WpiSettings";
|
public const string WPI_SETTINGS = "WpiSettings";
|
||||||
|
|
||||||
|
// key to access to wpi main & custom feed in wpi settings
|
||||||
|
public const string WPI_MAIN_FEED_KEY = "WpiMainFeedUrl";
|
||||||
|
public const string FEED_ULS_KEY = "FeedUrls";
|
||||||
|
|
||||||
public static readonly SystemSettings Empty = new SystemSettings { SettingsArray = new string[][] {} };
|
public static readonly SystemSettings Empty = new SystemSettings { SettingsArray = new string[][] {} };
|
||||||
|
|
||||||
|
|
|
@ -74,6 +74,7 @@
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Common\MailTemplate.cs" />
|
<Compile Include="Common\MailTemplate.cs" />
|
||||||
|
<Compile Include="Common\WebPlatformInstaller.cs" />
|
||||||
<Compile Include="DatabaseServers\DatabaseBrowserConfiguration.cs" />
|
<Compile Include="DatabaseServers\DatabaseBrowserConfiguration.cs" />
|
||||||
<Compile Include="Ecommerce\BillingCycle.cs" />
|
<Compile Include="Ecommerce\BillingCycle.cs" />
|
||||||
<Compile Include="Ecommerce\Category.cs" />
|
<Compile Include="Ecommerce\Category.cs" />
|
||||||
|
|
|
@ -29,15 +29,14 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using WebsitePanel.Providers.Web;
|
using WebsitePanel.EnterpriseServer.Base.Common;
|
||||||
|
using WebsitePanel.Providers.Web;
|
||||||
using WebsitePanel.Providers.ResultObjects;
|
using WebsitePanel.Providers.ResultObjects;
|
||||||
using WebsitePanel.Providers.Database;
|
using WebsitePanel.Providers.Database;
|
||||||
using WebsitePanel.Providers.WebAppGallery;
|
using WebsitePanel.Providers.WebAppGallery;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.Reflection;
|
|
||||||
using WebsitePanel.Providers.Common;
|
using WebsitePanel.Providers.Common;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace WebsitePanel.EnterpriseServer
|
namespace WebsitePanel.EnterpriseServer
|
||||||
{
|
{
|
||||||
|
@ -72,28 +71,33 @@ namespace WebsitePanel.EnterpriseServer
|
||||||
|
|
||||||
private static string[] getFeedsFromSettingsByServiceId(int serviceId)
|
private static string[] getFeedsFromSettingsByServiceId(int serviceId)
|
||||||
{
|
{
|
||||||
StringDictionary serviceSettings = ServerController.GetServiceSettings(serviceId);
|
var wpiSettings = SystemController.GetSystemSettings(SystemSettings.WPI_SETTINGS);
|
||||||
|
|
||||||
List<string> arFeeds = new List<string>();
|
List<string> feeds = new List<string>();
|
||||||
|
|
||||||
if (Utils.ParseBool(serviceSettings["FeedEnableMicrosoft"], true))
|
// Microsoft feed
|
||||||
|
string mainFeedUrl = wpiSettings[SystemSettings.WPI_MAIN_FEED_KEY];
|
||||||
|
if (string.IsNullOrEmpty(mainFeedUrl))
|
||||||
{
|
{
|
||||||
arFeeds.Add(esServers.MAIN_WPI_FEED);
|
mainFeedUrl = WebPlatformInstaller.MAIN_FEED_URL;
|
||||||
}
|
}
|
||||||
|
feeds.Add(mainFeedUrl);
|
||||||
|
|
||||||
if (Utils.ParseBool(serviceSettings["FeedEnableHelicon"], true))
|
// Zoo Feed
|
||||||
{
|
feeds.Add(WebPlatformInstaller.ZOO_FEED);
|
||||||
arFeeds.Add(esServers.HELICON_WPI_FEED);
|
|
||||||
}
|
|
||||||
|
|
||||||
string additionalFeeds = serviceSettings["FeedUrls"];
|
|
||||||
|
// additional feeds
|
||||||
|
string additionalFeeds = wpiSettings[SystemSettings.FEED_ULS_KEY];
|
||||||
if (!string.IsNullOrEmpty(additionalFeeds))
|
if (!string.IsNullOrEmpty(additionalFeeds))
|
||||||
{
|
{
|
||||||
arFeeds.AddRange(additionalFeeds.Split(';'));
|
feeds.AddRange(additionalFeeds.Split(';'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return arFeeds.ToArray();
|
return feeds.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void InitFeedsByServiceId(int UserId, int serviceId)
|
public static void InitFeedsByServiceId(int UserId, int serviceId)
|
||||||
{
|
{
|
||||||
string[] feeds = getFeedsFromSettingsByServiceId(serviceId);
|
string[] feeds = getFeedsFromSettingsByServiceId(serviceId);
|
||||||
|
|
|
@ -35,6 +35,7 @@ using System.Collections.Generic;
|
||||||
using System.Web.Services;
|
using System.Web.Services;
|
||||||
using System.Web.Services.Protocols;
|
using System.Web.Services.Protocols;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
using WebsitePanel.EnterpriseServer.Base.Common;
|
||||||
using WebsitePanel.Providers.Common;
|
using WebsitePanel.Providers.Common;
|
||||||
using Microsoft.Web.Services3;
|
using Microsoft.Web.Services3;
|
||||||
|
|
||||||
|
@ -54,8 +55,10 @@ namespace WebsitePanel.EnterpriseServer
|
||||||
[ToolboxItem(false)]
|
[ToolboxItem(false)]
|
||||||
public class esServers : System.Web.Services.WebService
|
public class esServers : System.Web.Services.WebService
|
||||||
{
|
{
|
||||||
public const string MAIN_WPI_FEED = "https://www.microsoft.com/web/webpi/4.0/WebProductList.xml";
|
/*
|
||||||
|
public const string MAIN_WPI_FEED = "https://www.microsoft.com/web/webpi/4.2/WebProductList.xml";
|
||||||
public const string HELICON_WPI_FEED = "http://www.helicontech.com/zoo/feed/wsp4";
|
public const string HELICON_WPI_FEED = "http://www.helicontech.com/zoo/feed/wsp4";
|
||||||
|
*/
|
||||||
|
|
||||||
#region Servers
|
#region Servers
|
||||||
[WebMethod]
|
[WebMethod]
|
||||||
|
@ -696,25 +699,28 @@ namespace WebsitePanel.EnterpriseServer
|
||||||
var wpiSettings = SystemController.GetSystemSettings(SystemSettings.WPI_SETTINGS);
|
var wpiSettings = SystemController.GetSystemSettings(SystemSettings.WPI_SETTINGS);
|
||||||
|
|
||||||
|
|
||||||
List<string> arFeeds = new List<string>();
|
List<string> feeds = new List<string>();
|
||||||
|
|
||||||
if (Utils.ParseBool(wpiSettings["FeedEnableMicrosoft"] ,true))
|
// Microsoft feed
|
||||||
|
string mainFeedUrl = wpiSettings[SystemSettings.WPI_MAIN_FEED_KEY];
|
||||||
|
if (string.IsNullOrEmpty(mainFeedUrl))
|
||||||
{
|
{
|
||||||
arFeeds.Add( MAIN_WPI_FEED );
|
mainFeedUrl = WebPlatformInstaller.MAIN_FEED_URL;
|
||||||
}
|
}
|
||||||
|
feeds.Add(mainFeedUrl);
|
||||||
|
|
||||||
if (Utils.ParseBool(wpiSettings["FeedEnableHelicon"] ,true))
|
// Zoo Feed
|
||||||
{
|
feeds.Add(WebPlatformInstaller.ZOO_FEED);
|
||||||
arFeeds.Add( HELICON_WPI_FEED );
|
|
||||||
}
|
|
||||||
|
// additional feeds
|
||||||
string additionalFeeds = wpiSettings["FeedUrls"];
|
string additionalFeeds = wpiSettings[SystemSettings.FEED_ULS_KEY];
|
||||||
if (!string.IsNullOrEmpty(additionalFeeds))
|
if (!string.IsNullOrEmpty(additionalFeeds))
|
||||||
{
|
{
|
||||||
arFeeds.AddRange(additionalFeeds.Split(';'));
|
feeds.AddRange(additionalFeeds.Split(';'));
|
||||||
}
|
}
|
||||||
|
|
||||||
OperatingSystemController.InitWPIFeeds(serverId, string.Join(";", arFeeds));
|
OperatingSystemController.InitWPIFeeds(serverId, string.Join(";", feeds));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -279,7 +279,8 @@ namespace WebsitePanel.Providers.Web
|
||||||
get { return FileUtils.EvaluateSystemVariables(ProviderSettings["ProtectedFoldersFile"]); }
|
get { return FileUtils.EvaluateSystemVariables(ProviderSettings["ProtectedFoldersFile"]); }
|
||||||
}
|
}
|
||||||
|
|
||||||
protected string GalleryXmlFeedUrl
|
/*
|
||||||
|
protected string GalleryXmlFeedUrl
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
@ -289,6 +290,7 @@ namespace WebsitePanel.Providers.Web
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private WmiHelper wmi = null;
|
private WmiHelper wmi = null;
|
||||||
|
|
|
@ -1,943 +0,0 @@
|
||||||
// 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.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
using System.Xml;
|
|
||||||
using System.Xml.Serialization;
|
|
||||||
|
|
||||||
using Microsoft.Practices.EnterpriseLibrary.Caching;
|
|
||||||
using System.Net;
|
|
||||||
using System.IO;
|
|
||||||
using WebsitePanel.Server.Utils;
|
|
||||||
using WebsitePanel.Providers.WebAppGallery;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Web;
|
|
||||||
using System.Reflection;
|
|
||||||
using Microsoft.Web.Deployment;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Security.Cryptography;
|
|
||||||
using System.Collections;
|
|
||||||
using Microsoft.Win32;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace WebsitePanel.Providers.Web
|
|
||||||
{
|
|
||||||
[Obsolete]
|
|
||||||
public sealed class WebApplicationGallery
|
|
||||||
{
|
|
||||||
// MS Deploy library
|
|
||||||
private const string MS_DEPLOY_ASSEMBLY_NAME = "Microsoft.Web.Deployment";
|
|
||||||
|
|
||||||
private CacheManager cache;
|
|
||||||
private static DeploymentSkipDirective SkipMsSQL = new DeploymentSkipDirective("skipSqlDirective", "objectName=dbFullSql");
|
|
||||||
private static DeploymentSkipDirective SkipMySQL = new DeploymentSkipDirective("skipSqlDirective", "objectName=dbMySql");
|
|
||||||
|
|
||||||
public const string AtomFeedNamespace = "http://www.w3.org/2005/Atom";
|
|
||||||
|
|
||||||
public static string WEB_PI_USER_AGENT_HEADER = "Platform-Installer/{0}({1})";
|
|
||||||
public const string WEB_PI_APP_PACK_ROOT_INSTALLER_ITEM_MISSING = "Root installer item for the {0} application could not be found. Please contact your Web Application Gallery feed provider to resolve the error.";
|
|
||||||
public const string WEB_PI_APP_PACK_DISPLAY_URL_MISSING = "Web application '{0}' could not be downloaded as installer displayURL is empty or missing.";
|
|
||||||
|
|
||||||
// web application gallery
|
|
||||||
public const string WAG_XML_FEED_CACHE_KEY = "WAG_XML_FEED_CACHE_KEY";
|
|
||||||
public const int WEB_APPLICATIONS_CACHE_STORE_MINUTES = 60;
|
|
||||||
public const int XML_FEED_RECOVERY_ATTEMPTS = 10;
|
|
||||||
// public const string WAG_DEFAULT_FEED_URL = "https://www.microsoft.com/web/webpi/3.0/WebApplicationList.xml";
|
|
||||||
public const string WAG_DEFAULT_FEED_URL = "https://www.microsoft.com/web/webpi/4.0/webapplicationlist.xml";
|
|
||||||
|
|
||||||
// well-known parameters matching
|
|
||||||
public readonly Dictionary<string, DeploymentParameterWellKnownTag> wellKnownParameters
|
|
||||||
= new Dictionary<string, DeploymentParameterWellKnownTag>(StringComparer.InvariantCultureIgnoreCase)
|
|
||||||
{
|
|
||||||
{"Database Server", DeploymentParameterWellKnownTag.DBServer},
|
|
||||||
{"Database Administrator", DeploymentParameterWellKnownTag.DBAdminUserName},
|
|
||||||
{"Database Administrator Password", DeploymentParameterWellKnownTag.DBAdminPassword},
|
|
||||||
{"Database Name", DeploymentParameterWellKnownTag.DBName},
|
|
||||||
{"Database User Name", DeploymentParameterWellKnownTag.DBUserName},
|
|
||||||
{"Database Password", DeploymentParameterWellKnownTag.DBUserPassword}
|
|
||||||
};
|
|
||||||
|
|
||||||
// well-known dependencies matching
|
|
||||||
public readonly Dictionary<string, GalleryApplicationWellKnownDependency> wellKnownDependencies
|
|
||||||
= new Dictionary<string, GalleryApplicationWellKnownDependency>(StringComparer.InvariantCultureIgnoreCase)
|
|
||||||
{
|
|
||||||
{"ASPNETApp", GalleryApplicationWellKnownDependency.AspNet20},
|
|
||||||
{"ASPNET35App", GalleryApplicationWellKnownDependency.AspNet20},
|
|
||||||
{"MVCApp", GalleryApplicationWellKnownDependency.AspNet20},
|
|
||||||
{"ASPNET4App", GalleryApplicationWellKnownDependency.AspNet40},
|
|
||||||
{"PHPApp", GalleryApplicationWellKnownDependency.PHP},
|
|
||||||
{"SQLApp", GalleryApplicationWellKnownDependency.SQL},
|
|
||||||
{"SQLDriverPHPApp", GalleryApplicationWellKnownDependency.SQL},
|
|
||||||
{"MySQLApp", GalleryApplicationWellKnownDependency.MySQL}
|
|
||||||
};
|
|
||||||
|
|
||||||
private string feedXmlURI;
|
|
||||||
|
|
||||||
static WebApplicationGallery()
|
|
||||||
{
|
|
||||||
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_MSDeploy_AssemblyResolve);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Assembly CurrentDomain_MSDeploy_AssemblyResolve(object sender, ResolveEventArgs args)
|
|
||||||
{
|
|
||||||
// Ensure we resolve MSDeploy assembly
|
|
||||||
if (args.Name.StartsWith(MS_DEPLOY_ASSEMBLY_NAME) == false)
|
|
||||||
return null;
|
|
||||||
//
|
|
||||||
var regkey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\IIS Extensions\MSDeploy");
|
|
||||||
//
|
|
||||||
if (regkey == null)
|
|
||||||
return null;
|
|
||||||
// Always start with the most recent version of MSDeploy
|
|
||||||
var versionKeys = regkey.GetSubKeyNames().OrderByDescending(x => x).ToArray();
|
|
||||||
// Log all version keys found
|
|
||||||
Array.ForEach(versionKeys, (x) => { Log.WriteInfo("MSDeploy version key found: {0}", x); });
|
|
||||||
// Determine appropriate key name to query for
|
|
||||||
var installPathKey = (IntPtr.Size == 8) ? "InstallPath" : "InstallPath_x86";
|
|
||||||
|
|
||||||
// Check if running in 32bit mode under 64bit Windows (WOW64) - works with .NET 2.0+
|
|
||||||
if (Environment.GetEnvironmentVariable("PROCESSOR_ARCHITEW6432") == "AMD64")
|
|
||||||
{
|
|
||||||
installPathKey = "InstallPath_x64";
|
|
||||||
}
|
|
||||||
|
|
||||||
var fileVersion = String.Empty;
|
|
||||||
//
|
|
||||||
var libPath = String.Empty;
|
|
||||||
//
|
|
||||||
for (int i = 0; i < versionKeys.Length; i++)
|
|
||||||
{
|
|
||||||
var versionKey = regkey.OpenSubKey(versionKeys[i]);
|
|
||||||
//
|
|
||||||
libPath = Path.Combine(versionKey.GetValue(installPathKey).ToString(), String.Concat(MS_DEPLOY_ASSEMBLY_NAME, ".dll"));
|
|
||||||
//
|
|
||||||
Log.WriteInfo("MSDeploy v{0}; Lib Path: {1}", versionKeys[i], libPath);
|
|
||||||
//
|
|
||||||
if (File.Exists(libPath) == true)
|
|
||||||
{
|
|
||||||
Log.WriteInfo("MSDeploy Lib Path: {0};", libPath);
|
|
||||||
var fileVerInfo = FileVersionInfo.GetVersionInfo(libPath);
|
|
||||||
//
|
|
||||||
WEB_PI_USER_AGENT_HEADER = String.Format(WEB_PI_USER_AGENT_HEADER, fileVerInfo.FileVersion, Environment.OSVersion.VersionString);
|
|
||||||
//
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//
|
|
||||||
if (String.IsNullOrEmpty(libPath) == false)
|
|
||||||
return Assembly.LoadFrom(libPath);
|
|
||||||
//
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public WebApplicationGallery()
|
|
||||||
: this(WAG_DEFAULT_FEED_URL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public WebApplicationGallery(string feedXmlURI)
|
|
||||||
{
|
|
||||||
cache = CacheFactory.GetCacheManager();
|
|
||||||
//
|
|
||||||
this.feedXmlURI = feedXmlURI;
|
|
||||||
}
|
|
||||||
|
|
||||||
public XmlDocument GetServiceXmlFeed()
|
|
||||||
{
|
|
||||||
XmlDocument xmldoc = (XmlDocument)cache[WAG_XML_FEED_CACHE_KEY];
|
|
||||||
//
|
|
||||||
if (xmldoc == null)
|
|
||||||
{
|
|
||||||
// First trying to load as usual...
|
|
||||||
try
|
|
||||||
{
|
|
||||||
//
|
|
||||||
xmldoc = new XmlDocument();
|
|
||||||
xmldoc.Load(feedXmlURI);
|
|
||||||
|
|
||||||
// Add XML to the cache
|
|
||||||
cache.Add(WAG_XML_FEED_CACHE_KEY, xmldoc);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log.WriteError(
|
|
||||||
String.Format(@"Could not load xml feed in a usual way from '{0}',
|
|
||||||
thus proceed to XML-FEED-RECOVERY section to try download it again in an advanced way.
|
|
||||||
No action is required the message for information purposes only.", feedXmlURI), ex);
|
|
||||||
}
|
|
||||||
// Unable to load feed in the usual way, so lets try to "fix" content-encoding issue
|
|
||||||
if (!xmldoc.HasChildNodes)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
int numOfRetries = 0;
|
|
||||||
//
|
|
||||||
try
|
|
||||||
{
|
|
||||||
WebClient wc = new WebClient();
|
|
||||||
wc.Headers.Add(HttpRequestHeader.UserAgent, WEB_PI_USER_AGENT_HEADER);
|
|
||||||
// Setting response encoding explicitly
|
|
||||||
wc.Encoding = Encoding.UTF8;
|
|
||||||
//
|
|
||||||
string feedXmlString = wc.DownloadString(feedXmlURI);
|
|
||||||
// Loading XML for several times with shift the from the beginning may helps
|
|
||||||
// to eliminate encoding issue (somtimes several starting bytes are not recognized
|
|
||||||
// by the parser and thus feed load is failed)
|
|
||||||
do
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
xmldoc.LoadXml(feedXmlString.Substring(numOfRetries));
|
|
||||||
|
|
||||||
// Add XML to the cache
|
|
||||||
cache.Add(WAG_XML_FEED_CACHE_KEY, xmldoc);
|
|
||||||
//
|
|
||||||
Log.WriteInfo("XML feed has been successfully added into the cache. See its content below.");
|
|
||||||
Log.WriteInfo(xmldoc.OuterXml);
|
|
||||||
// Exit from the loop if XML is loaded successfully
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
catch(Exception ex)
|
|
||||||
{
|
|
||||||
// Log an exception
|
|
||||||
Log.WriteError(
|
|
||||||
String.Format("XML-FEED-RECOVERY is failed at {0} attempt. {1} attempts left.", numOfRetries, XML_FEED_RECOVERY_ATTEMPTS-numOfRetries), ex);
|
|
||||||
//
|
|
||||||
numOfRetries++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (numOfRetries <= XML_FEED_RECOVERY_ATTEMPTS);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
// Log an exception
|
|
||||||
Log.WriteError(@"XML-FEED-RECOVERY is failed to recover the feed automatically.
|
|
||||||
Please ensure that the feed is a correct XML file if you use a custom one,
|
|
||||||
otherwise contact WebsitePanel Software for further assistance.", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
////
|
|
||||||
//XmlNamespaceManager nsmgr = GetXmlNsManager(xmldoc.NameTable);
|
|
||||||
////
|
|
||||||
//XmlNode rootNode = xmldoc.DocumentElement.SelectSingleNode("atom:dependencies", nsmgr);
|
|
||||||
////
|
|
||||||
//XmlNodeList idRefNodes = rootNode.SelectNodes(".//atom:dependency[@idref]", nsmgr);
|
|
||||||
////
|
|
||||||
//foreach (XmlNode idRefNode in idRefNodes)
|
|
||||||
//{
|
|
||||||
// //
|
|
||||||
// XmlNode idRefRepo = xmldoc.DocumentElement.SelectSingleNode(
|
|
||||||
// String.Format("//atom:dependency[@id='{0}']", idRefNode.Attributes["idref"].Value), nsmgr);
|
|
||||||
// //
|
|
||||||
// if (idRefRepo != null)
|
|
||||||
// {
|
|
||||||
// idRefNode.ParentNode.ReplaceChild(idRefRepo.Clone(), idRefNode);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
////
|
|
||||||
//idRefNodes = xmldoc.DocumentElement.SelectNodes("//atom:dependency[@idref]", nsmgr);
|
|
||||||
////
|
|
||||||
//foreach (XmlNode idRefNode in idRefNodes)
|
|
||||||
//{
|
|
||||||
// //
|
|
||||||
// XmlNode idRefRepo = xmldoc.DocumentElement.SelectSingleNode(
|
|
||||||
// String.Format("//atom:dependency[@id='{0}']", idRefNode.Attributes["idref"].Value), nsmgr);
|
|
||||||
// //
|
|
||||||
// if (idRefRepo != null)
|
|
||||||
// {
|
|
||||||
// idRefNode.ParentNode.ReplaceChild(idRefRepo.Clone(), idRefNode);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
//
|
|
||||||
return xmldoc;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsMsDeployInstalled()
|
|
||||||
{
|
|
||||||
//
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Assembly.Load(MS_DEPLOY_ASSEMBLY_NAME);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// type could not be instantiated
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<GalleryCategory> GetCategories()
|
|
||||||
{
|
|
||||||
XmlDocument xmldoc = GetServiceXmlFeed();
|
|
||||||
//
|
|
||||||
if (xmldoc == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
// get namespace manager
|
|
||||||
XmlNamespaceManager nsmgr = GetXmlNsManager(xmldoc.NameTable);
|
|
||||||
|
|
||||||
// get the list of all categories that are used by applications
|
|
||||||
List<string> appCategories = new List<string>();
|
|
||||||
foreach (XmlNode node in xmldoc.SelectNodes("//atom:entry[@type='application']/atom:keywords/atom:keywordId", nsmgr))
|
|
||||||
appCategories.Add(node.InnerText);
|
|
||||||
|
|
||||||
// get the list of all categories defined in the feed
|
|
||||||
// and filter them
|
|
||||||
List<GalleryCategory> categories = new List<GalleryCategory>();
|
|
||||||
foreach (XmlNode node in xmldoc.SelectNodes("/atom:feed/atom:keywords/atom:keyword", nsmgr))
|
|
||||||
{
|
|
||||||
string id = node.Attributes["id"].Value;
|
|
||||||
string name = node.InnerText;
|
|
||||||
if(appCategories.Contains(id))
|
|
||||||
categories.Add(new GalleryCategory { Id = id, Name = name });
|
|
||||||
}
|
|
||||||
|
|
||||||
return categories;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<GalleryApplication> GetApplications(string categoryName)
|
|
||||||
{
|
|
||||||
XmlDocument xmldoc = GetServiceXmlFeed();
|
|
||||||
//
|
|
||||||
if (xmldoc == null)
|
|
||||||
return null;
|
|
||||||
//
|
|
||||||
XmlNamespaceManager nsmgr = GetXmlNsManager(xmldoc.NameTable);
|
|
||||||
//
|
|
||||||
string xQuery = String.IsNullOrEmpty(categoryName) ? "//atom:entry[@type='application']"
|
|
||||||
: String.Format("//atom:entry[@type='application' and atom:keywords[atom:keywordId='{0}']]", categoryName);
|
|
||||||
//
|
|
||||||
List<GalleryApplication> appList = new List<GalleryApplication>();
|
|
||||||
//
|
|
||||||
foreach (XmlNode node in xmldoc.SelectNodes(xQuery, nsmgr))
|
|
||||||
{
|
|
||||||
appList.Add(DeserializeGalleryApplication(node, nsmgr));
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort apps alphabetically
|
|
||||||
appList.Sort( (a,b) => { return String.Compare(a.Title, b.Title, true); });
|
|
||||||
|
|
||||||
//
|
|
||||||
return appList;
|
|
||||||
}
|
|
||||||
|
|
||||||
public GalleryApplication GetApplicationByProductId(string productId)
|
|
||||||
{
|
|
||||||
XmlDocument xmldoc = GetServiceXmlFeed();
|
|
||||||
//
|
|
||||||
if (xmldoc == null)
|
|
||||||
return null;
|
|
||||||
//
|
|
||||||
XmlNamespaceManager nsmgr = GetXmlNsManager(xmldoc.NameTable);
|
|
||||||
//
|
|
||||||
string xQuery = String.Format("//atom:entry[@type='application' and atom:productId='{0}']", productId);
|
|
||||||
//
|
|
||||||
XmlNode node = xmldoc.SelectSingleNode(xQuery, nsmgr);
|
|
||||||
//
|
|
||||||
GalleryApplication app = DeserializeGalleryApplication(node, nsmgr);
|
|
||||||
//
|
|
||||||
return app;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetApplicationPackagePath(string productId)
|
|
||||||
{
|
|
||||||
return GetApplicationPackagePath(GetApplicationByProductId(productId));
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetApplicationPackagePath(GalleryApplication app)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
string appPackagePath = null;
|
|
||||||
//
|
|
||||||
if (app != null)
|
|
||||||
{
|
|
||||||
InstallerFile installerFile = null;
|
|
||||||
// Acquire root installer item
|
|
||||||
#region Atom Feed Version 0.2
|
|
||||||
if (app.InstallerItems.Count > 0)
|
|
||||||
{
|
|
||||||
InstallerItem installerItem_0 = app.InstallerItems[0];
|
|
||||||
if (installerItem_0 == null)
|
|
||||||
{
|
|
||||||
Log.WriteWarning(WEB_PI_APP_PACK_ROOT_INSTALLER_ITEM_MISSING, app.Title);
|
|
||||||
return appPackagePath;
|
|
||||||
}
|
|
||||||
// Ensure web app package can be reached
|
|
||||||
installerFile = installerItem_0.InstallerFile;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Atom Feed Version 2.0.1.0
|
|
||||||
else if (app.Installers.Count > 0)
|
|
||||||
{
|
|
||||||
Installer installerItem_0 = app.Installers[0];
|
|
||||||
if (installerItem_0 == null)
|
|
||||||
{
|
|
||||||
Log.WriteWarning(WEB_PI_APP_PACK_ROOT_INSTALLER_ITEM_MISSING, app.Title);
|
|
||||||
return appPackagePath;
|
|
||||||
}
|
|
||||||
// Ensure web app package can be reached
|
|
||||||
installerFile = installerItem_0.InstallerFile;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
if (installerFile == null || String.IsNullOrEmpty(installerFile.InstallerUrl))
|
|
||||||
{
|
|
||||||
Log.WriteWarning(WEB_PI_APP_PACK_DISPLAY_URL_MISSING, app.Title);
|
|
||||||
return appPackagePath;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
Log.WriteInfo("Web App Download URL: {0}", installerFile.InstallerUrl);
|
|
||||||
// Trying to match the original file name
|
|
||||||
HttpWebRequest webReq = (HttpWebRequest)HttpWebRequest.Create(installerFile.InstallerUrl);
|
|
||||||
{
|
|
||||||
//
|
|
||||||
Regex regex = new Regex("filename=\"(?<packageName>.{0,})\"");
|
|
||||||
string packageName = null;
|
|
||||||
//
|
|
||||||
webReq.UserAgent = WEB_PI_USER_AGENT_HEADER;
|
|
||||||
//
|
|
||||||
using (HttpWebResponse webResp = (HttpWebResponse)webReq.GetResponse())
|
|
||||||
{
|
|
||||||
string httpHeader = webResp.Headers["Content-Disposition"];
|
|
||||||
//
|
|
||||||
if (!String.IsNullOrEmpty(httpHeader))
|
|
||||||
{
|
|
||||||
string fileName = Array.Find<string>(httpHeader.Split(';'),
|
|
||||||
x => x.Trim().StartsWith("filename="));
|
|
||||||
//
|
|
||||||
Match match = regex.Match(fileName);
|
|
||||||
// Match has been acquired
|
|
||||||
if (match != null && match.Success)
|
|
||||||
{
|
|
||||||
packageName = match.Groups["packageName"].Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Download URL points to the download package directly
|
|
||||||
if (String.IsNullOrEmpty(packageName))
|
|
||||||
{
|
|
||||||
packageName = Path.GetFileName(installerFile.InstallerUrl);
|
|
||||||
}
|
|
||||||
//
|
|
||||||
if (HttpContext.Current != null)
|
|
||||||
{
|
|
||||||
appPackagePath = HttpContext.Current.Server.MapPath(String.Format("~/App_Cache/{0}", packageName));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
string assemblyPath = Path.GetDirectoryName(this.GetType().Assembly.Location);
|
|
||||||
appPackagePath = Path.Combine(assemblyPath, String.Format(@"App_Cache\{0}", packageName));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//
|
|
||||||
return appPackagePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<DeploymentParameter> GetApplicationParameters(string productId)
|
|
||||||
{
|
|
||||||
string packageFile = GetApplicationPackagePath(productId);
|
|
||||||
//
|
|
||||||
if (String.IsNullOrEmpty(packageFile))
|
|
||||||
return null;
|
|
||||||
//
|
|
||||||
List<DeploymentParameter> appParams = new List<DeploymentParameter>();
|
|
||||||
//
|
|
||||||
DeploymentObject iisApplication = null;
|
|
||||||
//
|
|
||||||
try
|
|
||||||
{
|
|
||||||
iisApplication = DeploymentManager.CreateObject(DeploymentWellKnownProvider.Package, packageFile);
|
|
||||||
//
|
|
||||||
foreach (DeploymentSyncParameter parameter in iisApplication.SyncParameters)
|
|
||||||
{
|
|
||||||
DeploymentParameter p = new DeploymentParameter
|
|
||||||
{
|
|
||||||
Name = parameter.Name,
|
|
||||||
FriendlyName = !String.IsNullOrEmpty(parameter.FriendlyName) ? parameter.FriendlyName : parameter.Name,
|
|
||||||
Value = parameter.Value,
|
|
||||||
DefaultValue = parameter.DefaultValue,
|
|
||||||
Description = parameter.Description,
|
|
||||||
ValidationKind = (DeploymentParameterValidationKind)parameter.Validation.Kind,
|
|
||||||
ValidationString = parameter.Validation.ValidationString,
|
|
||||||
WellKnownTags = (DeploymentParameterWellKnownTag)parameter.WellKnownTags
|
|
||||||
};
|
|
||||||
|
|
||||||
// add to the list
|
|
||||||
appParams.Add(p);
|
|
||||||
|
|
||||||
// fix tags for parameters with hard-coded names
|
|
||||||
if(wellKnownParameters.ContainsKey(p.Name))
|
|
||||||
p.WellKnownTags |= wellKnownParameters[p.Name];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
// Log an error
|
|
||||||
Log.WriteError(
|
|
||||||
String.Format("Could not read deployment parameters from '{0}' package.", packageFile), ex);
|
|
||||||
//
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (iisApplication != null)
|
|
||||||
iisApplication.Dispose();
|
|
||||||
}
|
|
||||||
//
|
|
||||||
return appParams;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string InstallApplication(string productId, List<DeploymentParameter> updatedParameters)
|
|
||||||
{
|
|
||||||
string packageFile = GetApplicationPackagePath(productId);
|
|
||||||
string applicationPath = null;
|
|
||||||
|
|
||||||
if (String.IsNullOrEmpty(packageFile))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
Log.WriteInfo("WebApp Package Path: {0}", packageFile);
|
|
||||||
|
|
||||||
if (!File.Exists(packageFile))
|
|
||||||
throw new Exception(GalleryErrors.PackageFileNotFound);
|
|
||||||
|
|
||||||
// Setup source deployment options
|
|
||||||
DeploymentBaseOptions sourceOptions = new DeploymentBaseOptions();
|
|
||||||
|
|
||||||
// Add tracing capabilities
|
|
||||||
sourceOptions.Trace += new EventHandler<DeploymentTraceEventArgs>(sourceOptions_Trace);
|
|
||||||
sourceOptions.TraceLevel = TraceLevel.Verbose;
|
|
||||||
|
|
||||||
// Setup deployment provider
|
|
||||||
DeploymentProviderOptions providerOptions = new DeploymentProviderOptions(DeploymentWellKnownProvider.Package);
|
|
||||||
|
|
||||||
// Set the package path location
|
|
||||||
providerOptions.Path = packageFile;
|
|
||||||
|
|
||||||
// Prepare the package deployment procedure
|
|
||||||
using (DeploymentObject iisApplication = DeploymentManager.CreateObject(providerOptions, sourceOptions))
|
|
||||||
{
|
|
||||||
// Setup destination deployment options
|
|
||||||
DeploymentBaseOptions destinationOptions = new DeploymentBaseOptions();
|
|
||||||
// Add tracing capabilities
|
|
||||||
destinationOptions.Trace += new EventHandler<DeploymentTraceEventArgs>(sourceOptions_Trace);
|
|
||||||
destinationOptions.TraceLevel = TraceLevel.Verbose;
|
|
||||||
|
|
||||||
// MSDEPLOY TEAM COMMENTS: For each parameter that was specified in the UI, set its value
|
|
||||||
DeploymentParameterWellKnownTag databaseEngine = DeploymentParameterWellKnownTag.None;
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
while(i < iisApplication.SyncParameters.Count)
|
|
||||||
{
|
|
||||||
// try to find parameter in updated parameters
|
|
||||||
string name = iisApplication.SyncParameters[i].Name;
|
|
||||||
DeploymentParameter updatedParameter = updatedParameters.Find( p => { return String.Compare(p.Name, name) == 0; });
|
|
||||||
|
|
||||||
if(updatedParameter != null)
|
|
||||||
{
|
|
||||||
// parameter found
|
|
||||||
// update its value
|
|
||||||
iisApplication.SyncParameters[i].Value = updatedParameter.Value;
|
|
||||||
i++; // advance to the next parameter
|
|
||||||
|
|
||||||
// check for selected database engine
|
|
||||||
if ((updatedParameter.WellKnownTags & DeploymentParameterWellKnownTag.MySql) == DeploymentParameterWellKnownTag.MySql)
|
|
||||||
databaseEngine = DeploymentParameterWellKnownTag.MySql;
|
|
||||||
else if ((updatedParameter.WellKnownTags & DeploymentParameterWellKnownTag.Sql) == DeploymentParameterWellKnownTag.Sql)
|
|
||||||
databaseEngine = DeploymentParameterWellKnownTag.Sql;
|
|
||||||
|
|
||||||
// get application path
|
|
||||||
if ((updatedParameter.WellKnownTags & DeploymentParameterWellKnownTag.IisApp) == DeploymentParameterWellKnownTag.IisApp)
|
|
||||||
applicationPath = updatedParameter.Value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// parameter not found
|
|
||||||
// delete it
|
|
||||||
iisApplication.SyncParameters.Remove(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Skip SQL Server database scripts if not SQL Server was selected
|
|
||||||
if (databaseEngine != DeploymentParameterWellKnownTag.Sql)
|
|
||||||
sourceOptions.SkipDirectives.Add(SkipMsSQL);
|
|
||||||
|
|
||||||
// Skip MySQL database scripts if not MySQL was selected
|
|
||||||
if (databaseEngine != DeploymentParameterWellKnownTag.MySql)
|
|
||||||
sourceOptions.SkipDirectives.Add(SkipMySQL);
|
|
||||||
|
|
||||||
// Setup deployment options
|
|
||||||
DeploymentSyncOptions syncOptions = new DeploymentSyncOptions();
|
|
||||||
// Add tracing capabilities
|
|
||||||
//syncOptions..Action += new EventHandler<DeploymentActionEventArgs>(syncOptions_Action);
|
|
||||||
// Issue a syncronization signal between the parties
|
|
||||||
iisApplication.SyncTo(DeploymentWellKnownProvider.Auto, applicationPath, destinationOptions, syncOptions);
|
|
||||||
//
|
|
||||||
Log.WriteInfo("{0}: {1}", "Application path", applicationPath);
|
|
||||||
//
|
|
||||||
}
|
|
||||||
//
|
|
||||||
return applicationPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Helper methods
|
|
||||||
|
|
||||||
private XmlNamespaceManager GetXmlNsManager(XmlNameTable nt)
|
|
||||||
{
|
|
||||||
XmlNamespaceManager nsmgr = new XmlNamespaceManager(nt);
|
|
||||||
nsmgr.AddNamespace("atom", "http://www.w3.org/2005/Atom");
|
|
||||||
//
|
|
||||||
return nsmgr;
|
|
||||||
}
|
|
||||||
|
|
||||||
private GalleryApplication DeserializeGalleryApplication(XmlNode node, XmlNamespaceManager nsmgr)
|
|
||||||
{
|
|
||||||
XmlSerializer xs = new XmlSerializer(typeof(GalleryApplication), AtomFeedNamespace);
|
|
||||||
GalleryApplication app = (GalleryApplication)xs.Deserialize(new XmlNodeReader(node));
|
|
||||||
//
|
|
||||||
app.LastUpdated = XmlToDateTime(GetAtomNodeText(node, nsmgr, "updated"), "yyyy-M-dTHH:mm:ssZ");
|
|
||||||
app.Published = XmlToDateTime(GetAtomNodeText(node, nsmgr, "published"), "yyyy-M-dTHH:mm:ssZ");
|
|
||||||
app.Link = GetAtomNodeAttribute(node, nsmgr, "link", "href");
|
|
||||||
//
|
|
||||||
app.IconUrl = GetAtomNodeText(node, nsmgr, "images/atom:icon");
|
|
||||||
|
|
||||||
// parse well-known dependencies
|
|
||||||
UpdateApplicationWellKnownDependencies(app, app.Dependency);
|
|
||||||
|
|
||||||
//
|
|
||||||
return app;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateApplicationWellKnownDependencies(GalleryApplication app, Dependency dependency)
|
|
||||||
{
|
|
||||||
if (dependency == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (dependency.IdRef != null && wellKnownDependencies.ContainsKey(dependency.IdRef))
|
|
||||||
app.WellKnownDependencies |= wellKnownDependencies[dependency.IdRef];
|
|
||||||
|
|
||||||
// process "And"
|
|
||||||
foreach (Dependency d in dependency.And)
|
|
||||||
UpdateApplicationWellKnownDependencies(app, d);
|
|
||||||
|
|
||||||
// process "Or"
|
|
||||||
foreach (Dependency d in dependency.Or)
|
|
||||||
UpdateApplicationWellKnownDependencies(app, d);
|
|
||||||
|
|
||||||
// process "LogicalAnd"
|
|
||||||
foreach (Dependency d in dependency.LogicalAnd)
|
|
||||||
UpdateApplicationWellKnownDependencies(app, d);
|
|
||||||
|
|
||||||
// process "LogicalOr"
|
|
||||||
foreach (Dependency d in dependency.LogicalOr)
|
|
||||||
UpdateApplicationWellKnownDependencies(app, d);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetAtomNodeText(XmlNode app, XmlNamespaceManager nsmgr, string nodeName)
|
|
||||||
{
|
|
||||||
XmlNode node = app.SelectSingleNode("atom:" + nodeName, nsmgr);
|
|
||||||
if (node == null)
|
|
||||||
return null;
|
|
||||||
return node.InnerText;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetAtomNodeAttribute(XmlNode app, XmlNamespaceManager nsmgr, string nodeName, string attributeName)
|
|
||||||
{
|
|
||||||
XmlNode node = app.SelectSingleNode("atom:" + nodeName, nsmgr);
|
|
||||||
if (node == null)
|
|
||||||
return null;
|
|
||||||
string ret = null;
|
|
||||||
XmlAttribute attribute = node.Attributes[attributeName];
|
|
||||||
if (attribute != null)
|
|
||||||
ret = attribute.Value;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
private DateTime XmlToDateTime(string val, string format)
|
|
||||||
{
|
|
||||||
DateTime ret = DateTime.MinValue;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(val))
|
|
||||||
ret = XmlConvert.ToDateTime(val, format);
|
|
||||||
}
|
|
||||||
catch (Exception) { }
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GetAtomNodeText(XmlNode node)
|
|
||||||
{
|
|
||||||
if (node == null)
|
|
||||||
return null;
|
|
||||||
return node.InnerText;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sourceOptions_Trace(object sender, DeploymentTraceEventArgs e)
|
|
||||||
{
|
|
||||||
Log.WriteInfo(e.Message);
|
|
||||||
Log.WriteInfo("Event Level: " + e.EventLevel);
|
|
||||||
Log.WriteInfo("Event Data: ");
|
|
||||||
//
|
|
||||||
foreach (string keyName in e.EventData.Keys)
|
|
||||||
{
|
|
||||||
Log.WriteInfo(keyName + " => " + e.EventData[keyName]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*private void syncOptions_Action(object sender, DeploymentActionEventArgs e)
|
|
||||||
{
|
|
||||||
Log.WriteInfo(e.Message);
|
|
||||||
Log.WriteInfo("Operation Type: " + e.OperationType);
|
|
||||||
Log.WriteInfo("Event Data: ");
|
|
||||||
//
|
|
||||||
foreach (string keyName in e.EventData.Keys)
|
|
||||||
{
|
|
||||||
Log.WriteInfo(keyName + " => " + e.EventData[keyName]);
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
|
|
||||||
public class DownloadQueueItem
|
|
||||||
{
|
|
||||||
public String ItemKey;
|
|
||||||
public WebClient ConnectionPoint;
|
|
||||||
public DownloadProgressChangedEventArgs Progress;
|
|
||||||
public string DownloadItemURI;
|
|
||||||
public string LocalFilePathToStore;
|
|
||||||
|
|
||||||
public void StartItemDownloadAsync(Object state)
|
|
||||||
{
|
|
||||||
ConnectionPoint.DownloadFileAsync(new Uri(DownloadItemURI), LocalFilePathToStore);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class AppPackagesDownloader
|
|
||||||
{
|
|
||||||
private static List<DownloadQueueItem> downloadQueue;
|
|
||||||
|
|
||||||
static AppPackagesDownloader()
|
|
||||||
{
|
|
||||||
downloadQueue = new List<DownloadQueueItem>();
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
public static bool CheckApplicationPackageHashSum_MD5(string localFilePath, string md5)
|
|
||||||
{
|
|
||||||
if (!File.Exists(localFilePath))
|
|
||||||
return false;
|
|
||||||
//
|
|
||||||
bool md5OK = false;
|
|
||||||
//
|
|
||||||
try
|
|
||||||
{
|
|
||||||
//
|
|
||||||
MD5 md5File = new MD5CryptoServiceProvider();
|
|
||||||
//
|
|
||||||
string fileMd5Sum = BitConverter.ToString(
|
|
||||||
md5File.ComputeHash(File.ReadAllBytes(localFilePath))).Replace("-", String.Empty);
|
|
||||||
//
|
|
||||||
md5OK = String.Equals(md5, fileMd5Sum, StringComparison.InvariantCultureIgnoreCase);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log.WriteError(String.Format("Failed to compute MD5 sum for {0} package.", localFilePath), ex);
|
|
||||||
}
|
|
||||||
//
|
|
||||||
return md5OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
public static bool CheckApplicationPackageHashSum_SHA1(string localFilePath, string sha1)
|
|
||||||
{
|
|
||||||
if (!File.Exists(localFilePath))
|
|
||||||
return false;
|
|
||||||
//
|
|
||||||
bool sha1OK = false;
|
|
||||||
//
|
|
||||||
try
|
|
||||||
{
|
|
||||||
//
|
|
||||||
SHA1 sha1File = new SHA1CryptoServiceProvider();
|
|
||||||
//
|
|
||||||
string fileSha1Sum = BitConverter.ToString(
|
|
||||||
sha1File.ComputeHash(File.ReadAllBytes(localFilePath))).Replace("-", String.Empty);
|
|
||||||
//
|
|
||||||
sha1OK = String.Equals(sha1, fileSha1Sum, StringComparison.InvariantCultureIgnoreCase);
|
|
||||||
//
|
|
||||||
if (!sha1OK)
|
|
||||||
Log.WriteWarning("SHA1-XML FEED: {0}; SHA1-FILE ON DISK: {1};", sha1, fileSha1Sum);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log.WriteError(String.Format("Failed to compute SHA1 sum for {0} package.", localFilePath), ex);
|
|
||||||
}
|
|
||||||
//
|
|
||||||
return sha1OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
public static bool IsApplicationInDownloadQueue(string appName)
|
|
||||||
{
|
|
||||||
bool exists = false;
|
|
||||||
//
|
|
||||||
if (!String.IsNullOrEmpty(appName))
|
|
||||||
{
|
|
||||||
ICollection ic = downloadQueue as ICollection;
|
|
||||||
//
|
|
||||||
lock (ic.SyncRoot)
|
|
||||||
{
|
|
||||||
exists = Array.Exists<DownloadQueueItem>(downloadQueue.ToArray(),
|
|
||||||
x => x.ItemKey == appName.ToLower());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//
|
|
||||||
return exists;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
public static void StartApplicationDownload(string appName, string packageUrl, string localPathToStore)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
bool appInQueue = IsApplicationInDownloadQueue(appName);
|
|
||||||
//
|
|
||||||
if (!appInQueue)
|
|
||||||
{
|
|
||||||
ICollection ic = downloadQueue as ICollection;
|
|
||||||
//
|
|
||||||
lock (ic.SyncRoot)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
DownloadQueueItem qi = new DownloadQueueItem
|
|
||||||
{
|
|
||||||
ItemKey = appName.ToLower(),
|
|
||||||
ConnectionPoint = new WebClient(),
|
|
||||||
Progress = null
|
|
||||||
};
|
|
||||||
//
|
|
||||||
qi.DownloadItemURI = packageUrl;
|
|
||||||
qi.LocalFilePathToStore = localPathToStore;
|
|
||||||
qi.ConnectionPoint.Headers.Add(HttpRequestHeader.UserAgent, WebApplicationGallery.WEB_PI_USER_AGENT_HEADER);
|
|
||||||
qi.ConnectionPoint.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(wc_DownloadFileCompleted);
|
|
||||||
qi.ConnectionPoint.DownloadProgressChanged += new DownloadProgressChangedEventHandler(wc_DownloadProgressChanged);
|
|
||||||
//
|
|
||||||
downloadQueue.Add(qi);
|
|
||||||
// Start async download (10 attempts)
|
|
||||||
int numOfAttempt = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
bool success = ThreadPool.QueueUserWorkItem(
|
|
||||||
new WaitCallback(qi.StartItemDownloadAsync));
|
|
||||||
// Exit the loop if the item successfuly queued
|
|
||||||
if (success)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
numOfAttempt++;
|
|
||||||
// Log an exception
|
|
||||||
Log.WriteError(String.Format("Could not start distibutive download from the following URI: {0}", qi.DownloadItemURI), ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (numOfAttempt <= 10);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int GetApplicationDownloadProgress(string appName)
|
|
||||||
{
|
|
||||||
int appProgress = 0;
|
|
||||||
//
|
|
||||||
bool appInQueue = IsApplicationInDownloadQueue(appName);
|
|
||||||
//
|
|
||||||
if (appInQueue)
|
|
||||||
{
|
|
||||||
ICollection ic = downloadQueue as ICollection;
|
|
||||||
//
|
|
||||||
lock (ic.SyncRoot)
|
|
||||||
{
|
|
||||||
DownloadQueueItem qi = Array.Find<DownloadQueueItem>(downloadQueue.ToArray(),
|
|
||||||
x => x.ItemKey == appName.ToLower());
|
|
||||||
//
|
|
||||||
if (qi.Progress != null)
|
|
||||||
appProgress = qi.Progress.ProgressPercentage;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//
|
|
||||||
return appProgress;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void wc_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
|
|
||||||
{
|
|
||||||
ICollection ic = downloadQueue as ICollection;
|
|
||||||
//
|
|
||||||
lock (ic.SyncRoot)
|
|
||||||
{
|
|
||||||
DownloadQueueItem qi = Array.Find<DownloadQueueItem>(downloadQueue.ToArray(),
|
|
||||||
x => x.ConnectionPoint == sender);
|
|
||||||
//
|
|
||||||
if (e.Error != null)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
if (qi != null)
|
|
||||||
Log.WriteError(String.Format("Could not download app {0}", qi.ItemKey), e.Error);
|
|
||||||
else
|
|
||||||
Log.WriteError(e.Error);
|
|
||||||
}
|
|
||||||
//
|
|
||||||
downloadQueue.Remove(qi);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
|
|
||||||
{
|
|
||||||
ICollection ic = downloadQueue as ICollection;
|
|
||||||
//
|
|
||||||
lock (ic.SyncRoot)
|
|
||||||
{
|
|
||||||
DownloadQueueItem qi = Array.Find<DownloadQueueItem>(downloadQueue.ToArray(),
|
|
||||||
x => x.ConnectionPoint == sender);
|
|
||||||
|
|
||||||
if (qi != null)
|
|
||||||
qi.Progress = e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -93,7 +93,6 @@
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="IIs60.cs" />
|
<Compile Include="IIs60.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="WebApplicationGallery.cs" />
|
|
||||||
<Compile Include="WPIWebApplicationGallery\WPIApplicationGallery.cs" />
|
<Compile Include="WPIWebApplicationGallery\WPIApplicationGallery.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -55,10 +55,8 @@ namespace WebsitePanel.Server.Code
|
||||||
|
|
||||||
#region private fields
|
#region private fields
|
||||||
|
|
||||||
private readonly List<string> _feeds;
|
private List<string> _feeds;
|
||||||
private string _webPIinstallersFolder;
|
private string _webPIinstallersFolder;
|
||||||
//private const string MainWpiFeed = "https://www.microsoft.com/web/webpi/3.0/webproductlist.xml";
|
|
||||||
private const string MainWpiFeed = "https://www.microsoft.com/web/webpi/4.0/WebProductList.xml";
|
|
||||||
private const string IisChoiceProduct = "StaticContent";
|
private const string IisChoiceProduct = "StaticContent";
|
||||||
private const string WebMatrixChoiceProduct = "WebMatrix";
|
private const string WebMatrixChoiceProduct = "WebMatrix";
|
||||||
private ProductManager _productManager;
|
private ProductManager _productManager;
|
||||||
|
@ -79,6 +77,14 @@ namespace WebsitePanel.Server.Code
|
||||||
|
|
||||||
public WpiHelper(IEnumerable<string> feeds)
|
public WpiHelper(IEnumerable<string> feeds)
|
||||||
{
|
{
|
||||||
|
// check feeds is not empty
|
||||||
|
if (null == feeds || !feeds.Any())
|
||||||
|
{
|
||||||
|
throw new Exception("WpiHelper error: empty feed list in constructor");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// by default feeds must contains main MS WPI feed url and Zoo feed url
|
||||||
_feeds = new List<string>();
|
_feeds = new List<string>();
|
||||||
_feeds.AddRange(feeds);
|
_feeds.AddRange(feeds);
|
||||||
|
|
||||||
|
@ -135,7 +141,6 @@ namespace WebsitePanel.Server.Code
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
#region Keywords
|
#region Keywords
|
||||||
public ReadOnlyCollection<Keyword> GetKeywords()
|
public ReadOnlyCollection<Keyword> GetKeywords()
|
||||||
{
|
{
|
||||||
|
@ -158,8 +163,6 @@ namespace WebsitePanel.Server.Code
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region Products
|
#region Products
|
||||||
public List<Product> GetProductsToInstall(string FeedLocation, string keywordId)
|
public List<Product> GetProductsToInstall(string FeedLocation, string keywordId)
|
||||||
{
|
{
|
||||||
|
@ -546,6 +549,7 @@ namespace WebsitePanel.Server.Code
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#endregion Public interface
|
#endregion Public interface
|
||||||
|
|
||||||
|
|
||||||
|
@ -553,12 +557,6 @@ namespace WebsitePanel.Server.Code
|
||||||
|
|
||||||
private void Initialize()
|
private void Initialize()
|
||||||
{
|
{
|
||||||
// insert Main WebPI xml file
|
|
||||||
if (!_feeds.Contains(MainWpiFeed, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
_feeds.Insert(0, MainWpiFeed);
|
|
||||||
}
|
|
||||||
|
|
||||||
// create cache folder if not exists
|
// create cache folder if not exists
|
||||||
//_webPIinstallersFolder = Environment.ExpandEnvironmentVariables(@"%LocalAppData%\Microsoft\Web Platform Installer\installers");
|
//_webPIinstallersFolder = Environment.ExpandEnvironmentVariables(@"%LocalAppData%\Microsoft\Web Platform Installer\installers");
|
||||||
_webPIinstallersFolder = Path.Combine(
|
_webPIinstallersFolder = Path.Combine(
|
||||||
|
@ -570,28 +568,89 @@ namespace WebsitePanel.Server.Code
|
||||||
Directory.CreateDirectory(_webPIinstallersFolder);
|
Directory.CreateDirectory(_webPIinstallersFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
// load feeds
|
LoadFeeds();
|
||||||
_productManager = new ProductManager();
|
|
||||||
|
|
||||||
|
|
||||||
foreach (string feed in _feeds)
|
|
||||||
{
|
|
||||||
WriteLog(string.Format("Loading feed {0}", feed));
|
|
||||||
if (feed.StartsWith("https://www.microsoft.com", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
_productManager.Load(new Uri(feed), true, true, true, _webPIinstallersFolder);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_productManager.LoadExternalFile(new Uri(feed));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
WriteLog(string.Format("{0} products loaded", _productManager.Products.Count));
|
WriteLog(string.Format("{0} products loaded", _productManager.Products.Count));
|
||||||
|
|
||||||
//LogDebugInfo();
|
//LogDebugInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void LoadFeeds()
|
||||||
|
{
|
||||||
|
if (null == _feeds || !_feeds.Any())
|
||||||
|
{
|
||||||
|
throw new Exception("WpiHelper: no feeds provided");
|
||||||
|
}
|
||||||
|
|
||||||
|
_productManager = new ProductManager();
|
||||||
|
|
||||||
|
if (TryLoadFeeds())
|
||||||
|
{
|
||||||
|
// ok, all feeds loaded
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// feed loading failed
|
||||||
|
|
||||||
|
if (_feeds.Count > 1)
|
||||||
|
{
|
||||||
|
// exclude feeds except first (default microsoft feed)
|
||||||
|
_feeds = new List<string> {_feeds[0]};
|
||||||
|
|
||||||
|
// re-create product manager
|
||||||
|
_productManager = new ProductManager();
|
||||||
|
if (TryLoadFeeds())
|
||||||
|
{
|
||||||
|
// loaded first (default) feed only
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception(string.Format("WpiHelper: download all feeds failed"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception(string.Format("WpiHelper: download all feeds failed"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TryLoadFeeds()
|
||||||
|
{
|
||||||
|
string loadingFeed = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
foreach (string feed in _feeds)
|
||||||
|
{
|
||||||
|
loadingFeed = feed;
|
||||||
|
WriteLog(string.Format("Loading feed {0}", feed));
|
||||||
|
if (feed.IndexOf("microsoft.com", StringComparison.OrdinalIgnoreCase) > 0)
|
||||||
|
{
|
||||||
|
// it is internal Microsoft feed
|
||||||
|
_productManager.Load(new Uri(feed), true, true, true, _webPIinstallersFolder);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_productManager.LoadExternalFile(new Uri(feed));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(loadingFeed))
|
||||||
|
{
|
||||||
|
// error occured on loading this feed
|
||||||
|
// log this
|
||||||
|
WriteLog(string.Format("Feed {0} loading error: {1}", loadingFeed, ex));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private Language GetLanguage(string languageId)
|
private Language GetLanguage(string languageId)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(languageId))
|
if (!string.IsNullOrEmpty(languageId))
|
||||||
|
|
|
@ -477,11 +477,7 @@ namespace WebsitePanel.Server
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static string[] FEEDS = new string[]
|
static private string[] _feeds = new string[]{};
|
||||||
{
|
|
||||||
// "https://www.microsoft.com/web/webpi/3.0/WebProductList.xml",
|
|
||||||
// "http://www.helicontech.com/zoo/feed/"
|
|
||||||
};
|
|
||||||
|
|
||||||
[WebMethod]
|
[WebMethod]
|
||||||
public void InitWPIFeeds(string feedUrls)
|
public void InitWPIFeeds(string feedUrls)
|
||||||
|
@ -491,18 +487,18 @@ namespace WebsitePanel.Server
|
||||||
throw new Exception("Empty feed list");
|
throw new Exception("Empty feed list");
|
||||||
}
|
}
|
||||||
|
|
||||||
string[] newFEEDS = feedUrls.Split(';');
|
string[] newFeeds = feedUrls.Split(';');
|
||||||
|
|
||||||
if (newFEEDS.Length == 0)
|
if (newFeeds.Length == 0)
|
||||||
{
|
{
|
||||||
throw new Exception("Empty feed list");
|
throw new Exception("Empty feed list");
|
||||||
}
|
}
|
||||||
if (!ArraysEqual<string>(newFEEDS, FEEDS))
|
if (!ArraysEqual<string>(newFeeds, _feeds))
|
||||||
{
|
{
|
||||||
Log.WriteInfo("InitWPIFeeds - new value: " + feedUrls);
|
Log.WriteInfo("InitWPIFeeds - new value: " + feedUrls);
|
||||||
|
|
||||||
//Feeds settings have been channged
|
//Feeds settings have been channged
|
||||||
FEEDS = newFEEDS;
|
_feeds = newFeeds;
|
||||||
wpi = null;
|
wpi = null;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -604,7 +600,7 @@ namespace WebsitePanel.Server
|
||||||
|
|
||||||
WPIServiceContract client = new WPIServiceContract();
|
WPIServiceContract client = new WPIServiceContract();
|
||||||
|
|
||||||
client.Initialize(FEEDS);
|
client.Initialize(_feeds);
|
||||||
client.BeginInstallation(products);
|
client.BeginInstallation(products);
|
||||||
|
|
||||||
|
|
||||||
|
@ -795,14 +791,14 @@ namespace WebsitePanel.Server
|
||||||
static WpiHelper wpi = null;
|
static WpiHelper wpi = null;
|
||||||
WpiHelper GetWpiFeed()
|
WpiHelper GetWpiFeed()
|
||||||
{
|
{
|
||||||
if (FEEDS.Length == 0)
|
if (_feeds.Length == 0)
|
||||||
{
|
{
|
||||||
throw new Exception("Empty feed list");
|
throw new Exception("Empty feed list");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (null == wpi)
|
if (null == wpi)
|
||||||
{
|
{
|
||||||
wpi = new WpiHelper(FEEDS);
|
wpi = new WpiHelper(_feeds);
|
||||||
}
|
}
|
||||||
return wpi;
|
return wpi;
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,4 +147,10 @@
|
||||||
<data name="locEnableSsl.Text" xml:space="preserve">
|
<data name="locEnableSsl.Text" xml:space="preserve">
|
||||||
<value>Enable SSL:</value>
|
<value>Enable SSL:</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="lclWpiMainFeedUrl.Text" xml:space="preserve">
|
||||||
|
<value>Main feed URL:</value>
|
||||||
|
</data>
|
||||||
|
<data name="lclWpiCustomFeeds.Text" xml:space="preserve">
|
||||||
|
<value>Custom feeds:</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
|
@ -32,6 +32,7 @@ ul.WPIKeywordList {
|
||||||
ul.WPIKeywordList>li {
|
ul.WPIKeywordList>li {
|
||||||
padding: .4em .4em;
|
padding: .4em .4em;
|
||||||
margin-right: .4em;
|
margin-right: .4em;
|
||||||
|
line-height: 2em;
|
||||||
display: inline;
|
display: inline;
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,34 +35,28 @@
|
||||||
<asp:Panel ID="BackupPanel" runat="server" Height="0" style="overflow:hidden;">
|
<asp:Panel ID="BackupPanel" runat="server" Height="0" style="overflow:hidden;">
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="SubHead" style="width:200px;"><asp:Localize ID="Localize1" runat="server" meta:resourcekey="lclBackupFolderPath" /></td>
|
<td class="SubHead" style="width:200px;"><asp:Localize runat="server" meta:resourcekey="lclBackupFolderPath" /></td>
|
||||||
<td><asp:TextBox runat="server" ID="txtBackupsPath" Width="300px" /></td>
|
<td><asp:TextBox runat="server" ID="txtBackupsPath" Width="450px" /></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</asp:Panel>
|
</asp:Panel>
|
||||||
|
|
||||||
<wsp:CollapsiblePanel id="lclWpiSettings" runat="server"
|
<wsp:CollapsiblePanel id="lclWpiSettings" runat="server"
|
||||||
TargetControlID="WpiPanel" meta:resourcekey="lclWpiSettings" Text="WebPlatformInstaller Settings"/>
|
TargetControlID="WpiPanel" meta:resourcekey="lclWpiSettings" Text="Web Platform Installer Settings"/>
|
||||||
<asp:Panel ID="WpiPanel" runat="server" Height="0" style="overflow:hidden;">
|
|
||||||
<asp:CheckBox ID="wpiMicrosoftFeed" runat="server" Text="Yes" Visible="false"/>
|
<asp:Panel ID="WpiPanel" runat="server" Height="0" style="overflow:hidden;">
|
||||||
<asp:CheckBox ID="wpiHeliconTechFeed" runat="server" Text="Yes" Visible="false" />
|
<table>
|
||||||
<%-- <table>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="SubHead" style="width:200px;">Enable Microsoft feed</td>
|
<td class="SubHead" style="width:200px;"><asp:Localize runat="server" meta:resourcekey="lclWpiMainFeedUrl" Text="Main feed URL:" /></td>
|
||||||
<td class="Normal">
|
<td><asp:TextBox runat="server" ID="txtMainFeedUrl" Width="450px" /></td>
|
||||||
<asp:CheckBox ID="wpiMicrosoftFeed" runat="server" Text="Yes" Visible="false"/>
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="SubHead" style="width:200px;">Enable HeliconTech feed</td>
|
<td class="SubHead" style="width:200px; vertical-align: top;"><asp:Localize runat="server" meta:resourcekey="lclWpiCustomFeeds" Text="Custom feeds:" /></td>
|
||||||
<td class="Normal">
|
<td>
|
||||||
<asp:CheckBox ID="wpiHeliconTechFeed" runat="server" Text="Yes" Visible="false" />
|
<uc1:EditFeedsList ID="wpiEditFeedsList" runat="server" DisplayNames="false" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
--%>
|
|
||||||
<uc1:EditFeedsList ID="wpiEditFeedsList" runat="server" DisplayNames="false" />
|
|
||||||
</asp:Panel>
|
</asp:Panel>
|
||||||
</div>
|
</div>
|
||||||
<div class="FormFooter">
|
<div class="FormFooter">
|
||||||
|
|
|
@ -36,7 +36,7 @@ using System.Web.UI;
|
||||||
using System.Web.UI.WebControls;
|
using System.Web.UI.WebControls;
|
||||||
using System.Web.UI.WebControls.WebParts;
|
using System.Web.UI.WebControls.WebParts;
|
||||||
using System.Web.UI.HtmlControls;
|
using System.Web.UI.HtmlControls;
|
||||||
|
using WebsitePanel.EnterpriseServer.Base.Common;
|
||||||
using WSP = WebsitePanel.EnterpriseServer;
|
using WSP = WebsitePanel.EnterpriseServer;
|
||||||
|
|
||||||
namespace WebsitePanel.Portal
|
namespace WebsitePanel.Portal
|
||||||
|
@ -48,12 +48,12 @@ namespace WebsitePanel.Portal
|
||||||
public const string SMTP_USERNAME = "SmtpUsername";
|
public const string SMTP_USERNAME = "SmtpUsername";
|
||||||
public const string SMTP_PASSWORD = "SmtpPassword";
|
public const string SMTP_PASSWORD = "SmtpPassword";
|
||||||
public const string SMTP_ENABLE_SSL = "SmtpEnableSsl";
|
public const string SMTP_ENABLE_SSL = "SmtpEnableSsl";
|
||||||
|
|
||||||
public const string BACKUPS_PATH = "BackupsPath";
|
public const string BACKUPS_PATH = "BackupsPath";
|
||||||
|
|
||||||
public const string FEED_ULS = "FeedUrls";
|
/*
|
||||||
public const string FEED_ENABLE_MICROSOFT = "FeedEnableMicrosoft";
|
public const string FEED_ENABLE_MICROSOFT = "FeedEnableMicrosoft";
|
||||||
public const string FEED_ENABLE_HELICON = "FeedEnableHelicon";
|
public const string FEED_ENABLE_HELICON = "FeedEnableHelicon";
|
||||||
|
*/
|
||||||
|
|
||||||
protected void Page_Load(object sender, EventArgs e)
|
protected void Page_Load(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
|
@ -95,20 +95,31 @@ namespace WebsitePanel.Portal
|
||||||
|
|
||||||
|
|
||||||
// WPI
|
// WPI
|
||||||
settings = ES.Services.System.GetSystemSettings(
|
settings = ES.Services.System.GetSystemSettings(WSP.SystemSettings.WPI_SETTINGS);
|
||||||
WSP.SystemSettings.WPI_SETTINGS);
|
|
||||||
|
|
||||||
|
/*
|
||||||
if (settings != null)
|
if (settings != null)
|
||||||
{
|
{
|
||||||
wpiMicrosoftFeed.Checked = Utils.ParseBool(settings[FEED_ENABLE_MICROSOFT],true);
|
wpiMicrosoftFeed.Checked = Utils.ParseBool(settings[FEED_ENABLE_MICROSOFT],true);
|
||||||
wpiHeliconTechFeed.Checked = Utils.ParseBool(settings[FEED_ENABLE_HELICON],true);
|
wpiHeliconTechFeed.Checked = Utils.ParseBool(settings[FEED_ENABLE_HELICON],true);
|
||||||
wpiEditFeedsList.Value = settings[FEED_ULS];
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
wpiMicrosoftFeed.Checked = true;
|
wpiMicrosoftFeed.Checked = true;
|
||||||
wpiHeliconTechFeed.Checked = true;
|
wpiHeliconTechFeed.Checked = true;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (null != settings)
|
||||||
|
{
|
||||||
|
wpiEditFeedsList.Value = settings[WSP.SystemSettings.FEED_ULS_KEY];
|
||||||
|
|
||||||
|
string mainFeedUrl = settings[WSP.SystemSettings.WPI_MAIN_FEED_KEY];
|
||||||
|
if (string.IsNullOrEmpty(mainFeedUrl))
|
||||||
|
{
|
||||||
|
mainFeedUrl = WebPlatformInstaller.MAIN_FEED_URL;
|
||||||
|
}
|
||||||
|
txtMainFeedUrl.Text = mainFeedUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -152,13 +163,21 @@ namespace WebsitePanel.Portal
|
||||||
|
|
||||||
|
|
||||||
// WPI
|
// WPI
|
||||||
settings[FEED_ULS] = wpiEditFeedsList.Value;
|
/*
|
||||||
settings[FEED_ENABLE_MICROSOFT] = wpiMicrosoftFeed.Checked.ToString();
|
settings[FEED_ENABLE_MICROSOFT] = wpiMicrosoftFeed.Checked.ToString();
|
||||||
settings[FEED_ENABLE_HELICON] = wpiHeliconTechFeed.Checked.ToString();
|
settings[FEED_ENABLE_HELICON] = wpiHeliconTechFeed.Checked.ToString();
|
||||||
|
*/
|
||||||
|
|
||||||
|
settings[WSP.SystemSettings.FEED_ULS_KEY] = wpiEditFeedsList.Value;
|
||||||
|
string mainFeedUrl = txtMainFeedUrl.Text;
|
||||||
|
if (string.IsNullOrEmpty(mainFeedUrl))
|
||||||
|
{
|
||||||
|
mainFeedUrl = WebPlatformInstaller.MAIN_FEED_URL;
|
||||||
|
}
|
||||||
|
settings[WSP.SystemSettings.WPI_MAIN_FEED_KEY] = mainFeedUrl;
|
||||||
|
|
||||||
|
|
||||||
result = ES.Services.System.SetSystemSettings(
|
result = ES.Services.System.SetSystemSettings(WSP.SystemSettings.WPI_SETTINGS, settings);
|
||||||
WSP.SystemSettings.WPI_SETTINGS, settings);
|
|
||||||
|
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -130,15 +130,6 @@ namespace WebsitePanel.Portal {
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
protected global::System.Web.UI.WebControls.Panel BackupPanel;
|
protected global::System.Web.UI.WebControls.Panel BackupPanel;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Localize1 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.Localize Localize1;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// txtBackupsPath control.
|
/// txtBackupsPath control.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -167,22 +158,13 @@ namespace WebsitePanel.Portal {
|
||||||
protected global::System.Web.UI.WebControls.Panel WpiPanel;
|
protected global::System.Web.UI.WebControls.Panel WpiPanel;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// wpiMicrosoftFeed control.
|
/// txtMainFeedUrl control.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Auto-generated field.
|
/// Auto-generated field.
|
||||||
/// To modify move field declaration from designer file to code-behind file.
|
/// To modify move field declaration from designer file to code-behind file.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
protected global::System.Web.UI.WebControls.CheckBox wpiMicrosoftFeed;
|
protected global::System.Web.UI.WebControls.TextBox txtMainFeedUrl;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// wpiHeliconTechFeed 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 wpiHeliconTechFeed;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// wpiEditFeedsList control.
|
/// wpiEditFeedsList control.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue