Ability to change main WPI (Microsoft) feed url in System Settings.

This commit is contained in:
ruslanht 2013-01-30 17:33:37 +02:00
parent 815519b650
commit 54c8438ece
14 changed files with 122 additions and 1041 deletions

View file

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

View file

@ -42,6 +42,10 @@ namespace WebsitePanel.EnterpriseServer
public const string BACKUP_SETTINGS = "BackupSettings";
public const string SETUP_SETTINGS = "SetupSettings";
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[][] {} };

View file

@ -74,6 +74,7 @@
<SubType>Code</SubType>
</Compile>
<Compile Include="Common\MailTemplate.cs" />
<Compile Include="Common\WebPlatformInstaller.cs" />
<Compile Include="DatabaseServers\DatabaseBrowserConfiguration.cs" />
<Compile Include="Ecommerce\BillingCycle.cs" />
<Compile Include="Ecommerce\Category.cs" />

View file

@ -29,15 +29,14 @@
using System;
using System.Collections.Generic;
using System.Threading;
using WebsitePanel.Providers.Web;
using WebsitePanel.EnterpriseServer.Base.Common;
using WebsitePanel.Providers.Web;
using WebsitePanel.Providers.ResultObjects;
using WebsitePanel.Providers.Database;
using WebsitePanel.Providers.WebAppGallery;
using System.Collections.Specialized;
using System.Reflection;
using WebsitePanel.Providers.Common;
using System.Diagnostics;
using System.IO;
namespace WebsitePanel.EnterpriseServer
{
@ -72,28 +71,33 @@ namespace WebsitePanel.EnterpriseServer
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))
{
arFeeds.Add(esServers.HELICON_WPI_FEED);
}
// Zoo Feed
feeds.Add(WebPlatformInstaller.ZOO_FEED);
string additionalFeeds = serviceSettings["FeedUrls"];
// additional feeds
string additionalFeeds = wpiSettings[SystemSettings.FEED_ULS_KEY];
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)
{
string[] feeds = getFeedsFromSettingsByServiceId(serviceId);

View file

@ -35,6 +35,7 @@ using System.Collections.Generic;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.ComponentModel;
using WebsitePanel.EnterpriseServer.Base.Common;
using WebsitePanel.Providers.Common;
using Microsoft.Web.Services3;
@ -54,8 +55,10 @@ namespace WebsitePanel.EnterpriseServer
[ToolboxItem(false)]
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";
*/
#region Servers
[WebMethod]
@ -696,25 +699,28 @@ namespace WebsitePanel.EnterpriseServer
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))
{
arFeeds.Add( HELICON_WPI_FEED );
}
string additionalFeeds = wpiSettings["FeedUrls"];
// Zoo Feed
feeds.Add(WebPlatformInstaller.ZOO_FEED);
// additional feeds
string additionalFeeds = wpiSettings[SystemSettings.FEED_ULS_KEY];
if (!string.IsNullOrEmpty(additionalFeeds))
{
arFeeds.AddRange(additionalFeeds.Split(';'));
feeds.AddRange(additionalFeeds.Split(';'));
}
OperatingSystemController.InitWPIFeeds(serverId, string.Join(";", arFeeds));
OperatingSystemController.InitWPIFeeds(serverId, string.Join(";", feeds));
}

View file

@ -279,7 +279,8 @@ namespace WebsitePanel.Providers.Web
get { return FileUtils.EvaluateSystemVariables(ProviderSettings["ProtectedFoldersFile"]); }
}
protected string GalleryXmlFeedUrl
/*
protected string GalleryXmlFeedUrl
{
get
{
@ -289,6 +290,7 @@ namespace WebsitePanel.Providers.Web
return ret;
}
}
*/
#endregion
private WmiHelper wmi = null;

View file

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

View file

@ -93,7 +93,6 @@
</Compile>
<Compile Include="IIs60.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="WebApplicationGallery.cs" />
<Compile Include="WPIWebApplicationGallery\WPIApplicationGallery.cs" />
</ItemGroup>
<ItemGroup>

View file

@ -57,8 +57,6 @@ namespace WebsitePanel.Server.Code
private readonly List<string> _feeds;
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 WebMatrixChoiceProduct = "WebMatrix";
private ProductManager _productManager;
@ -79,6 +77,14 @@ namespace WebsitePanel.Server.Code
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.AddRange(feeds);
@ -135,7 +141,6 @@ namespace WebsitePanel.Server.Code
}
#endregion
#region Keywords
public ReadOnlyCollection<Keyword> GetKeywords()
{
@ -158,8 +163,6 @@ namespace WebsitePanel.Server.Code
}
#endregion
#region Products
public List<Product> GetProductsToInstall(string FeedLocation, string keywordId)
{
@ -546,6 +549,7 @@ namespace WebsitePanel.Server.Code
}
#endregion
#endregion Public interface
@ -553,12 +557,6 @@ namespace WebsitePanel.Server.Code
private void Initialize()
{
// insert Main WebPI xml file
if (!_feeds.Contains(MainWpiFeed, StringComparer.OrdinalIgnoreCase))
{
_feeds.Insert(0, MainWpiFeed);
}
// create cache folder if not exists
//_webPIinstallersFolder = Environment.ExpandEnvironmentVariables(@"%LocalAppData%\Microsoft\Web Platform Installer\installers");
_webPIinstallersFolder = Path.Combine(

View file

@ -477,11 +477,7 @@ namespace WebsitePanel.Server
}
static string[] FEEDS = new string[]
{
// "https://www.microsoft.com/web/webpi/3.0/WebProductList.xml",
// "http://www.helicontech.com/zoo/feed/"
};
static private string[] _feeds = new string[]{};
[WebMethod]
public void InitWPIFeeds(string feedUrls)
@ -491,18 +487,18 @@ namespace WebsitePanel.Server
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");
}
if (!ArraysEqual<string>(newFEEDS, FEEDS))
if (!ArraysEqual<string>(newFeeds, _feeds))
{
Log.WriteInfo("InitWPIFeeds - new value: " + feedUrls);
//Feeds settings have been channged
FEEDS = newFEEDS;
_feeds = newFeeds;
wpi = null;
}
@ -604,7 +600,7 @@ namespace WebsitePanel.Server
WPIServiceContract client = new WPIServiceContract();
client.Initialize(FEEDS);
client.Initialize(_feeds);
client.BeginInstallation(products);
@ -795,14 +791,14 @@ namespace WebsitePanel.Server
static WpiHelper wpi = null;
WpiHelper GetWpiFeed()
{
if (FEEDS.Length == 0)
if (_feeds.Length == 0)
{
throw new Exception("Empty feed list");
}
if (null == wpi)
{
wpi = new WpiHelper(FEEDS);
wpi = new WpiHelper(_feeds);
}
return wpi;
}

View file

@ -147,4 +147,10 @@
<data name="locEnableSsl.Text" xml:space="preserve">
<value>Enable SSL:</value>
</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>

View file

@ -35,34 +35,28 @@
<asp:Panel ID="BackupPanel" runat="server" Height="0" style="overflow:hidden;">
<table>
<tr>
<td class="SubHead" style="width:200px;"><asp:Localize ID="Localize1" runat="server" meta:resourcekey="lclBackupFolderPath" /></td>
<td><asp:TextBox runat="server" ID="txtBackupsPath" Width="300px" /></td>
<td class="SubHead" style="width:200px;"><asp:Localize runat="server" meta:resourcekey="lclBackupFolderPath" /></td>
<td><asp:TextBox runat="server" ID="txtBackupsPath" Width="450px" /></td>
</tr>
</table>
</asp:Panel>
<wsp:CollapsiblePanel id="lclWpiSettings" runat="server"
TargetControlID="WpiPanel" meta:resourcekey="lclWpiSettings" Text="WebPlatformInstaller Settings"/>
<asp:Panel ID="WpiPanel" runat="server" Height="0" style="overflow:hidden;">
<asp:CheckBox ID="wpiMicrosoftFeed" runat="server" Text="Yes" Visible="false"/>
<asp:CheckBox ID="wpiHeliconTechFeed" runat="server" Text="Yes" Visible="false" />
<%-- <table>
TargetControlID="WpiPanel" meta:resourcekey="lclWpiSettings" Text="Web Platform Installer Settings"/>
<asp:Panel ID="WpiPanel" runat="server" Height="0" style="overflow:hidden;">
<table>
<tr>
<td class="SubHead" style="width:200px;">Enable Microsoft feed</td>
<td class="Normal">
<asp:CheckBox ID="wpiMicrosoftFeed" runat="server" Text="Yes" Visible="false"/>
</td>
<td class="SubHead" style="width:200px;"><asp:Localize runat="server" meta:resourcekey="lclWpiMainFeedUrl" Text="Main feed URL:" /></td>
<td><asp:TextBox runat="server" ID="txtMainFeedUrl" Width="450px" /></td>
</tr>
<tr>
<td class="SubHead" style="width:200px;">Enable HeliconTech feed</td>
<td class="Normal">
<asp:CheckBox ID="wpiHeliconTechFeed" runat="server" Text="Yes" Visible="false" />
<td class="SubHead" style="width:200px; vertical-align: top;"><asp:Localize runat="server" meta:resourcekey="lclWpiCustomFeeds" Text="Custom feeds:" /></td>
<td>
<uc1:EditFeedsList ID="wpiEditFeedsList" runat="server" DisplayNames="false" />
</td>
</tr>
</table>
--%>
<uc1:EditFeedsList ID="wpiEditFeedsList" runat="server" DisplayNames="false" />
</table>
</asp:Panel>
</div>
<div class="FormFooter">

View file

@ -36,7 +36,7 @@ using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using WebsitePanel.EnterpriseServer.Base.Common;
using WSP = WebsitePanel.EnterpriseServer;
namespace WebsitePanel.Portal
@ -48,12 +48,12 @@ namespace WebsitePanel.Portal
public const string SMTP_USERNAME = "SmtpUsername";
public const string SMTP_PASSWORD = "SmtpPassword";
public const string SMTP_ENABLE_SSL = "SmtpEnableSsl";
public const string BACKUPS_PATH = "BackupsPath";
public const string FEED_ULS = "FeedUrls";
/*
public const string FEED_ENABLE_MICROSOFT = "FeedEnableMicrosoft";
public const string FEED_ENABLE_HELICON = "FeedEnableHelicon";
*/
protected void Page_Load(object sender, EventArgs e)
{
@ -95,20 +95,31 @@ namespace WebsitePanel.Portal
// WPI
settings = ES.Services.System.GetSystemSettings(
WSP.SystemSettings.WPI_SETTINGS);
settings = ES.Services.System.GetSystemSettings(WSP.SystemSettings.WPI_SETTINGS);
/*
if (settings != null)
{
wpiMicrosoftFeed.Checked = Utils.ParseBool(settings[FEED_ENABLE_MICROSOFT],true);
wpiHeliconTechFeed.Checked = Utils.ParseBool(settings[FEED_ENABLE_HELICON],true);
wpiEditFeedsList.Value = settings[FEED_ULS];
}
else
{
wpiMicrosoftFeed.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
settings[FEED_ULS] = wpiEditFeedsList.Value;
/*
settings[FEED_ENABLE_MICROSOFT] = wpiMicrosoftFeed.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(
WSP.SystemSettings.WPI_SETTINGS, settings);
result = ES.Services.System.SetSystemSettings(WSP.SystemSettings.WPI_SETTINGS, settings);
if (result < 0)
{

View file

@ -130,15 +130,6 @@ namespace WebsitePanel.Portal {
/// </remarks>
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>
/// txtBackupsPath control.
/// </summary>
@ -167,22 +158,13 @@ namespace WebsitePanel.Portal {
protected global::System.Web.UI.WebControls.Panel WpiPanel;
/// <summary>
/// wpiMicrosoftFeed control.
/// txtMainFeedUrl 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 wpiMicrosoftFeed;
/// <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;
protected global::System.Web.UI.WebControls.TextBox txtMainFeedUrl;
/// <summary>
/// wpiEditFeedsList control.