Includes: - complete re-write of Web Application Gallery - Addition of Web PI Installer in Server module
4037 lines
145 KiB
C#
4037 lines
145 KiB
C#
// 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;
|
|
using System.Management;
|
|
using System.DirectoryServices;
|
|
using System.DirectoryServices.ActiveDirectory;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using System.IO;
|
|
using WebsitePanel.Providers.HostedSolution;
|
|
using WebsitePanel.Providers.OS;
|
|
using WebsitePanel.Providers.ResultObjects;
|
|
using WebsitePanel.Providers.Utils;
|
|
using WebsitePanel.Providers.Web.Handlers;
|
|
using WebsitePanel.Providers.Web.HttpRedirect;
|
|
using WebsitePanel.Providers.Web.Iis.Authentication;
|
|
using WebsitePanel.Providers.Web.Iis.ClassicAsp;
|
|
using WebsitePanel.Providers.Web.Iis.DefaultDocuments;
|
|
using WebsitePanel.Providers.Web.Iis.DirectoryBrowse;
|
|
using WebsitePanel.Providers.Web.Iis.WebObjects;
|
|
using WebsitePanel.Providers.Web.Iis.Extensions;
|
|
using WebsitePanel.Providers.Web.MimeTypes;
|
|
using WebsitePanel.Providers.Web.Iis.Utility;
|
|
using Microsoft.Web.Administration;
|
|
using Microsoft.Web.Management.Server;
|
|
|
|
using WebsitePanel.Providers.Utils.LogParser;
|
|
using Microsoft.Win32;
|
|
using WebsitePanel.Providers.Common;
|
|
using System.Collections.Specialized;
|
|
using WebsitePanel.Providers.Web.WebObjects;
|
|
using WebsitePanel.Providers.Web.Iis.Common;
|
|
using WebsitePanel.Providers.Web.Iis;
|
|
using Ionic.Zip;
|
|
using WebsitePanel.Providers.WebAppGallery;
|
|
using WebsitePanel.Server.Utils;
|
|
using WebsitePanel.Providers.Web.Delegation;
|
|
|
|
namespace WebsitePanel.Providers.Web
|
|
{
|
|
internal abstract class Constants
|
|
{
|
|
public const string CachingSection = "system.webServer/caching";
|
|
public const string DefaultDocumentsSection = "system.webServer/defaultDocument";
|
|
public const string DirectoryBrowseSection = "system.webServer/directoryBrowse";
|
|
public const string FactCgiSection = "system.webServer/fastCgi";
|
|
public const string HandlersSection = "system.webServer/handlers";
|
|
public const string HttpErrorsSection = "system.webServer/httpErrors";
|
|
public const string HttpProtocolSection = "system.webServer/httpProtocol";
|
|
public const string HttpRedirectSection = "system.webServer/httpRedirect";
|
|
public const string AnonymousAuthenticationSection = "system.webServer/security/authentication/anonymousAuthentication";
|
|
public const string BasicAuthenticationSection = "system.webServer/security/authentication/basicAuthentication";
|
|
public const string WindowsAuthenticationSection = "system.webServer/security/authentication/windowsAuthentication";
|
|
public const string StaticContentSection = "system.webServer/staticContent";
|
|
public const string ModulesSection = "system.webServer/modules";
|
|
public const string IsapiCgiRestrictionSection = "system.webServer/security/isapiCgiRestriction";
|
|
|
|
public const string APP_POOL_NAME_FORMAT_STRING = "#SITE-NAME# #IIS7-ASPNET-VERSION# (#PIPELINE-MODE#)";
|
|
|
|
public const string AspNet11Pool = "AspNet11Pool";
|
|
public const string ClassicAspNet20Pool = "ClassicAspNet20Pool";
|
|
public const string IntegratedAspNet20Pool = "IntegratedAspNet20Pool";
|
|
public const string ClassicAspNet40Pool = "ClassicAspNet40Pool";
|
|
public const string IntegratedAspNet40Pool = "IntegratedAspNet40Pool";
|
|
|
|
public const string AspPathSetting = "AspPath";
|
|
public const string AspNet11PathSetting = "AspNet11Path";
|
|
public const string AspNet20PathSetting = "AspNet20Path";
|
|
public const string AspNet20x64PathSetting = "AspNet20x64Path";
|
|
public const string AspNet40PathSetting = "AspNet40Path";
|
|
public const string AspNet40x64PathSetting = "AspNet40x64Path";
|
|
|
|
public const string WEBSITEPANEL_IISMODULES = "WebsitePanel.IIsModules";
|
|
|
|
public const string HeliconApeModule = "Helicon Ape";
|
|
public const string HeliconApeHandlerPath = "*.apehandler";
|
|
|
|
public const string IsapiModule = "IsapiModule";
|
|
public const string FastCgiModule = "FastCgiModule";
|
|
public const string CgiModule = "CgiModule";
|
|
|
|
internal abstract class PhpMode
|
|
{
|
|
public const string FastCGI = "FastCGI";
|
|
public const string CGI = "CGI";
|
|
public const string ISAPI = "ISAPI";
|
|
}
|
|
|
|
internal abstract class HandlerAlias
|
|
{
|
|
public const string CLASSIC_ASP = "ASPClassic (*{0})";
|
|
public const string PHP_FASTCGI = "PHP via FastCGI (*{0})";
|
|
public const string PHP_CGI = "PHP via CGI (*{0})";
|
|
public const string PERL_ISAPI = "Perl via ISAPI (*{0})";
|
|
public const string PHP_ISAPI = "PHP via ISAPI (*{0})";
|
|
public const string COLDFUSION = "ColdFusion (*{0})";
|
|
}
|
|
|
|
public static bool X64Environment
|
|
{
|
|
get { return (IntPtr.Size == 8); }
|
|
}
|
|
}
|
|
|
|
public class WebAppPool
|
|
{
|
|
public static readonly Dictionary<SiteAppPoolMode, string> AspNetVersions = new Dictionary<SiteAppPoolMode, string>
|
|
{
|
|
{ SiteAppPoolMode.dotNetFramework1, "v1.1" },
|
|
{ SiteAppPoolMode.dotNetFramework2, "v2.0" },
|
|
{ SiteAppPoolMode.dotNetFramework4, "v4.0" }
|
|
};
|
|
|
|
public string AspNetInstalled { get; set; }
|
|
public SiteAppPoolMode Mode { get; set; }
|
|
public string Name { get; set; }
|
|
}
|
|
|
|
public class WebAppPoolHelper
|
|
{
|
|
private List<WebAppPool> supportedAppPools;
|
|
|
|
public List<WebAppPool> SupportedAppPools
|
|
{
|
|
get
|
|
{
|
|
return supportedAppPools;
|
|
}
|
|
}
|
|
|
|
public static Dictionary<string, SiteAppPoolMode> SupportedAppPoolModes = new Dictionary<string, SiteAppPoolMode>
|
|
{
|
|
{ "1", SiteAppPoolMode.dotNetFramework1 | SiteAppPoolMode.Classic },
|
|
{ "2", SiteAppPoolMode.dotNetFramework2 | SiteAppPoolMode.Classic },
|
|
{ "2I", SiteAppPoolMode.dotNetFramework2 | SiteAppPoolMode.Integrated },
|
|
{ "4", SiteAppPoolMode.dotNetFramework4 | SiteAppPoolMode.Classic },
|
|
{ "4I", SiteAppPoolMode.dotNetFramework4 | SiteAppPoolMode.Integrated }
|
|
};
|
|
|
|
//
|
|
public WebAppPoolHelper(ServiceProviderSettings s)
|
|
{
|
|
SetupSupportedAppPools(s);
|
|
}
|
|
//
|
|
public SiteAppPoolMode dotNetVersion(SiteAppPoolMode m)
|
|
{
|
|
return m & (SiteAppPoolMode.dotNetFramework1 | SiteAppPoolMode.dotNetFramework2 | SiteAppPoolMode.dotNetFramework4);
|
|
}
|
|
//
|
|
public SiteAppPoolMode pipeline(SiteAppPoolMode m)
|
|
{
|
|
return m & (SiteAppPoolMode.Classic | SiteAppPoolMode.Integrated);
|
|
}
|
|
//
|
|
public SiteAppPoolMode isolation(SiteAppPoolMode m)
|
|
{
|
|
return m & (SiteAppPoolMode.Shared | SiteAppPoolMode.Dedicated);
|
|
}
|
|
//
|
|
public string aspnet_runtime(SiteAppPoolMode m)
|
|
{
|
|
return WebAppPool.AspNetVersions[dotNetVersion(m)];
|
|
}
|
|
//
|
|
public ManagedPipelineMode runtime_pipeline(SiteAppPoolMode m)
|
|
{
|
|
return (pipeline(m) == SiteAppPoolMode.Classic) ? ManagedPipelineMode.Classic : ManagedPipelineMode.Integrated;
|
|
}
|
|
//
|
|
public bool is_shared_pool(string poolName)
|
|
{
|
|
return Array.Exists<WebAppPool>(supportedAppPools.ToArray(),
|
|
x => x.Name.Equals(poolName) && isolation(x.Mode) == SiteAppPoolMode.Shared);
|
|
}
|
|
//
|
|
public WebAppPool match_webapp_pool(WebVirtualDirectory vdir)
|
|
{
|
|
// Detect isolation mode
|
|
SiteAppPoolMode sisMode = is_shared_pool(vdir.ApplicationPool) ?
|
|
SiteAppPoolMode.Shared : SiteAppPoolMode.Dedicated;
|
|
// Match proper app pool
|
|
return Array.Find<WebAppPool>(SupportedAppPools.ToArray(),
|
|
x => x.AspNetInstalled.Equals(vdir.AspNetInstalled) && isolation(x.Mode) == sisMode);
|
|
}
|
|
//
|
|
private void SetupSupportedAppPools(ServiceProviderSettings settings)
|
|
{
|
|
supportedAppPools = new List<WebAppPool>();
|
|
|
|
#region Populate Shared Application Pools
|
|
// ASP.NET 1.1
|
|
if (!String.IsNullOrEmpty(settings[Constants.AspNet11Pool]))
|
|
{
|
|
supportedAppPools.Add(new WebAppPool
|
|
{
|
|
AspNetInstalled = "1",
|
|
Mode = SiteAppPoolMode.dotNetFramework1 | SiteAppPoolMode.Classic | SiteAppPoolMode.Shared,
|
|
Name = settings[Constants.AspNet11Pool].Trim()
|
|
});
|
|
}
|
|
// ASP.NET 2.0 (Classic pipeline)
|
|
if (!String.IsNullOrEmpty(settings[Constants.ClassicAspNet20Pool]))
|
|
{
|
|
supportedAppPools.Add(new WebAppPool
|
|
{
|
|
AspNetInstalled = "2",
|
|
Mode = SiteAppPoolMode.dotNetFramework2 | SiteAppPoolMode.Classic | SiteAppPoolMode.Shared,
|
|
Name = settings[Constants.ClassicAspNet20Pool].Trim()
|
|
});
|
|
}
|
|
// ASP.NET 2.0 (Integrated pipeline)
|
|
if (!String.IsNullOrEmpty(settings[Constants.IntegratedAspNet20Pool]))
|
|
{
|
|
supportedAppPools.Add(new WebAppPool
|
|
{
|
|
AspNetInstalled = "2I",
|
|
Mode = SiteAppPoolMode.dotNetFramework2 | SiteAppPoolMode.Integrated | SiteAppPoolMode.Shared,
|
|
Name = settings[Constants.IntegratedAspNet20Pool].Trim()
|
|
});
|
|
}
|
|
// ASP.NET 4.0 (Classic pipeline)
|
|
if (!String.IsNullOrEmpty(settings[Constants.ClassicAspNet40Pool]))
|
|
{
|
|
supportedAppPools.Add(new WebAppPool
|
|
{
|
|
AspNetInstalled = "4",
|
|
Mode = SiteAppPoolMode.dotNetFramework4 | SiteAppPoolMode.Classic | SiteAppPoolMode.Shared,
|
|
Name = settings[Constants.ClassicAspNet40Pool].Trim()
|
|
});
|
|
}
|
|
// ASP.NET 4.0 (Integrated pipeline)
|
|
if (!String.IsNullOrEmpty(settings[Constants.IntegratedAspNet40Pool]))
|
|
{
|
|
supportedAppPools.Add(new WebAppPool
|
|
{
|
|
AspNetInstalled = "4I",
|
|
Mode = SiteAppPoolMode.dotNetFramework4 | SiteAppPoolMode.Integrated | SiteAppPoolMode.Shared,
|
|
Name = settings[Constants.IntegratedAspNet40Pool].Trim()
|
|
});
|
|
}
|
|
#endregion
|
|
|
|
#region Populate Dedicated Application Pools
|
|
// ASP.NET 1.1
|
|
supportedAppPools.Add(new WebAppPool
|
|
{
|
|
AspNetInstalled = "1",
|
|
Mode = SiteAppPoolMode.dotNetFramework1 | SiteAppPoolMode.Classic | SiteAppPoolMode.Dedicated,
|
|
Name = Constants.APP_POOL_NAME_FORMAT_STRING
|
|
});
|
|
// ASP.NET 2.0 (Classic pipeline)
|
|
supportedAppPools.Add(new WebAppPool
|
|
{
|
|
AspNetInstalled = "2",
|
|
Mode = SiteAppPoolMode.dotNetFramework2 | SiteAppPoolMode.Classic | SiteAppPoolMode.Dedicated,
|
|
Name = Constants.APP_POOL_NAME_FORMAT_STRING
|
|
});
|
|
// ASP.NET 2.0 (Integrated pipeline)
|
|
supportedAppPools.Add(new WebAppPool
|
|
{
|
|
AspNetInstalled = "2I",
|
|
Mode = SiteAppPoolMode.dotNetFramework2 | SiteAppPoolMode.Integrated | SiteAppPoolMode.Dedicated,
|
|
Name = Constants.APP_POOL_NAME_FORMAT_STRING
|
|
});
|
|
// ASP.NET 4.0 (Classic pipeline)
|
|
supportedAppPools.Add(new WebAppPool
|
|
{
|
|
AspNetInstalled = "4",
|
|
Mode = SiteAppPoolMode.dotNetFramework4 | SiteAppPoolMode.Classic | SiteAppPoolMode.Dedicated,
|
|
Name = Constants.APP_POOL_NAME_FORMAT_STRING
|
|
});
|
|
// ASP.NET 4.0 (Integrated pipeline)
|
|
supportedAppPools.Add(new WebAppPool
|
|
{
|
|
AspNetInstalled = "4I",
|
|
Mode = SiteAppPoolMode.dotNetFramework4 | SiteAppPoolMode.Integrated | SiteAppPoolMode.Dedicated,
|
|
Name = Constants.APP_POOL_NAME_FORMAT_STRING
|
|
});
|
|
#endregion
|
|
|
|
// Make some corrections for frameworks with the version number greater or less than 2.0 ...
|
|
|
|
#region No ASP.NET 1.1 has been found - so remove extra pools
|
|
if (String.IsNullOrEmpty(settings[Constants.AspNet11PathSetting]))
|
|
supportedAppPools.RemoveAll(x => dotNetVersion(x.Mode) == SiteAppPoolMode.dotNetFramework1);
|
|
#endregion
|
|
|
|
#region No ASP.NET 4.0 has been found - so remove extra pools
|
|
var aspNet40PathSetting = (Constants.X64Environment)
|
|
? Constants.AspNet40x64PathSetting : Constants.AspNet40PathSetting;
|
|
//
|
|
if (String.IsNullOrEmpty(settings[aspNet40PathSetting]))
|
|
supportedAppPools.RemoveAll(x => dotNetVersion(x.Mode) == SiteAppPoolMode.dotNetFramework4);
|
|
#endregion
|
|
}
|
|
}
|
|
|
|
public class WebManagementServiceSettings
|
|
{
|
|
public string Port { get; set; }
|
|
public string NETBIOS { get; set; }
|
|
public string ServiceUrl { get; set; }
|
|
public int RequiresWindowsCredentials { get; set; }
|
|
}
|
|
|
|
public class IIs70 : IIs60, IWebServer
|
|
{
|
|
private WebObjectsModuleService webObjectsSvc;
|
|
private DirectoryBrowseModuleService dirBrowseSvc;
|
|
private AnonymAuthModuleService anonymAuthSvc;
|
|
private WindowsAuthModuleService winAuthSvc;
|
|
private BasicAuthModuleService basicAuthSvc;
|
|
private DefaultDocsModuleService defaultDocSvc;
|
|
private CustomHttpErrorsModuleService customErrorsSvc;
|
|
private CustomHttpHeadersModuleService customHeadersSvc;
|
|
private ClassicAspModuleService classicAspSvc;
|
|
private MimeTypesModuleService mimeTypesSvc;
|
|
private ExtensionsModuleService extensionsSvc;
|
|
private HandlersModuleService handlersSvc;
|
|
private HttpRedirectModuleService httpRedirectSvc;
|
|
//
|
|
|
|
#region Constants
|
|
|
|
public const string IIS_IUSRS_GROUP = "IIS_IUSRS";
|
|
|
|
//
|
|
public const string FPSE2002_OWSADM_PATH_x86 = @"%CommonProgramFiles%\Microsoft Shared\Web Server Extensions\50\bin\owsadm.exe";
|
|
public const string FPSE2002_OWSADM_PATH_x64 = @"%CommonProgramFiles(x86)%\Microsoft Shared\Web Server Extensions\50\bin\owsadm.exe";
|
|
//
|
|
public const string FRONTPAGE_2002_REGLOC_x86 = @"SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\5.0";
|
|
public const string FRONTPAGE_2002_REGLOC_x64 = @"SOFTWARE\Wow6432Node\Microsoft\Shared Tools\Web Server Extensions\5.0";
|
|
//
|
|
public const string FRONTPAGE_ALLPORTS_REGLOC_x86 = @"SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\All Ports\";
|
|
public const string FRONTPAGE_ALLPORTS_REGLOC_x64 = @"SOFTWARE\Wow6432Node\Microsoft\Shared Tools\Web Server Extensions\All Ports\";
|
|
//
|
|
public const string FRONTPAGE_PORT_REGLOC_x86 = @"SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\Ports\";
|
|
public const string FRONTPAGE_PORT_REGLOC_x64 = @"SOFTWARE\Wow6432Node\Microsoft\Shared Tools\Web Server Extensions\Ports\";
|
|
|
|
private string[] INSTALL_SECTIONS_ALLOWED = new string[] {
|
|
Constants.CachingSection,
|
|
Constants.DefaultDocumentsSection,
|
|
Constants.DirectoryBrowseSection,
|
|
Constants.FactCgiSection,
|
|
Constants.HandlersSection,
|
|
Constants.HttpErrorsSection,
|
|
Constants.HttpProtocolSection,
|
|
Constants.HttpRedirectSection,
|
|
Constants.AnonymousAuthenticationSection,
|
|
Constants.BasicAuthenticationSection,
|
|
Constants.WindowsAuthenticationSection,
|
|
Constants.StaticContentSection
|
|
};
|
|
|
|
#endregion
|
|
|
|
#region Helper Properties
|
|
|
|
protected string FPSE2002_OWSADM_PATH
|
|
{
|
|
get
|
|
{
|
|
if (Constants.X64Environment)
|
|
return FPSE2002_OWSADM_PATH_x64;
|
|
else
|
|
return FPSE2002_OWSADM_PATH_x86;
|
|
}
|
|
}
|
|
|
|
new protected string FRONTPAGE_2002_REGLOC
|
|
{
|
|
get
|
|
{
|
|
if (Constants.X64Environment)
|
|
return FRONTPAGE_2002_REGLOC_x64;
|
|
else
|
|
return FRONTPAGE_2002_REGLOC_x86;
|
|
}
|
|
}
|
|
|
|
new protected string FRONTPAGE_ALLPORTS_REGLOC
|
|
{
|
|
get
|
|
{
|
|
if (Constants.X64Environment)
|
|
return FRONTPAGE_ALLPORTS_REGLOC_x64;
|
|
else
|
|
return FRONTPAGE_ALLPORTS_REGLOC_x86;
|
|
}
|
|
}
|
|
|
|
new protected string FRONTPAGE_PORT_REGLOC
|
|
{
|
|
get
|
|
{
|
|
if (Constants.X64Environment)
|
|
return FRONTPAGE_PORT_REGLOC_x64;
|
|
else
|
|
return FRONTPAGE_PORT_REGLOC_x86;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Provider Properties
|
|
|
|
public bool Enable32BitAppOnWin64
|
|
{
|
|
get { return ProviderSettings["AspNetBitnessMode"] == "32"; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets shared iisAppObject pool name (Classic Managed Pipeline)
|
|
/// </summary>
|
|
public string ClassicAspNet20Pool
|
|
{
|
|
get { return ProviderSettings["ClassicAspNet20Pool"]; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets shared iisAppObject pool name (Integrated Managed Pipeline)
|
|
/// </summary>
|
|
public string IntegratedAspNet20Pool
|
|
{
|
|
get { return ProviderSettings["IntegratedAspNet20Pool"]; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets shared iisAppObject pool name (Classic Managed Pipeline)
|
|
/// </summary>
|
|
public string ClassicAspNet40Pool
|
|
{
|
|
get { return ProviderSettings["ClassicAspNet40Pool"]; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets shared iisAppObject pool name (Integrated Managed Pipeline)
|
|
/// </summary>
|
|
public string IntegratedAspNet40Pool
|
|
{
|
|
get { return ProviderSettings["IntegratedAspNet40Pool"]; }
|
|
}
|
|
|
|
public string PhpMode
|
|
{
|
|
get { return ProviderSettings["PhpMode"]; }
|
|
}
|
|
|
|
public string PhpExecutablePath
|
|
{
|
|
get { return FileUtils.EvaluateSystemVariables(ProviderSettings["PhpPath"]); }
|
|
}
|
|
|
|
public string SecureFoldersModuleAssembly
|
|
{
|
|
get { return ProviderSettings["SecureFoldersModuleAssembly"]; }
|
|
}
|
|
|
|
protected override string ProtectedAccessFile
|
|
{
|
|
get
|
|
{
|
|
return ".htaccess";
|
|
}
|
|
}
|
|
|
|
protected override string ProtectedFoldersFile
|
|
{
|
|
get
|
|
{
|
|
return ".htfolders";
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
public IIs70()
|
|
{
|
|
if (IsIISInstalled())
|
|
{
|
|
// New implementation avoiding locks and other sync issues
|
|
winAuthSvc = new WindowsAuthModuleService();
|
|
anonymAuthSvc = new AnonymAuthModuleService();
|
|
basicAuthSvc = new BasicAuthModuleService();
|
|
defaultDocSvc = new DefaultDocsModuleService();
|
|
classicAspSvc = new ClassicAspModuleService();
|
|
httpRedirectSvc = new HttpRedirectModuleService();
|
|
extensionsSvc = new ExtensionsModuleService();
|
|
customErrorsSvc = new CustomHttpErrorsModuleService();
|
|
customHeadersSvc = new CustomHttpHeadersModuleService();
|
|
webObjectsSvc = new WebObjectsModuleService();
|
|
dirBrowseSvc = new DirectoryBrowseModuleService();
|
|
mimeTypesSvc = new MimeTypesModuleService();
|
|
handlersSvc = new HandlersModuleService();
|
|
}
|
|
}
|
|
|
|
#region Helper methods
|
|
|
|
private void CreateWebSiteAnonymousAccount(WebSite site)
|
|
{
|
|
// anonymous user groups
|
|
List<string> webGroups = new List<string>();
|
|
webGroups.Add(WebGroupName);
|
|
|
|
// create web site anonymous account
|
|
SystemUser user = new SystemUser();
|
|
user.Name = GetNonQualifiedAccountName(site.AnonymousUsername);
|
|
user.FullName = GetNonQualifiedAccountName(site.AnonymousUsername);
|
|
|
|
// Fix. Import web site that runs under NETWORK_SERVICE identity fails.
|
|
// WebsitePanel cannot create anonymous account.
|
|
/*if (!user.Name.Contains(site.Name.Replace(".", "")))
|
|
{
|
|
user.Name = user.FullName = site.Name.Replace(".", "") + "_web";
|
|
}*/
|
|
|
|
//check is user name less than 20 symbols (Windows name length restriction)
|
|
if (user.Name.Length > 20)
|
|
{
|
|
int separatorPlace = user.Name.IndexOf("_");
|
|
user.Name = user.Name.Remove(separatorPlace - (user.Name.Length - 20), user.Name.Length - 20);
|
|
}
|
|
|
|
site.AnonymousUsername = user.Name;
|
|
|
|
user.Description = "WebsitePanel System Account";
|
|
user.MemberOf = webGroups.ToArray();
|
|
|
|
//set new password for created Anonymous Account
|
|
if (String.IsNullOrEmpty(site.AnonymousUserPassword))
|
|
{
|
|
site.AnonymousUserPassword = Guid.NewGuid().ToString();
|
|
}
|
|
|
|
user.Password = site.AnonymousUserPassword;
|
|
user.PasswordCantChange = true;
|
|
user.PasswordNeverExpires = true;
|
|
user.AccountDisabled = false;
|
|
user.System = true;
|
|
// create in the system
|
|
try
|
|
{
|
|
SecurityUtils.CreateUser(user, ServerSettings, UsersOU, GroupsOU);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// the possible reason the account already exists
|
|
// check this
|
|
if (SecurityUtils.UserExists(user.Name, ServerSettings, UsersOU))
|
|
{
|
|
// yes
|
|
// try to give it original name
|
|
for (int i = 2; i < 99; i++)
|
|
{
|
|
string username = user.Name + i.ToString();
|
|
if (!SecurityUtils.UserExists(username, ServerSettings, UsersOU))
|
|
{
|
|
user.Name = username;
|
|
site.AnonymousUsername = username;
|
|
|
|
// try to create again
|
|
SecurityUtils.CreateUser(user, ServerSettings, UsersOU, GroupsOU);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw ex;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void FillVirtualDirectoryFromIISObject(ServerManager srvman, WebVirtualDirectory virtualDir)
|
|
{
|
|
// Set physical path.
|
|
virtualDir.ContentPath = webObjectsSvc.GetPhysicalPath(srvman, virtualDir);
|
|
// load iisDirObject browse
|
|
PropertyBag bag = dirBrowseSvc.GetDirectoryBrowseSettings(srvman, virtualDir.FullQualifiedPath);
|
|
virtualDir.EnableDirectoryBrowsing = (bool)bag[DirectoryBrowseGlobals.Enabled];
|
|
|
|
// load anonym auth
|
|
bag = anonymAuthSvc.GetAuthenticationSettings(srvman, virtualDir.FullQualifiedPath);
|
|
virtualDir.AnonymousUsername = (string)bag[AuthenticationGlobals.AnonymousAuthenticationUserName];
|
|
virtualDir.AnonymousUserPassword = (string)bag[AuthenticationGlobals.AnonymousAuthenticationPassword];
|
|
virtualDir.EnableAnonymousAccess = (bool)bag[AuthenticationGlobals.Enabled];
|
|
|
|
// load windows auth
|
|
bag = winAuthSvc.GetAuthenticationSettings(srvman, virtualDir.FullQualifiedPath);
|
|
virtualDir.EnableWindowsAuthentication = (bool)bag[AuthenticationGlobals.Enabled];
|
|
// load basic auth
|
|
basicAuthSvc.GetAuthenticationSettings(srvman, virtualDir);
|
|
|
|
// load default docs
|
|
virtualDir.DefaultDocs = defaultDocSvc.GetDefaultDocumentSettings(srvman, virtualDir.FullQualifiedPath);
|
|
|
|
// load classic asp
|
|
bag = classicAspSvc.GetClassicAspSettings(srvman, virtualDir.FullQualifiedPath);
|
|
virtualDir.EnableParentPaths = (bool)bag[ClassicAspGlobals.EnableParentPaths];
|
|
//
|
|
virtualDir.IIs7 = true;
|
|
}
|
|
|
|
private void FillIISObjectFromVirtualDirectory(WebVirtualDirectory virtualDir)
|
|
{
|
|
dirBrowseSvc.SetDirectoryBrowseEnabled(virtualDir.FullQualifiedPath, virtualDir.EnableDirectoryBrowsing);
|
|
//
|
|
SetAnonymousAuthentication(virtualDir);
|
|
//
|
|
winAuthSvc.SetEnabled(virtualDir.FullQualifiedPath, virtualDir.EnableWindowsAuthentication);
|
|
//
|
|
basicAuthSvc.SetAuthenticationSettings(virtualDir);
|
|
//
|
|
defaultDocSvc.SetDefaultDocumentSettings(virtualDir.FullQualifiedPath, virtualDir.DefaultDocs);
|
|
//
|
|
classicAspSvc.SetClassicAspSettings(virtualDir);
|
|
}
|
|
|
|
private void FillVirtualDirectoryRestFromIISObject(ServerManager srvman, WebVirtualDirectory virtualDir)
|
|
{
|
|
// HTTP REDIRECT
|
|
httpRedirectSvc.GetHttpRedirectSettings(srvman, virtualDir);
|
|
|
|
// HTTP HEADERS
|
|
customHeadersSvc.GetCustomHttpHeaders(srvman, virtualDir);
|
|
|
|
// HTTP ERRORS
|
|
customErrorsSvc.GetCustomErrors(srvman, virtualDir);
|
|
|
|
// MIME MAPPINGS
|
|
mimeTypesSvc.GetMimeMaps(srvman, virtualDir);
|
|
|
|
// SCRIPT MAPS
|
|
// Load installed script maps.
|
|
|
|
virtualDir.AspInstalled = false; // not installed
|
|
virtualDir.PhpInstalled = ""; // none
|
|
virtualDir.PerlInstalled = false; // not installed
|
|
virtualDir.PythonInstalled = false; // not installed
|
|
virtualDir.ColdFusionInstalled = false; // not installed
|
|
//
|
|
var config = srvman.GetWebConfiguration(virtualDir.FullQualifiedPath);
|
|
var handlersSection = config.GetSection(Constants.HandlersSection);
|
|
|
|
// Loop through available maps and fill installed processors
|
|
foreach (ConfigurationElement action in handlersSection.GetCollection())
|
|
{
|
|
// Extract and evaluate scripting processor path
|
|
string processor = FileUtils.EvaluateSystemVariables(
|
|
Convert.ToString(action.GetAttributeValue("scriptProcessor")));
|
|
//
|
|
string actionName = Convert.ToString(action.GetAttributeValue("name"));
|
|
|
|
// Detect whether ASP scripting is enabled
|
|
if (!String.IsNullOrEmpty(AspPath) && String.Equals(AspPath, processor, StringComparison.InvariantCultureIgnoreCase))
|
|
virtualDir.AspInstalled = true;
|
|
|
|
// Detect whether PHP 5 scripting is enabled
|
|
if (!String.IsNullOrEmpty(PhpExecutablePath) && String.Equals(PhpExecutablePath, processor, StringComparison.InvariantCultureIgnoreCase))
|
|
virtualDir.PhpInstalled = PHP_5;
|
|
|
|
// Detect whether PHP 4 scripting is enabled
|
|
if (!String.IsNullOrEmpty(Php4Path) && String.Equals(Php4Path, processor, StringComparison.InvariantCultureIgnoreCase))
|
|
virtualDir.PhpInstalled = PHP_4;
|
|
|
|
// Detect whether ColdFusion scripting is enabled
|
|
if (!String.IsNullOrEmpty(ColdFusionPath) && String.Compare(ColdFusionPath, processor, true) == 0 && actionName.Contains(".cfm"))
|
|
virtualDir.ColdFusionInstalled = true;
|
|
|
|
// Detect whether Perl scripting is enabled
|
|
if (!String.IsNullOrEmpty(PerlPath) && String.Equals(PerlPath, processor, StringComparison.InvariantCultureIgnoreCase))
|
|
virtualDir.PerlInstalled = true;
|
|
}
|
|
|
|
//
|
|
string fqPath = virtualDir.FullQualifiedPath;
|
|
if (!fqPath.EndsWith(@"/"))
|
|
fqPath += "/";
|
|
//
|
|
fqPath += CGI_BIN_FOLDER;
|
|
//
|
|
HandlerAccessPolicy policy = handlersSvc.GetHandlersAccessPolicy(srvman, fqPath);
|
|
virtualDir.CgiBinInstalled = (policy & HandlerAccessPolicy.Execute) > 0;
|
|
|
|
// ASP.NET
|
|
FillAspNetSettingsFromIISObject(srvman, virtualDir);
|
|
}
|
|
|
|
private void FillAspNetSettingsFromIISObject(ServerManager srvman, WebVirtualDirectory vdir)
|
|
{
|
|
// Read ASP.NET settings
|
|
if (String.IsNullOrEmpty(vdir.ApplicationPool))
|
|
return;
|
|
//
|
|
try
|
|
{
|
|
var appool = srvman.ApplicationPools[vdir.ApplicationPool];
|
|
//
|
|
var aphl = new WebAppPoolHelper(ProviderSettings);
|
|
// ASP.NET 2.0 pipeline is supposed by default
|
|
var dotNetVersion = SiteAppPoolMode.dotNetFramework2;
|
|
//
|
|
#region Iterate over managed runtime keys of the helper class to properly evaluate ASP.NET version installed
|
|
foreach (var k in WebAppPool.AspNetVersions)
|
|
{
|
|
if (k.Value.Equals(appool.ManagedRuntimeVersion))
|
|
{
|
|
dotNetVersion = k.Key;
|
|
break;
|
|
}
|
|
}
|
|
#endregion
|
|
// Detect pipeline mode being used
|
|
if (appool.ManagedPipelineMode == ManagedPipelineMode.Classic)
|
|
dotNetVersion |= SiteAppPoolMode.Classic;
|
|
else
|
|
dotNetVersion |= SiteAppPoolMode.Integrated;
|
|
//
|
|
var aspNetVersion = String.Empty;
|
|
#region Iterate over supported ASP.NET versions based on result of the previous runtime version assesement
|
|
foreach (var item in WebAppPoolHelper.SupportedAppPoolModes)
|
|
{
|
|
if (item.Value == dotNetVersion)
|
|
{
|
|
// Obtain ASP.NET version installed
|
|
aspNetVersion = item.Key;
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
#endregion
|
|
// Assign the result of assesement
|
|
vdir.AspNetInstalled = aspNetVersion;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.WriteError(String.Format("Failed to read ASP.NET settings from {0}.", vdir.Name), ex);
|
|
// Re-throw
|
|
throw (ex);
|
|
}
|
|
}
|
|
|
|
private void DeleteDedicatedPoolsAllocated(string siteName)
|
|
{
|
|
try
|
|
{
|
|
WebAppPoolHelper aphl = new WebAppPoolHelper(ProviderSettings);
|
|
//
|
|
var dedicatedPools = Array.FindAll<WebAppPool>(aphl.SupportedAppPools.ToArray(),
|
|
x => aphl.isolation(x.Mode) == SiteAppPoolMode.Dedicated);
|
|
|
|
// cleanup app pools
|
|
using (var srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
foreach (var item in dedicatedPools)
|
|
{
|
|
string poolName = WSHelper.InferAppPoolName(item.Name, siteName, item.Mode);
|
|
//
|
|
ApplicationPool pool = srvman.ApplicationPools[poolName];
|
|
if (pool == null)
|
|
continue;
|
|
//
|
|
srvman.ApplicationPools.Remove(pool);
|
|
}
|
|
|
|
// save changes
|
|
srvman.CommitChanges();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.WriteError(ex);
|
|
throw (ex);
|
|
}
|
|
}
|
|
|
|
private void FillIISObjectFromVirtualDirectoryRest(WebVirtualDirectory virtualDir)
|
|
{
|
|
// TO-DO: HTTP REDIRECT
|
|
httpRedirectSvc.SetHttpRedirectSettings(virtualDir);
|
|
|
|
// TO-DO: HTTP HEADERS
|
|
customHeadersSvc.SetCustomHttpHeaders(virtualDir);
|
|
|
|
// TO-DO: HTTP ERRORS
|
|
customErrorsSvc.SetCustomErrors(virtualDir);
|
|
|
|
// TO-DO: MIME MAPPINGS
|
|
mimeTypesSvc.SetMimeMaps(virtualDir);
|
|
|
|
// Revert script mappings to the parent to simplify script mappings cleanup
|
|
//handlersSvc.InheritScriptMapsFromParent(virtualDir.FullQualifiedPath);
|
|
|
|
// TO-DO: SCRIPT MAPS
|
|
#region ASP script mappings
|
|
if (!String.IsNullOrEmpty(AspPath) && File.Exists(AspPath))
|
|
{
|
|
// Classic ASP
|
|
if (virtualDir.AspInstalled)
|
|
{
|
|
handlersSvc.AddScriptMaps(virtualDir, ASP_EXTENSIONS, AspPath,
|
|
Constants.HandlerAlias.CLASSIC_ASP, Constants.IsapiModule);
|
|
}
|
|
else
|
|
{
|
|
handlersSvc.RemoveScriptMaps(virtualDir, ASP_EXTENSIONS, AspPath);
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region PHP 5 script mappings
|
|
if (!String.IsNullOrEmpty(PhpExecutablePath) && File.Exists(PhpExecutablePath))
|
|
{
|
|
if (virtualDir.PhpInstalled == PHP_5)
|
|
{
|
|
switch (PhpMode)
|
|
{
|
|
case Constants.PhpMode.FastCGI:
|
|
handlersSvc.AddScriptMaps(virtualDir, PHP_EXTENSIONS,
|
|
PhpExecutablePath, Constants.HandlerAlias.PHP_FASTCGI, Constants.FastCgiModule);
|
|
break;
|
|
case Constants.PhpMode.CGI:
|
|
handlersSvc.AddScriptMaps(virtualDir, PHP_EXTENSIONS,
|
|
PhpExecutablePath, Constants.HandlerAlias.PHP_CGI, Constants.CgiModule);
|
|
break;
|
|
case Constants.PhpMode.ISAPI:
|
|
handlersSvc.AddScriptMaps(virtualDir, PHP_EXTENSIONS,
|
|
PhpExecutablePath, Constants.HandlerAlias.PHP_ISAPI, Constants.IsapiModule);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
handlersSvc.RemoveScriptMaps(virtualDir, PHP_EXTENSIONS, PhpExecutablePath);
|
|
}
|
|
}
|
|
//
|
|
#endregion
|
|
|
|
#region PHP 4 script mappings (IsapiModule only)
|
|
if (!String.IsNullOrEmpty(Php4Path) && File.Exists(Php4Path))
|
|
{
|
|
if (virtualDir.PhpInstalled == PHP_4)
|
|
{
|
|
handlersSvc.AddScriptMaps(virtualDir, PHP_EXTENSIONS, Php4Path,
|
|
Constants.HandlerAlias.PHP_ISAPI, Constants.IsapiModule);
|
|
}
|
|
else
|
|
{
|
|
handlersSvc.RemoveScriptMaps(virtualDir, PHP_EXTENSIONS, Php4Path);
|
|
}
|
|
}
|
|
//
|
|
#endregion
|
|
|
|
#region PERL scrit mappings
|
|
//
|
|
if (!String.IsNullOrEmpty(PerlPath) && File.Exists(PerlPath))
|
|
{
|
|
// Start from building Perl-specific CGI-executable definition
|
|
// IsapiModule
|
|
if (virtualDir.PerlInstalled)
|
|
{
|
|
// Perl works only in 32-bit mode on x64 environment
|
|
webObjectsSvc.ForceEnableAppPoolWow6432Mode(virtualDir.ApplicationPool);
|
|
//
|
|
handlersSvc.AddScriptMaps(virtualDir, PERL_EXTENSIONS, PerlPath,
|
|
Constants.HandlerAlias.PERL_ISAPI, Constants.IsapiModule);
|
|
}
|
|
else
|
|
{
|
|
handlersSvc.RemoveScriptMaps(virtualDir, PERL_EXTENSIONS, PerlPath);
|
|
}
|
|
}
|
|
//
|
|
#endregion
|
|
|
|
|
|
#region ColdFusion script mappings
|
|
//ColdFusion code
|
|
if (virtualDir.ColdFusionInstalled)
|
|
{
|
|
handlersSvc.AddScriptMaps(virtualDir, COLDFUSION_EXTENSIONS, ColdFusionPath,
|
|
Constants.HandlerAlias.COLDFUSION, Constants.IsapiModule);
|
|
}
|
|
else
|
|
{
|
|
handlersSvc.RemoveScriptMaps(virtualDir, COLDFUSION_EXTENSIONS, ColdFusionPath);
|
|
}
|
|
#endregion
|
|
// TO-DO: REST
|
|
}
|
|
|
|
/// <summary>
|
|
/// Update CGI-Bin
|
|
/// </summary>
|
|
/// <param name="installedHandlers">Already installed scrip maps.</param>
|
|
/// <param name="extensions">Extensions to check.</param>
|
|
/// <param name="processor">Extensions processor.</param>
|
|
private void UpdateCgiBinFolder(WebVirtualDirectory virtualDir)
|
|
{
|
|
//
|
|
string fqPath = virtualDir.FullQualifiedPath;
|
|
if (!fqPath.EndsWith(@"/"))
|
|
fqPath += "/";
|
|
//
|
|
fqPath += CGI_BIN_FOLDER;
|
|
string cgiBinPath = Path.Combine(virtualDir.ContentPath, CGI_BIN_FOLDER);
|
|
|
|
using (ServerManager srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
//
|
|
HandlerAccessPolicy policy = handlersSvc.GetHandlersAccessPolicy(srvman, fqPath);
|
|
policy &= ~HandlerAccessPolicy.Execute;
|
|
//
|
|
if (virtualDir.CgiBinInstalled)
|
|
{
|
|
// create folder if not exists
|
|
if (!FileUtils.DirectoryExists(cgiBinPath))
|
|
FileUtils.CreateDirectory(cgiBinPath);
|
|
//
|
|
policy |= HandlerAccessPolicy.Execute;
|
|
}
|
|
|
|
//
|
|
if (FileUtils.DirectoryExists(cgiBinPath))
|
|
handlersSvc.SetHandlersAccessPolicy(srvman, fqPath, policy);
|
|
|
|
// save
|
|
srvman.CommitChanges();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets anonymous authentication for the virtual iisDirObject
|
|
/// </summary>
|
|
/// <param name="vdir"></param>
|
|
private void SetAnonymousAuthentication(WebVirtualDirectory virtualDir)
|
|
{
|
|
// set anonymous credentials
|
|
anonymAuthSvc.SetAuthenticationSettings(virtualDir.FullQualifiedPath,
|
|
GetQualifiedAccountName(virtualDir.AnonymousUsername),
|
|
virtualDir.AnonymousUserPassword, virtualDir.EnableAnonymousAccess);
|
|
// configure "Connect As" feature
|
|
if (virtualDir.ContentPath.StartsWith(@"\\"))
|
|
webObjectsSvc.ConfigureConnectAsFeature(virtualDir);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates if needed dedicated iisAppObject pools and assigns to specified site iisAppObject pool according to
|
|
/// selected ASP.NET version.
|
|
/// </summary>
|
|
/// <param name="site">WEb site to operate on.</param>
|
|
/// <param name="createAppPools">A value which shows whether iisAppObject pools has to be created.</param>
|
|
private void SetWebSiteApplicationPool(WebSite site, bool createAppPools)
|
|
{
|
|
var aphl = new WebAppPoolHelper(ProviderSettings);
|
|
// Site isolation mode
|
|
var sisMode = site.DedicatedApplicationPool ? SiteAppPoolMode.Dedicated : SiteAppPoolMode.Shared;
|
|
// Create dedicated iisAppObject pool name for the site with installed ASP.NET version
|
|
if (createAppPools && site.DedicatedApplicationPool)
|
|
{
|
|
// Find dedicated app pools
|
|
var dedicatedPools = Array.FindAll<WebAppPool>(aphl.SupportedAppPools.ToArray(),
|
|
x => aphl.isolation(x.Mode) == SiteAppPoolMode.Dedicated);
|
|
// Generate dedicated iisAppObject pools names and create them.
|
|
foreach (var item in dedicatedPools)
|
|
{
|
|
// Retrieve .NET Framework version
|
|
var dotNetVersion = aphl.dotNetVersion(item.Mode);
|
|
//
|
|
var enable32BitAppOnWin64 = Enable32BitAppOnWin64;
|
|
// Force "enable32BitAppOnWin64" set to true for .NET v1.1
|
|
if (dotNetVersion == SiteAppPoolMode.dotNetFramework1)
|
|
enable32BitAppOnWin64 = true;
|
|
//
|
|
var poolName = WSHelper.InferAppPoolName(item.Name, site.Name, item.Mode);
|
|
// Ensure we are not going to add an existing app pool
|
|
if (webObjectsSvc.IsApplicationPoolExist(poolName))
|
|
continue;
|
|
//
|
|
using (var srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
// Create iisAppObject pool
|
|
var pool = srvman.ApplicationPools.Add(poolName);
|
|
pool.ManagedRuntimeVersion = aphl.aspnet_runtime(item.Mode);
|
|
pool.ManagedPipelineMode = aphl.runtime_pipeline(item.Mode);
|
|
pool.Enable32BitAppOnWin64 = enable32BitAppOnWin64;
|
|
pool.AutoStart = true;
|
|
// Identity
|
|
pool.ProcessModel.IdentityType = ProcessModelIdentityType.SpecificUser;
|
|
pool.ProcessModel.UserName = GetQualifiedAccountName(site.AnonymousUsername);
|
|
pool.ProcessModel.Password = site.AnonymousUserPassword;
|
|
// Commit changes
|
|
srvman.CommitChanges();
|
|
}
|
|
}
|
|
}
|
|
// Find
|
|
var siteAppPool = Array.Find<WebAppPool>(aphl.SupportedAppPools.ToArray(),
|
|
x => x.AspNetInstalled.Equals(site.AspNetInstalled) && aphl.isolation(x.Mode) == sisMode);
|
|
// Assign iisAppObject pool according to ASP.NET version installed and isolation mode specified.
|
|
site.ApplicationPool = WSHelper.InferAppPoolName(siteAppPool.Name, site.Name, siteAppPool.Mode);
|
|
}
|
|
|
|
private void CheckEnableWritePermissions(ServerManager srvman, WebVirtualDirectory virtualDir)
|
|
{
|
|
string anonymousUsername = virtualDir.AnonymousUsername;
|
|
//
|
|
if (virtualDir.DedicatedApplicationPool)
|
|
{
|
|
ApplicationPool appPool = webObjectsSvc.GetApplicationPool(srvman, virtualDir);
|
|
//
|
|
if (appPool != null)
|
|
anonymousUsername = appPool.ProcessModel.UserName;
|
|
}
|
|
//
|
|
if (!String.IsNullOrEmpty(anonymousUsername))
|
|
virtualDir.EnableWritePermissions = CheckWriteAccessEnabled(virtualDir.ContentPath,
|
|
GetNonQualifiedAccountName(anonymousUsername));
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region IWebServer Members
|
|
|
|
public override void ChangeSiteState(string siteId, ServerState state)
|
|
{
|
|
webObjectsSvc.ChangeSiteState(siteId, state);
|
|
}
|
|
|
|
public override ServerState GetSiteState(string siteId)
|
|
{
|
|
using (ServerManager srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
return GetSiteState(srvman, siteId);
|
|
}
|
|
}
|
|
|
|
public ServerState GetSiteState(ServerManager srvman, string siteId)
|
|
{
|
|
return webObjectsSvc.GetSiteState(srvman, siteId);
|
|
}
|
|
|
|
public override bool SiteExists(string siteId)
|
|
{
|
|
using (ServerManager srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
return webObjectsSvc.SiteExists(srvman, siteId);
|
|
}
|
|
}
|
|
|
|
public override string[] GetSites()
|
|
{
|
|
using (ServerManager srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
return webObjectsSvc.GetSites(srvman);
|
|
}
|
|
}
|
|
|
|
public new string GetSiteId(string siteName)
|
|
{
|
|
using (ServerManager srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
return webObjectsSvc.GetWebSiteNameFromIIS(srvman, siteName);
|
|
}
|
|
}
|
|
|
|
public override WebSite GetSite(string siteId)
|
|
{
|
|
WebSite site = null;
|
|
using (ServerManager srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
WebAppPoolHelper aphl = new WebAppPoolHelper(ProviderSettings);
|
|
//
|
|
site = webObjectsSvc.GetWebSiteFromIIS(srvman, siteId);
|
|
//
|
|
site.Bindings = webObjectsSvc.GetSiteBindings(srvman, siteId);
|
|
//
|
|
FillVirtualDirectoryFromIISObject(srvman, site);
|
|
//
|
|
FillVirtualDirectoryRestFromIISObject(srvman, site);
|
|
|
|
// check frontpage
|
|
site.FrontPageAvailable = IsFrontPageSystemInstalled();
|
|
site.FrontPageInstalled = IsFrontPageInstalled(srvman, siteId);
|
|
|
|
//check ColdFusion
|
|
if (IsColdFusionSystemInstalled())
|
|
{
|
|
if (IsColdFusion7Installed())
|
|
{
|
|
site.ColdFusionVersion = "7";
|
|
site.ColdFusionAvailable = true;
|
|
}
|
|
else
|
|
{
|
|
if (IsColdFusion8Installed())
|
|
{
|
|
site.ColdFusionVersion = "8";
|
|
site.ColdFusionAvailable = true;
|
|
}
|
|
}
|
|
|
|
if (IsColdFusion9Installed())
|
|
{
|
|
site.ColdFusionVersion = "9";
|
|
site.ColdFusionAvailable = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
site.ColdFusionAvailable = false;
|
|
}
|
|
|
|
site.CreateCFVirtualDirectories = ColdFusionDirectoriesAdded(srvman, siteId);
|
|
|
|
//site.ColdFusionInstalled = IsColdFusionEnabledOnSite(GetSiteId(site.Name));
|
|
|
|
// check sharepoint
|
|
site.SharePointInstalled = false;
|
|
//
|
|
site.DedicatedApplicationPool = !aphl.is_shared_pool(site.ApplicationPool);
|
|
//
|
|
CheckEnableWritePermissions(srvman, site);
|
|
//
|
|
ReadWebManagementAccessDetails(srvman, site);
|
|
//
|
|
ReadWebDeployPublishingAccessDetails(site);
|
|
//
|
|
site.SecuredFoldersInstalled = IsSecuredFoldersInstalled(srvman, siteId);
|
|
|
|
// check Helicon Ape
|
|
HeliconApeStatus heliconApeStatus = GetHeliconApeStatus(srvman, siteId);
|
|
site.HeliconApeInstalled = heliconApeStatus.IsInstalled;
|
|
site.HeliconApeEnabled = heliconApeStatus.IsEnabled;
|
|
|
|
//
|
|
site.SiteState = GetSiteState(srvman, siteId);
|
|
//
|
|
site.SecuredFoldersInstalled = IsSecuredFoldersInstalled(srvman, siteId);
|
|
//
|
|
site.SiteState = GetSiteState(srvman, siteId);
|
|
//
|
|
}
|
|
return site;
|
|
}
|
|
|
|
public new string[] GetSitesAccounts(string[] siteIds)
|
|
{
|
|
List<string> accounts = new List<string>();
|
|
|
|
using (ServerManager srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
for (int i = 0; i < siteIds.Length; i++)
|
|
{
|
|
try
|
|
{
|
|
accounts.Add((string)anonymAuthSvc.GetAuthenticationSettings(srvman, siteIds[i])[AuthenticationGlobals.AnonymousAuthenticationUserName]);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.WriteError(String.Format("Web site {0} is either deleted or doesn't exist", siteIds[i]), ex);
|
|
}
|
|
}
|
|
}
|
|
return accounts.ToArray();
|
|
}
|
|
|
|
public override ServerBinding[] GetSiteBindings(string siteId)
|
|
{
|
|
using (ServerManager srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
return webObjectsSvc.GetSiteBindings(srvman, siteId);
|
|
}
|
|
}
|
|
|
|
public override string CreateSite(WebSite site)
|
|
{
|
|
// assign site id
|
|
site.SiteId = site.Name;
|
|
|
|
// create anonymous user
|
|
CreateWebSiteAnonymousAccount(site);
|
|
|
|
// Grant IIS_WPG group membership to site's anonymous account
|
|
SecurityUtils.GrantLocalGroupMembership(site.AnonymousUsername, IIS_IUSRS_GROUP, ServerSettings);
|
|
|
|
// set iisAppObject pools
|
|
SetWebSiteApplicationPool(site, true);
|
|
|
|
// set folder permissions
|
|
SetWebFolderPermissions(site.ContentPath, GetNonQualifiedAccountName(site.AnonymousUsername),
|
|
site.EnableWritePermissions, site.DedicatedApplicationPool);
|
|
|
|
// set DATA folder permissions
|
|
SetWebFolderPermissions(site.DataPath, GetNonQualifiedAccountName(site.AnonymousUsername),
|
|
true, site.DedicatedApplicationPool);
|
|
|
|
// qualify account name with AD Domain
|
|
site.AnonymousUsername = GetQualifiedAccountName(site.AnonymousUsername);
|
|
|
|
//
|
|
try
|
|
{
|
|
// Create site
|
|
webObjectsSvc.CreateSite(site);
|
|
// Update web site bindings
|
|
webObjectsSvc.UpdateSiteBindings(site.SiteId, site.Bindings);
|
|
// Set web site logging settings
|
|
webObjectsSvc.SetWebSiteLoggingSettings(site);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.WriteError(ex);
|
|
}
|
|
//
|
|
SetAnonymousAuthentication(site);
|
|
|
|
// create logs folder if not exists
|
|
if (!FileUtils.DirectoryExists(site.LogsPath))
|
|
FileUtils.CreateDirectory(site.LogsPath);
|
|
|
|
//
|
|
FillIISObjectFromVirtualDirectory(site);
|
|
//
|
|
FillIISObjectFromVirtualDirectoryRest(site);
|
|
//
|
|
UpdateCgiBinFolder(site);
|
|
//
|
|
try
|
|
{
|
|
webObjectsSvc.ChangeSiteState(site.SiteId, ServerState.Started);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.WriteError(ex);
|
|
}
|
|
//
|
|
return site.SiteId;
|
|
}
|
|
|
|
public override void UpdateSite(WebSite site)
|
|
{
|
|
// load original site settings
|
|
WebSite origSite = GetSite(site.SiteId);
|
|
|
|
// Get non-qualified anonymous account user name (eq. without domain name or machine name)
|
|
string anonymousAccount = GetNonQualifiedAccountName(site.AnonymousUsername);
|
|
string origAnonymousAccount = GetNonQualifiedAccountName(origSite.AnonymousUsername);
|
|
|
|
// if folder has been changed
|
|
if (String.Compare(origSite.ContentPath, site.ContentPath, true) != 0)
|
|
RemoveWebFolderPermissions(origSite.ContentPath, origAnonymousAccount);
|
|
|
|
// ensure anonumous user account exists
|
|
if (!SecurityUtils.UserExists(anonymousAccount, ServerSettings, UsersOU))
|
|
{
|
|
CreateWebSiteAnonymousAccount(site);
|
|
}
|
|
|
|
anonymousAccount = GetNonQualifiedAccountName(site.AnonymousUsername);
|
|
|
|
// Grant IIS_IUSRS group membership
|
|
if (!SecurityUtils.HasLocalGroupMembership(anonymousAccount, IIS_IUSRS_GROUP, ServerSettings, UsersOU))
|
|
{
|
|
SecurityUtils.GrantLocalGroupMembership(anonymousAccount, IIS_IUSRS_GROUP, ServerSettings);
|
|
}
|
|
|
|
//
|
|
bool appPoolFlagChanged = origSite.DedicatedApplicationPool != site.DedicatedApplicationPool;
|
|
// check if we need to remove dedicated app pools
|
|
bool deleteDedicatedPools = (appPoolFlagChanged && !site.DedicatedApplicationPool);
|
|
//
|
|
SetWebSiteApplicationPool(site, false);
|
|
//
|
|
if (!webObjectsSvc.IsApplicationPoolExist(site.ApplicationPool) &&
|
|
site.DedicatedApplicationPool)
|
|
{
|
|
// CREATE dedicated pool
|
|
SetWebSiteApplicationPool(site, true);
|
|
}
|
|
//
|
|
FillIISObjectFromVirtualDirectory(site);
|
|
//
|
|
FillIISObjectFromVirtualDirectoryRest(site);
|
|
|
|
// set logs folder permissions
|
|
if (!FileUtils.DirectoryExists(site.LogsPath))
|
|
FileUtils.CreateDirectory(site.LogsPath);
|
|
// Update website
|
|
webObjectsSvc.UpdateSite(site);
|
|
// Update website bindings
|
|
webObjectsSvc.UpdateSiteBindings(site.SiteId, site.Bindings);
|
|
// Set website logging settings
|
|
webObjectsSvc.SetWebSiteLoggingSettings(site);
|
|
//
|
|
UpdateCgiBinFolder(site);
|
|
|
|
// TO-DO
|
|
// update all child virtual directories to use new pool
|
|
if (appPoolFlagChanged)
|
|
{
|
|
WebVirtualDirectory[] dirs = GetVirtualDirectories(site.SiteId);
|
|
foreach (WebVirtualDirectory dir in dirs)
|
|
{
|
|
// set dedicated pool flag
|
|
//dir.DedicatedApplicationPool = site.DedicatedApplicationPool;
|
|
WebVirtualDirectory vdir = GetVirtualDirectory(site.SiteId, dir.Name);
|
|
vdir.AspNetInstalled = site.AspNetInstalled;
|
|
vdir.ApplicationPool = site.ApplicationPool;
|
|
// update iisDirObject
|
|
UpdateVirtualDirectory(site.SiteId, vdir);
|
|
}
|
|
// Enforce Web Deploy publishing settings if enabled to ensure we use correct settings all the time
|
|
if (site.WebDeploySitePublishingEnabled == true)
|
|
{
|
|
EnforceDelegationRulesRestrictions(site.Name, site.WebDeployPublishingAccount);
|
|
}
|
|
}
|
|
|
|
#region ColdFusion Virtual Directories
|
|
using (ServerManager srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
//TODO: NANOFIX:Added the If block and put the rest of the code in the else block(For Virtual Directory)
|
|
if (string.IsNullOrEmpty(base.CFFlashRemotingDirPath))
|
|
{
|
|
DeleteCFVirtualDirectories(site.SiteId);
|
|
site.CreateCFVirtualDirectories = false;
|
|
}
|
|
else
|
|
{
|
|
if (ColdFusionDirectoriesAdded(srvman, site.SiteId))
|
|
{
|
|
if (!site.CreateCFVirtualDirectories)
|
|
{
|
|
DeleteCFVirtualDirectories(site.SiteId);
|
|
site.CreateCFVirtualDirectories = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (site.CreateCFVirtualDirectories)
|
|
{
|
|
CreateCFVirtualDirectories(site.SiteId);
|
|
site.CreateCFVirtualDirectories = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region ColdFusionHandlerFix
|
|
//TODO: NANOFIX: Region Added for Cold Fusion Handler Fix
|
|
using (ServerManager srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
var appConfig = srvman.GetApplicationHostConfiguration();
|
|
ConfigurationSection handlersSection = appConfig.GetSection(Constants.HandlersSection, (site as WebVirtualDirectory).FullQualifiedPath);
|
|
|
|
var handlersCollection = handlersSection.GetCollection();
|
|
|
|
List<ConfigurationElement> cfElementList = new List<ConfigurationElement>();
|
|
foreach (var action in handlersCollection)
|
|
{
|
|
var name = action["name"].ToString();
|
|
if (string.Compare(name, "coldfusion", true) == 0)
|
|
{
|
|
cfElementList.Add(action);
|
|
}
|
|
}
|
|
foreach (var e in cfElementList)
|
|
{
|
|
handlersCollection.Remove(e);
|
|
}
|
|
if (site.ColdFusionInstalled)
|
|
{
|
|
|
|
var cfElement = handlersCollection.CreateElement("add");
|
|
|
|
cfElement["name"] = "coldfusion";
|
|
cfElement["modules"] = "IsapiModule";
|
|
cfElement["path"] = "*";
|
|
cfElement["scriptProcessor"] = base.ColdFusionPath;
|
|
cfElement["verb"] = "*";
|
|
cfElement["resourceType"] = "Unspecified";
|
|
cfElement["requireAccess"] = "None";
|
|
cfElement["preCondition"] = "bitness64";
|
|
handlersCollection.AddAt(0, cfElement);
|
|
|
|
|
|
}
|
|
srvman.CommitChanges();
|
|
}
|
|
#endregion
|
|
|
|
// remove dedicated pools if any
|
|
if (deleteDedicatedPools)
|
|
DeleteDedicatedPoolsAllocated(site.Name);
|
|
|
|
// set WEB folder permissions
|
|
SetWebFolderPermissions(site.ContentPath, anonymousAccount, site.EnableWritePermissions, site.DedicatedApplicationPool);
|
|
|
|
// set DATA folder permissions
|
|
SetWebFolderPermissions(site.DataPath, anonymousAccount, true, site.DedicatedApplicationPool);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates site's bindings with supplied ones.
|
|
/// </summary>
|
|
/// <param name="siteId">Site's id to update bindings for.</param>
|
|
/// <param name="bindings">Bindings information.</param>
|
|
public override void UpdateSiteBindings(string siteId, ServerBinding[] bindings)
|
|
{
|
|
this.webObjectsSvc.UpdateSiteBindings(siteId, bindings);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Deletes site with specified id.
|
|
/// </summary>
|
|
/// <param name="siteId">Site's id to be deleted.</param>
|
|
public override void DeleteSite(string siteId)
|
|
{
|
|
// Load site description.
|
|
WebSite site = this.GetSite(siteId);
|
|
|
|
#region Fix for bug #594
|
|
// Disable Remote Management Access and revoke access permissions if any
|
|
if (IsWebManagementServiceInstalled() && IsWebManagementAccessEnabled(site))
|
|
{
|
|
RevokeWebManagementAccess(siteId, site[WebSite.WmSvcAccountName]);
|
|
}
|
|
#endregion
|
|
|
|
// Disable Web Deploy publishing functionality and revoke access permissions if any
|
|
if (IsWebDeployInstalled() && site.WebDeploySitePublishingEnabled)
|
|
{
|
|
RevokeWebDeployPublishingAccess(site.SiteId, site.WebDeployPublishingAccount);
|
|
}
|
|
|
|
// Get non-qualified account name
|
|
string anonymousAccount = GetNonQualifiedAccountName(site.AnonymousUsername);
|
|
// Remove unnecessary permissions.
|
|
RemoveWebFolderPermissions(site.ContentPath, anonymousAccount);
|
|
|
|
// Stop web site
|
|
webObjectsSvc.ChangeSiteState(site.Name, ServerState.Stopped);
|
|
Log.WriteInfo(String.Format("Site {0} was stopped before deleting.", site.Name));
|
|
// Delete site in IIS
|
|
webObjectsSvc.DeleteSite(siteId);
|
|
|
|
// Delete dedicated pool if required
|
|
if (site.DedicatedApplicationPool)
|
|
{
|
|
DeleteDedicatedPoolsAllocated(site.Name);
|
|
}
|
|
// ensure anonymous account is shared account
|
|
if (!String.Equals("IUSR", anonymousAccount))
|
|
{
|
|
// Revoke IIS_IUSRS membership first
|
|
if (SecurityUtils.HasLocalGroupMembership(anonymousAccount, IIS_IUSRS_GROUP, ServerSettings, UsersOU))
|
|
{
|
|
SecurityUtils.RevokeLocalGroupMembership(anonymousAccount, IIS_IUSRS_GROUP, ServerSettings);
|
|
}
|
|
|
|
// delete anonymous user account
|
|
if (SecurityUtils.UserExists(anonymousAccount, ServerSettings, UsersOU))
|
|
{
|
|
SecurityUtils.DeleteUser(anonymousAccount, ServerSettings, UsersOU);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks whether virtual iisDirObject with supplied name under specified site exists.
|
|
/// </summary>
|
|
/// <param name="siteId">Site id.</param>
|
|
/// <param name="directoryName">Directory name to check.</param>
|
|
/// <returns>true - if it exists; false - otherwise.</returns>
|
|
public override bool VirtualDirectoryExists(string siteId, string directoryName)
|
|
{
|
|
return this.webObjectsSvc.VirtualDirectoryExists(siteId, directoryName);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets virtual directories that belong to site with supplied id.
|
|
/// </summary>
|
|
/// <param name="siteId">Site's id to get virtual directories for.</param>
|
|
/// <returns>virtual directories that belong to site with supplied id.</returns>
|
|
public override WebVirtualDirectory[] GetVirtualDirectories(string siteId)
|
|
{
|
|
using (ServerManager srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
return GetVirtualDirectories(srvman, siteId);
|
|
}
|
|
}
|
|
|
|
private WebVirtualDirectory[] GetVirtualDirectories(ServerManager srvman, string siteId)
|
|
{
|
|
// get all virt dirs
|
|
WebVirtualDirectory[] virtDirs = webObjectsSvc.GetVirtualDirectories(srvman, siteId);
|
|
|
|
// filter
|
|
string sharedToolsFolder = GetMicrosoftSharedFolderPath();
|
|
List<WebVirtualDirectory> result = new List<WebVirtualDirectory>();
|
|
foreach (WebVirtualDirectory dir in virtDirs)
|
|
{
|
|
// check if this is a system (FrontPage or SharePoint) virtual iisDirObject
|
|
if (!String.IsNullOrEmpty(sharedToolsFolder)
|
|
&& dir.ContentPath.ToLower().StartsWith(sharedToolsFolder.ToLower()))
|
|
continue;
|
|
result.Add(dir);
|
|
}
|
|
return result.ToArray();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets virtual iisDirObject description that belongs to site with supplied id and has specified name.
|
|
/// </summary>
|
|
/// <param name="siteId">Site's id that owns virtual iisDirObject.</param>
|
|
/// <param name="directoryName">Directory's name to get description for.</param>
|
|
/// <returns>virtual iisDirObject description that belongs to site with supplied id and has specified name.</returns>
|
|
public override WebVirtualDirectory GetVirtualDirectory(string siteId, string directoryName)
|
|
{
|
|
using (ServerManager srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
WebAppPoolHelper aphl = new WebAppPoolHelper(ProviderSettings);
|
|
//
|
|
WebVirtualDirectory webVirtualDirectory = webObjectsSvc.GetVirtualDirectory(siteId, directoryName);
|
|
//
|
|
this.FillVirtualDirectoryFromIISObject(srvman, webVirtualDirectory);
|
|
this.FillVirtualDirectoryRestFromIISObject(srvman, webVirtualDirectory);
|
|
//
|
|
webVirtualDirectory.DedicatedApplicationPool = !aphl.is_shared_pool(webVirtualDirectory.ApplicationPool);
|
|
//
|
|
CheckEnableWritePermissions(srvman, webVirtualDirectory);
|
|
//
|
|
ReadWebManagementAccessDetails(srvman, webVirtualDirectory);
|
|
//
|
|
ReadWebDeployPublishingAccessDetails(webVirtualDirectory);
|
|
//
|
|
return webVirtualDirectory;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates virtual iisDirObject under site with specified id.
|
|
/// </summary>
|
|
/// <param name="siteId">Site's id to create virtual iisDirObject under.</param>
|
|
/// <param name="iisDirObject">Virtual iisDirObject description.</param>
|
|
public override void CreateVirtualDirectory(string siteId, WebVirtualDirectory directory)
|
|
{
|
|
// Create iisDirObject folder if not exists.
|
|
if (!FileUtils.DirectoryExists(directory.ContentPath))
|
|
{
|
|
FileUtils.CreateDirectory(directory.ContentPath);
|
|
}
|
|
//
|
|
WebSite webSite = GetSite(siteId);
|
|
// copy props from parent site
|
|
directory.ParentSiteName = siteId;
|
|
directory.AspNetInstalled = webSite.AspNetInstalled;
|
|
directory.ApplicationPool = webSite.ApplicationPool;
|
|
// Create record in IIS's configuration.
|
|
webObjectsSvc.CreateVirtualDirectory(siteId, directory.VirtualPath, directory.ContentPath);
|
|
|
|
using (ServerManager srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
PropertyBag bag = anonymAuthSvc.GetAuthenticationSettings(srvman, siteId);
|
|
directory.AnonymousUsername = (string)bag[AuthenticationGlobals.AnonymousAuthenticationUserName];
|
|
directory.AnonymousUserPassword = (string)bag[AuthenticationGlobals.AnonymousAuthenticationPassword];
|
|
directory.EnableAnonymousAccess = (bool)bag[AuthenticationGlobals.Enabled];
|
|
// Update virtual iisDirObject.
|
|
this.UpdateVirtualDirectory(siteId, directory);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates virtual iisDirObject settings.
|
|
/// </summary>
|
|
/// <param name="siteId">Site's id that owns supplied iisDirObject.</param>
|
|
/// <param name="iisDirObject">Web iisDirObject that needs to be updated.</param>
|
|
public override void UpdateVirtualDirectory(string siteId, WebVirtualDirectory directory)
|
|
{
|
|
string origPath = null;
|
|
using (ServerManager srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
if (!this.webObjectsSvc.SiteExists(srvman, siteId))
|
|
return;
|
|
|
|
// get original path
|
|
origPath = webObjectsSvc.GetPhysicalPath(srvman, directory);
|
|
}
|
|
|
|
WebAppPoolHelper aphl = new WebAppPoolHelper(ProviderSettings);
|
|
//
|
|
bool dedicatedPool = !aphl.is_shared_pool(directory.ApplicationPool);
|
|
//
|
|
SiteAppPoolMode sisMode = dedicatedPool ? SiteAppPoolMode.Dedicated : SiteAppPoolMode.Shared;
|
|
//
|
|
directory.ParentSiteName = siteId;
|
|
|
|
// remove unnecessary permissions
|
|
// if original folder has been changed
|
|
if (String.Compare(origPath, directory.ContentPath, true) != 0)
|
|
RemoveWebFolderPermissions(origPath, GetNonQualifiedAccountName(directory.AnonymousUsername));
|
|
// set folder permissions
|
|
SetWebFolderPermissions(directory.ContentPath, GetNonQualifiedAccountName(directory.AnonymousUsername),
|
|
directory.EnableWritePermissions, dedicatedPool);
|
|
//
|
|
var pool = Array.Find<WebAppPool>(aphl.SupportedAppPools.ToArray(),
|
|
x => x.AspNetInstalled.Equals(directory.AspNetInstalled) && aphl.isolation(x.Mode) == sisMode);
|
|
// Assign to virtual iisDirObject iisAppObject pool
|
|
directory.ApplicationPool = WSHelper.InferAppPoolName(pool.Name, siteId, pool.Mode);
|
|
//
|
|
webObjectsSvc.UpdateVirtualDirectory(directory);
|
|
//
|
|
this.FillIISObjectFromVirtualDirectory(directory);
|
|
this.FillIISObjectFromVirtualDirectoryRest(directory);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Deletes virtual iisDirObject within specified site.
|
|
/// </summary>
|
|
/// <param name="siteId">Site id.</param>
|
|
/// <param name="directoryName">Directory name to delete.</param>
|
|
public override void DeleteVirtualDirectory(string siteId, string directoryName)
|
|
{
|
|
var virtualDir = new WebVirtualDirectory
|
|
{
|
|
ParentSiteName = siteId,
|
|
Name = directoryName
|
|
};
|
|
//
|
|
webObjectsSvc.DeleteVirtualDirectory(virtualDir);
|
|
anonymAuthSvc.RemoveAuthenticationSettings(virtualDir.FullQualifiedPath);
|
|
}
|
|
|
|
public new void GrantWebSiteAccess(string path, string siteId, NTFSPermission permission)
|
|
{
|
|
// TODO
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region IISPassword
|
|
|
|
protected override bool IsSecuredFoldersInstalled(string siteId)
|
|
{
|
|
using (var srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
return IsSecuredFoldersInstalled(srvman, siteId);
|
|
}
|
|
}
|
|
|
|
private bool IsSecuredFoldersInstalled(ServerManager srvman, string siteId)
|
|
{
|
|
var appConfig = srvman.GetApplicationHostConfiguration();
|
|
//
|
|
var modulesSection = appConfig.GetSection(Constants.ModulesSection, siteId);
|
|
//
|
|
var modulesCollection = modulesSection.GetCollection();
|
|
//
|
|
foreach (var moduleEntry in modulesCollection)
|
|
{
|
|
if (String.Equals(moduleEntry["name"].ToString(), Constants.WEBSITEPANEL_IISMODULES, StringComparison.InvariantCultureIgnoreCase))
|
|
return true;
|
|
}
|
|
//
|
|
return false;
|
|
}
|
|
|
|
protected override string GetSiteContentPath(string siteId)
|
|
{
|
|
using (var srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
return GetSiteContentPath(srvman, siteId);
|
|
}
|
|
}
|
|
|
|
protected string GetSiteContentPath(ServerManager srvman, string siteId)
|
|
{
|
|
var webSite = webObjectsSvc.GetWebSiteFromIIS(srvman, siteId);
|
|
//
|
|
if (webSite != null)
|
|
return webObjectsSvc.GetPhysicalPath(srvman, webSite);
|
|
//
|
|
return String.Empty;
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <exception cref="System.ArgumentNullException" />
|
|
/// <exception cref="System.ApplicationException" />
|
|
/// <param name="siteId"></param>
|
|
public override void InstallSecuredFolders(string siteId)
|
|
{
|
|
using (var srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
//
|
|
if (String.IsNullOrEmpty(siteId))
|
|
throw new ArgumentNullException("siteId");
|
|
|
|
// WebsitePanel.IIsModules works for apps working in Integrated Pipeline mode
|
|
#region Switch automatically to the app pool with Integrated Pipeline enabled
|
|
var webSite = webObjectsSvc.GetWebSiteFromIIS(srvman, siteId);
|
|
//
|
|
if (webSite == null)
|
|
throw new ApplicationException(String.Format("Could not find a web site with the following identifier: {0}.", siteId));
|
|
//
|
|
var aphl = new WebAppPoolHelper(ProviderSettings);
|
|
// Fill ASP.NET settings
|
|
FillAspNetSettingsFromIISObject(srvman, webSite);
|
|
//
|
|
var currentPool = aphl.match_webapp_pool(webSite);
|
|
var dotNetVersion = aphl.dotNetVersion(currentPool.Mode);
|
|
var sisMode = aphl.isolation(currentPool.Mode);
|
|
// AT least ASP.NET 2.0 is allowed to provide such capabilities...
|
|
if (dotNetVersion == SiteAppPoolMode.dotNetFramework1)
|
|
dotNetVersion = SiteAppPoolMode.dotNetFramework2;
|
|
// and Integrated pipeline...
|
|
if (aphl.pipeline(currentPool.Mode) != SiteAppPoolMode.Integrated)
|
|
{
|
|
// Lookup for the opposite pool matching the criteria
|
|
var oppositePool = Array.Find<WebAppPool>(aphl.SupportedAppPools.ToArray(),
|
|
x => aphl.dotNetVersion(x.Mode) == dotNetVersion && aphl.isolation(x.Mode) == sisMode
|
|
&& aphl.pipeline(x.Mode) == SiteAppPoolMode.Integrated);
|
|
//
|
|
webSite.AspNetInstalled = oppositePool.AspNetInstalled;
|
|
//
|
|
SetWebSiteApplicationPool(webSite, false);
|
|
//
|
|
|
|
var iisSiteObject = srvman.Sites[siteId];
|
|
iisSiteObject.Applications["/"].ApplicationPoolName = webSite.ApplicationPool;
|
|
//
|
|
srvman.CommitChanges();
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Disable automatically Integrated Windows Authentication
|
|
//
|
|
using (var srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
PropertyBag winAuthBag = winAuthSvc.GetAuthenticationSettings(srvman, siteId);
|
|
//
|
|
if ((bool)winAuthBag[AuthenticationGlobals.Enabled])
|
|
{
|
|
|
|
Configuration config = srvman.GetApplicationHostConfiguration();
|
|
|
|
ConfigurationSection windowsAuthenticationSection = config.GetSection(
|
|
"system.webServer/security/authentication/windowsAuthentication",
|
|
siteId);
|
|
//
|
|
windowsAuthenticationSection["enabled"] = false;
|
|
//
|
|
srvman.CommitChanges();
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
//
|
|
using (var srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
//
|
|
Configuration appConfig = srvman.GetApplicationHostConfiguration();
|
|
//
|
|
ConfigurationSection modulesSection = appConfig.GetSection(Constants.ModulesSection, siteId);
|
|
//
|
|
ConfigurationElementCollection modulesCollection = modulesSection.GetCollection();
|
|
//
|
|
ConfigurationElement moduleAdd = modulesCollection.CreateElement("add");
|
|
//
|
|
moduleAdd["name"] = Constants.WEBSITEPANEL_IISMODULES;
|
|
moduleAdd["type"] = SecureFoldersModuleAssembly;
|
|
// Enable module for all content despite ASP.NET is enabled or not
|
|
moduleAdd["preCondition"] = "";
|
|
//
|
|
modulesCollection.Add(moduleAdd);
|
|
//
|
|
srvman.CommitChanges();
|
|
}
|
|
|
|
}
|
|
|
|
public override void UninstallSecuredFolders(string siteId)
|
|
{
|
|
//
|
|
if (String.IsNullOrEmpty(siteId))
|
|
throw new ArgumentNullException("siteId");
|
|
//
|
|
using (var srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
//
|
|
Configuration appConfig = srvman.GetApplicationHostConfiguration();
|
|
//
|
|
ConfigurationSection modulesSection = appConfig.GetSection(Constants.ModulesSection, siteId);
|
|
//
|
|
ConfigurationElementCollection modulesCollection = modulesSection.GetCollection();
|
|
//
|
|
ConfigurationElement iisModulesEntry = null;
|
|
//
|
|
foreach (ConfigurationElement moduleEntry in modulesCollection)
|
|
{
|
|
if (String.Equals(moduleEntry["name"].ToString(), Constants.WEBSITEPANEL_IISMODULES, StringComparison.InvariantCultureIgnoreCase))
|
|
{
|
|
iisModulesEntry = moduleEntry;
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
if (iisModulesEntry != null)
|
|
{
|
|
modulesCollection.Remove(iisModulesEntry);
|
|
srvman.CommitChanges();
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Helicon Ape
|
|
|
|
public override HeliconApeStatus GetHeliconApeStatus(string siteId)
|
|
{
|
|
using (ServerManager srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
return GetHeliconApeStatus(srvman, siteId);
|
|
}
|
|
}
|
|
|
|
private HeliconApeStatus GetHeliconApeStatus(ServerManager srvman, string siteId)
|
|
{
|
|
string installDir = GetHeliconApeInstallDir(siteId);
|
|
string registrationInfo = GetRegistrationInfo(siteId, installDir);
|
|
|
|
return new HeliconApeStatus
|
|
{
|
|
IsEnabled = IsHeliconApeEnabled(srvman, siteId),
|
|
InstallDir = installDir,
|
|
IsInstalled = IsHeliconApeInstalled(srvman, siteId, installDir),
|
|
Version = GetHeliconApeVersion(siteId, installDir),
|
|
IsRegistered = IsHeliconApeRegistered(siteId, registrationInfo),
|
|
RegistrationInfo = registrationInfo
|
|
};
|
|
}
|
|
|
|
private bool IsHeliconApeEnabled(ServerManager srvman, string siteId)
|
|
{
|
|
var appConfig = srvman.GetApplicationHostConfiguration();
|
|
var modulesSection = appConfig.GetSection(Constants.ModulesSection, siteId);
|
|
var modulesCollection = modulesSection.GetCollection();
|
|
|
|
foreach (var moduleEntry in modulesCollection)
|
|
{
|
|
if (String.Equals(moduleEntry["name"].ToString(), Constants.HeliconApeModule, StringComparison.InvariantCultureIgnoreCase))
|
|
return true;
|
|
}
|
|
//
|
|
return false;
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates the specified account and grants it Web Publishing Access permissions
|
|
/// </summary>
|
|
/// <param name="siteName">Web site name to enable Web Publishing Access at</param>
|
|
/// <param name="accountName">User name to grant the access for</param>
|
|
/// <param name="accountPassword">User password</param>
|
|
public new void GrantWebDeployPublishingAccess(string siteName, string accountName, string accountPassword)
|
|
{
|
|
// Web Publishing Access feature requires FullControl permissions on the web site's wwwroot folder
|
|
GrantWebManagementAccessInternally(siteName, accountName, accountPassword, NTFSPermission.FullControl);
|
|
//
|
|
EnforceDelegationRulesRestrictions(siteName, accountName);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates the specified account and grants it Web Publishing Access permissions
|
|
/// </summary>
|
|
/// <param name="siteName">Web site name to enable Web Publishing Access at</param>
|
|
/// <param name="accountName">User name to grant the access for</param>
|
|
/// <param name="accountPassword">User password</param>
|
|
public new void RevokeWebDeployPublishingAccess(string siteName, string accountName)
|
|
{
|
|
// Web Publishing Access feature requires FullControl permissions on the web site's wwwroot folder
|
|
RevokeWebManagementAccess(siteName, accountName);
|
|
//
|
|
RemoveDelegationRulesRestrictions(siteName, accountName);
|
|
}
|
|
|
|
private void RemoveDelegationRulesRestrictions(string siteName, string accountName)
|
|
{
|
|
WebSite webSite = null;
|
|
using (ServerManager srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
webSite = webObjectsSvc.GetWebSiteFromIIS(srvman, siteName);
|
|
}
|
|
var moduleService = new DelegationRulesModuleService();
|
|
// Adjust web publishing permissions to the user accordingly to deny some rules for shared app pools
|
|
|
|
var fqUsername = GetFullQualifiedAccountName(accountName);
|
|
// Instantiate application pool helper to retrieve the app pool mode web site is running in
|
|
WebAppPoolHelper aphl = new WebAppPoolHelper(ProviderSettings);
|
|
//
|
|
// Shared app pool is a subject restrictions to change ASP.NET version and recycle the pool,
|
|
// so we need to remove these restrictions
|
|
if (aphl.is_shared_pool(webSite.ApplicationPool) == true)
|
|
{
|
|
//
|
|
moduleService.RemoveUserFromRule("recycleApp", "{userScope}", fqUsername);
|
|
moduleService.RemoveUserFromRule("appPoolPipeline,appPoolNetFx", "{userScope}", fqUsername);
|
|
}
|
|
}
|
|
|
|
public void EnforceDelegationRulesRestrictions(string siteName, string accountName)
|
|
{
|
|
WebSite webSite = null;
|
|
using (ServerManager srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
webSite = webObjectsSvc.GetWebSiteFromIIS(srvman, siteName);
|
|
}
|
|
|
|
var moduleService = new DelegationRulesModuleService();
|
|
// Adjust web publishing permissions to the user accordingly to deny some rules for shared app pools
|
|
var fqUsername = GetFullQualifiedAccountName(accountName);
|
|
// Instantiate application pool helper to retrieve the app pool mode web site is running in
|
|
WebAppPoolHelper aphl = new WebAppPoolHelper(ProviderSettings);
|
|
// Shared app pool is a subject restrictions to change ASP.NET version and recycle the pool
|
|
if (aphl.is_shared_pool(webSite.ApplicationPool) == true)
|
|
{
|
|
//
|
|
moduleService.RestrictRuleToUser("recycleApp", "{userScope}", fqUsername);
|
|
moduleService.RestrictRuleToUser("appPoolPipeline,appPoolNetFx", "{userScope}", fqUsername);
|
|
}
|
|
// Dedicated app pool is not a subject for any restrictions
|
|
else
|
|
{
|
|
//
|
|
moduleService.AllowRuleToUser("recycleApp", "{userScope}", fqUsername);
|
|
moduleService.AllowRuleToUser("appPoolPipeline,appPoolNetFx", "{userScope}", fqUsername);
|
|
}
|
|
}
|
|
|
|
private string GetHeliconApeInstallDir(string siteId)
|
|
{
|
|
//Check global registration
|
|
return Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Helicon\\Ape", "InstallDir", string.Empty) as string;
|
|
}
|
|
|
|
private bool IsHeliconApeInstalled(ServerManager srvman, string siteId, string installDir)
|
|
{
|
|
//Check global registration
|
|
bool result = !string.IsNullOrEmpty(installDir);
|
|
|
|
if (!result && !string.IsNullOrEmpty(siteId))
|
|
{
|
|
//Check per-site installation
|
|
string sitepath = GetSiteContentPath(srvman, siteId);
|
|
string dllPath = Path.Combine(sitepath, "Bin\\Helicon.Ape.dll");
|
|
|
|
result = File.Exists(dllPath);
|
|
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private static string HELICON_APE_NOT_REGISTERED = "Not registered";
|
|
|
|
private string GetHeliconApeVersion(string siteId, string installDir)
|
|
{
|
|
if (string.IsNullOrEmpty(installDir))
|
|
return HELICON_APE_NOT_REGISTERED;
|
|
|
|
return System.Diagnostics.FileVersionInfo.GetVersionInfo(Path.Combine(installDir, "Helicon.Ape.Editor.dll")).FileVersion;
|
|
}
|
|
|
|
private string GetHeliconApeModuleType(string siteId)
|
|
{
|
|
string installDir = GetHeliconApeInstallDir(siteId);
|
|
string version = GetHeliconApeVersion(siteId, installDir);
|
|
|
|
if (version.Equals(HELICON_APE_NOT_REGISTERED))
|
|
{
|
|
// Ape installed for site
|
|
return "Helicon.Ape.ApeModule";
|
|
}
|
|
else
|
|
{
|
|
// Ape installed globally in GAC
|
|
// return full type with version
|
|
return
|
|
string.Format(
|
|
"Helicon.Ape.ApeModule, Helicon.Ape, Version={0}, Culture=neutral, PublicKeyToken=95bfbfd1a38437eb",
|
|
version);
|
|
}
|
|
}
|
|
|
|
private string GetHeliconApeHandlerType(string siteId)
|
|
{
|
|
string installDir = GetHeliconApeInstallDir(siteId);
|
|
string version = GetHeliconApeVersion(siteId, installDir);
|
|
|
|
if (version.Equals(HELICON_APE_NOT_REGISTERED))
|
|
{
|
|
// Ape installed for site
|
|
return "Helicon.Ape.Handler";
|
|
}
|
|
else
|
|
{
|
|
// Ape installed globally in GAC
|
|
// return full type with version
|
|
return
|
|
string.Format(
|
|
"Helicon.Ape.Handler, Helicon.Ape, Version={0}, Culture=neutral, PublicKeyToken=95bfbfd1a38437eb",
|
|
version);
|
|
}
|
|
}
|
|
|
|
private string FindregistrationInfo(string path)
|
|
{
|
|
System.Text.RegularExpressions.Regex reRegistrationName = new System.Text.RegularExpressions.Regex("^\\s*RegistrationName\\s*=\\s*([^#=]+)\\s*(?:#.*)?", System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.CultureInvariant | System.Text.RegularExpressions.RegexOptions.Compiled);
|
|
|
|
string registrationName = "";
|
|
|
|
|
|
using (StreamReader sr = File.OpenText(path))
|
|
{
|
|
while (sr.Peek() >= 0)
|
|
{
|
|
string line = sr.ReadLine();
|
|
if (reRegistrationName.Match(line).Success)
|
|
{
|
|
registrationName = reRegistrationName.Match(line).Groups[1].Value;
|
|
|
|
if (
|
|
!string.IsNullOrEmpty(registrationName)
|
|
)
|
|
{
|
|
return string.Format("Registered to: {0}", registrationName);
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//Not found
|
|
return string.Empty;
|
|
|
|
|
|
}
|
|
|
|
private string GetRegistrationInfo(string siteId, string installDir)
|
|
{
|
|
if (string.IsNullOrEmpty(installDir))
|
|
return string.Empty;
|
|
|
|
|
|
|
|
string registrationInfo = FindregistrationInfo(Path.Combine(installDir, "licenses.conf"));
|
|
if (!string.IsNullOrEmpty(registrationInfo))
|
|
return registrationInfo;
|
|
|
|
|
|
|
|
registrationInfo = FindregistrationInfo(Path.Combine(installDir, "httpd.conf"));
|
|
if (!string.IsNullOrEmpty(registrationInfo))
|
|
return registrationInfo;
|
|
|
|
|
|
|
|
long dtFirstRunBinary = (long)Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Helicon\\Ape", "FirstRun", 0L);
|
|
|
|
DateTime dtFirstRun;
|
|
if (0 == dtFirstRunBinary)
|
|
{
|
|
dtFirstRun = DateTime.Now;
|
|
Registry.SetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Helicon\\Ape", "FirstRun", dtFirstRun.ToBinary(),RegistryValueKind.QWord );
|
|
}
|
|
else
|
|
{
|
|
dtFirstRun = DateTime.FromBinary(dtFirstRunBinary);
|
|
}
|
|
|
|
int trialDays = 45 - (DateTime.Now - dtFirstRun).Days;
|
|
if (trialDays < 0)
|
|
trialDays = 0;
|
|
|
|
|
|
return string.Format("Trial days left: {0}", trialDays);
|
|
|
|
|
|
}
|
|
|
|
private bool IsHeliconApeRegistered(string siteId, string registrationInfo)
|
|
{
|
|
if (string.IsNullOrEmpty(registrationInfo))
|
|
return false;
|
|
|
|
|
|
return registrationInfo.StartsWith("Registered to:");
|
|
}
|
|
|
|
public override void EnableHeliconApe(string siteId)
|
|
{
|
|
WebSite webSite = null;
|
|
using (ServerManager srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
//
|
|
if (String.IsNullOrEmpty(siteId))
|
|
throw new ArgumentNullException("siteId");
|
|
|
|
// Helicon.Ape.ApeModule works for apps working in Integrated Pipeline mode
|
|
// Switch automatically to the app pool with Integrated Pipeline enabled
|
|
webSite = webObjectsSvc.GetWebSiteFromIIS(srvman, siteId);
|
|
//
|
|
if (webSite == null)
|
|
throw new ApplicationException(String.Format("Could not find a web site with the following identifier: {0}.", siteId));
|
|
|
|
// Fill ASP.NET settings
|
|
FillAspNetSettingsFromIISObject(srvman, webSite);
|
|
}
|
|
|
|
//
|
|
var aphl = new WebAppPoolHelper(ProviderSettings);
|
|
var currentPool = aphl.match_webapp_pool(webSite);
|
|
var dotNetVersion = aphl.dotNetVersion(currentPool.Mode);
|
|
var sisMode = aphl.isolation(currentPool.Mode);
|
|
// AT least ASP.NET 2.0 is allowed to provide such capabilities...
|
|
if (dotNetVersion == SiteAppPoolMode.dotNetFramework1)
|
|
dotNetVersion = SiteAppPoolMode.dotNetFramework2;
|
|
// and Integrated pipeline...
|
|
if (aphl.pipeline(currentPool.Mode) != SiteAppPoolMode.Integrated)
|
|
{
|
|
// Lookup for the opposite pool matching the criteria
|
|
var oppositePool = Array.Find<WebAppPool>(aphl.SupportedAppPools.ToArray(),
|
|
x => aphl.dotNetVersion(x.Mode) == dotNetVersion && aphl.isolation(x.Mode) == sisMode
|
|
&& aphl.pipeline(x.Mode) == SiteAppPoolMode.Integrated);
|
|
//
|
|
webSite.AspNetInstalled = oppositePool.AspNetInstalled;
|
|
//
|
|
SetWebSiteApplicationPool(webSite, false);
|
|
//
|
|
using (var srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
var iisSiteObject = srvman.Sites[siteId];
|
|
iisSiteObject.Applications["/"].ApplicationPoolName = webSite.ApplicationPool;
|
|
//
|
|
srvman.CommitChanges();
|
|
}
|
|
}
|
|
|
|
#region Disable automatically Integrated Windows Authentication
|
|
using (var srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
PropertyBag winAuthBag = winAuthSvc.GetAuthenticationSettings(srvman, siteId);
|
|
//
|
|
if ((bool)winAuthBag[AuthenticationGlobals.Enabled])
|
|
{
|
|
Configuration config = srvman.GetApplicationHostConfiguration();
|
|
|
|
ConfigurationSection windowsAuthenticationSection = config.GetSection(
|
|
"system.webServer/security/authentication/windowsAuthentication",
|
|
siteId);
|
|
//
|
|
windowsAuthenticationSection["enabled"] = false;
|
|
//
|
|
srvman.CommitChanges();
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Disable automatically Secured Folders
|
|
if (IsSecuredFoldersInstalled(siteId))
|
|
{
|
|
UninstallSecuredFolders(siteId);
|
|
}
|
|
#endregion
|
|
|
|
|
|
//
|
|
using (var srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
//
|
|
Configuration appConfig = srvman.GetApplicationHostConfiguration();
|
|
|
|
// add Helicon.Ape module
|
|
ConfigurationSection modulesSection = appConfig.GetSection(Constants.ModulesSection, siteId);
|
|
ConfigurationElementCollection modulesCollection = modulesSection.GetCollection();
|
|
ConfigurationElement moduleAdd = modulesCollection.CreateElement("add");
|
|
moduleAdd["name"] = Constants.HeliconApeModule;
|
|
moduleAdd["type"] = GetHeliconApeModuleType(siteId);
|
|
//
|
|
modulesCollection.Add(moduleAdd);
|
|
|
|
// add Helicon.Ape handler
|
|
ConfigurationSection handlersSection = appConfig.GetSection(Constants.HandlersSection, siteId);
|
|
ConfigurationElementCollection handlersCollection = handlersSection.GetCollection();
|
|
ConfigurationElement handlerAdd = handlersCollection.CreateElement("add");
|
|
handlerAdd["name"] = Constants.HeliconApeModule;
|
|
handlerAdd["type"] = GetHeliconApeHandlerType(siteId);
|
|
handlerAdd["path"] = Constants.HeliconApeHandlerPath;
|
|
handlerAdd["verb"] = "*";
|
|
handlerAdd["resourceType"] = "Unspecified";
|
|
//
|
|
handlersCollection.Add(handlerAdd);
|
|
//
|
|
srvman.CommitChanges();
|
|
}
|
|
}
|
|
|
|
public override void DisableHeliconApe(string siteId)
|
|
{
|
|
//
|
|
if (String.IsNullOrEmpty(siteId))
|
|
throw new ArgumentNullException("siteId");
|
|
//
|
|
using (var srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
//
|
|
Configuration appConfig = srvman.GetApplicationHostConfiguration();
|
|
|
|
// remove Helicon.Ape module
|
|
ConfigurationSection modulesSection = appConfig.GetSection(Constants.ModulesSection, siteId);
|
|
ConfigurationElementCollection modulesCollection = modulesSection.GetCollection();
|
|
ConfigurationElement htaccessModuleEntry = null;
|
|
foreach (ConfigurationElement moduleEntry in modulesCollection)
|
|
{
|
|
if (String.Equals(moduleEntry["name"].ToString(), Constants.HeliconApeModule, StringComparison.InvariantCultureIgnoreCase))
|
|
{
|
|
htaccessModuleEntry = moduleEntry;
|
|
break;
|
|
}
|
|
}
|
|
if (htaccessModuleEntry != null)
|
|
{
|
|
modulesCollection.Remove(htaccessModuleEntry);
|
|
}
|
|
|
|
// remove Helicon.Ape handler
|
|
ConfigurationSection handlersSection = appConfig.GetSection(Constants.HandlersSection, siteId);
|
|
ConfigurationElementCollection handlersCollection = handlersSection.GetCollection();
|
|
ConfigurationElement htaccessHandlerEntry = null;
|
|
foreach (ConfigurationElement handlerEntry in handlersCollection)
|
|
{
|
|
if (String.Equals(handlerEntry["name"].ToString(), Constants.HeliconApeModule, StringComparison.InvariantCultureIgnoreCase))
|
|
{
|
|
htaccessHandlerEntry = handlerEntry;
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
if (htaccessHandlerEntry != null)
|
|
{
|
|
handlersCollection.Remove(htaccessHandlerEntry);
|
|
}
|
|
|
|
// commit changes to metabase
|
|
if (htaccessModuleEntry != null || htaccessHandlerEntry != null)
|
|
{
|
|
srvman.CommitChanges();
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
public override List<HtaccessFolder> GetHeliconApeFolders(string siteId)
|
|
{
|
|
string siteRootPath = GetSiteContentPath(siteId);
|
|
List<HtaccessFolder> folders = new List<HtaccessFolder>();
|
|
|
|
// walk through the virtual directories
|
|
WebVirtualDirectory[] virtualDirectories = GetVirtualDirectories(siteId);
|
|
foreach (WebVirtualDirectory webVirtualDirectory in virtualDirectories)
|
|
{
|
|
HtaccessFolder.GetDirectoriesWithHtaccess(siteRootPath, "\\" + webVirtualDirectory.FullQualifiedPath, webVirtualDirectory.ContentPath, webVirtualDirectory.ContentPath, folders);
|
|
}
|
|
|
|
// walk through the filesystem
|
|
HtaccessFolder.GetDirectoriesWithHtaccess(siteRootPath, "", siteRootPath, siteRootPath, folders);
|
|
|
|
folders.Sort();
|
|
|
|
return folders;
|
|
}
|
|
|
|
public override HtaccessFolder GetHeliconApeFolder(string siteId, string folderPath)
|
|
{
|
|
// search folder
|
|
List<HtaccessFolder> htaccessFolders = GetHeliconApeFolders(siteId);
|
|
|
|
foreach (HtaccessFolder htaccessFolder in htaccessFolders)
|
|
{
|
|
if (string.Equals(folderPath, htaccessFolder.Path, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
htaccessFolder.ReadHtaccess();
|
|
return htaccessFolder;
|
|
}
|
|
}
|
|
|
|
// create new htaccess folder
|
|
return HtaccessFolder.CreateHtaccessFolder(GetSiteContentPath(siteId), folderPath);
|
|
}
|
|
|
|
public override HtaccessFolder GetHeliconApeHttpdFolder()
|
|
{
|
|
return HtaccessFolder.CreateHttpdConfFolder(GetHeliconApeInstallDir("-1"));
|
|
}
|
|
|
|
public override void UpdateHeliconApeFolder(string siteId, HtaccessFolder folder)
|
|
{
|
|
if (null != folder)
|
|
{
|
|
if (string.IsNullOrEmpty(folder.ContentPath))
|
|
{
|
|
HtaccessFolder newFolder = GetHeliconApeFolder(siteId, folder.Path);
|
|
newFolder.HtaccessContent = folder.HtaccessContent;
|
|
newFolder.Update();
|
|
}
|
|
else
|
|
{
|
|
if (string.IsNullOrEmpty(folder.SiteRootPath))
|
|
{
|
|
folder.SiteRootPath = GetSiteContentPath(siteId);
|
|
}
|
|
folder.Update();
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void UpdateHeliconApeHttpdFolder(HtaccessFolder folder)
|
|
{
|
|
if (null != folder)
|
|
{
|
|
HtaccessFolder newFolder = GetHeliconApeHttpdFolder();
|
|
newFolder.HtaccessContent = folder.HtaccessContent;
|
|
newFolder.Update();
|
|
}
|
|
}
|
|
|
|
public override void DeleteHeliconApeFolder(string siteId, string folderPath)
|
|
{
|
|
string rootPath = GetSiteContentPath(siteId);
|
|
string contentPath = Path.Combine(rootPath, folderPath);
|
|
string htaccessPath = Path.Combine(contentPath, HtaccessFolder.HTACCESS_FILE);
|
|
|
|
if (File.Exists(htaccessPath))
|
|
{
|
|
File.Delete(htaccessPath);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Secured Helicon Ape Users
|
|
|
|
public static string GeneratePasswordHash(HtaccessUser user)
|
|
{
|
|
if (HtaccessFolder.AUTH_TYPE_BASIC == user.AuthType)
|
|
{
|
|
|
|
// BASIC
|
|
switch (user.EncType)
|
|
{
|
|
case HtaccessUser.ENCODING_TYPE_APACHE_MD5:
|
|
return PasswdHelper.MD5Encode(user.Password, PasswdHelper.GetRandomSalt());
|
|
case HtaccessUser.ENCODING_TYPE_SHA1:
|
|
return PasswdHelper.SHA1Encode(user.Password);
|
|
case HtaccessUser.ENCODING_TYPE_UNIX_CRYPT:
|
|
default:
|
|
BsdDES bsdDes = new BsdDES();
|
|
return bsdDes.Crypt(user.Password);
|
|
}
|
|
}
|
|
|
|
// DIGEST
|
|
return string.Format("{0}:{1}", user.Realm, PasswdHelper.DigestEncode(user.Name, user.Password, user.Realm));
|
|
}
|
|
|
|
public override List<HtaccessUser> GetHeliconApeUsers(string siteId)
|
|
{
|
|
string rootPath = GetSiteContentPath(siteId);
|
|
List<HtaccessUser> users = new List<HtaccessUser>();
|
|
|
|
//users.Add(new WebUser {Name = HtaccessFolder.VALID_USER});
|
|
|
|
// load users file
|
|
string usersPath = Path.Combine(rootPath, HtaccessFolder.HTPASSWDS_FILE);
|
|
List<string> lines = HtaccessFolder.ReadLinesFile(usersPath);
|
|
|
|
// iterate through all lines
|
|
for (int i = 0; i < lines.Count; i++)
|
|
{
|
|
string line = lines[i];
|
|
|
|
int colonIdx = line.IndexOf(":");
|
|
if (colonIdx != -1)
|
|
{
|
|
string username = line.Substring(0, colonIdx);
|
|
|
|
// add it to the return collection
|
|
users.Add(GetHeliconApeUser(siteId, username));
|
|
}
|
|
}
|
|
|
|
return users;
|
|
}
|
|
|
|
public override HtaccessUser GetHeliconApeUser(string siteId, string userName)
|
|
{
|
|
// load users file
|
|
string rootPath = GetSiteContentPath(siteId);
|
|
string usersPath = Path.Combine(rootPath, HtaccessFolder.HTPASSWDS_FILE);
|
|
List<string> lines = HtaccessFolder.ReadLinesFile(usersPath);
|
|
|
|
// iterate through all lines
|
|
HtaccessUser user = null;
|
|
for (int i = 0; i < lines.Count; i++)
|
|
{
|
|
string line = lines[i];
|
|
|
|
int colonIdx = line.IndexOf(":");
|
|
if (colonIdx != -1)
|
|
{
|
|
string username = line.Substring(0, colonIdx);
|
|
string password = line.Substring(colonIdx + 1);
|
|
if (String.Compare(username, userName, true) == 0)
|
|
{
|
|
// exists
|
|
user = new HtaccessUser();
|
|
user.Name = username;
|
|
user.Password = password;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (user == null)
|
|
return null; // user doesn't exist
|
|
|
|
List<string> userGroups = new List<string>();
|
|
|
|
// read groups information
|
|
// open groups file
|
|
string groupsPath = Path.Combine(rootPath, HtaccessFolder.HTGROUPS_FILE);
|
|
List<string> groupLines = HtaccessFolder.ReadLinesFile(groupsPath);
|
|
|
|
for (int i = 0; i < groupLines.Count; i++)
|
|
{
|
|
string groupLine = groupLines[i];
|
|
int colonIdx = groupLine.IndexOf(":");
|
|
if (colonIdx != -1)
|
|
{
|
|
string groupName = groupLine.Substring(0, colonIdx);
|
|
string[] groupMembers = groupLine.Substring(colonIdx + 1).Split(' ');
|
|
|
|
// check group members
|
|
for (int j = 0; j < groupMembers.Length; j++)
|
|
{
|
|
if (String.Compare(groupMembers[j], user.Name, true) == 0)
|
|
{
|
|
userGroups.Add(groupName);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} // end iterating groups
|
|
user.Groups = userGroups.ToArray();
|
|
|
|
return user;
|
|
}
|
|
|
|
public override void UpdateHeliconApeUser(string siteId, HtaccessUser user)
|
|
{
|
|
UpdateHeliconApeUser(siteId, user, false);
|
|
}
|
|
|
|
private void UpdateHeliconApeUser(string siteId, HtaccessUser user, bool deleteUser)
|
|
{
|
|
if (HtaccessFolder.VALID_USER == user.Name)
|
|
return;
|
|
|
|
string rootPath = GetSiteContentPath(siteId);
|
|
string usersPath = Path.Combine(rootPath, HtaccessFolder.HTPASSWDS_FILE);
|
|
|
|
// load users file
|
|
List<string> lines = HtaccessFolder.ReadLinesFile(usersPath);
|
|
|
|
// check if the user already exists
|
|
List<string> updatedLines = new List<string>();
|
|
bool exists = false;
|
|
for (int i = 0; i < lines.Count; i++)
|
|
{
|
|
string line = lines[i];
|
|
string updatedLine = line;
|
|
|
|
int colonIdx = line.IndexOf(":");
|
|
if (colonIdx != -1)
|
|
{
|
|
string username = line.Substring(0, colonIdx);
|
|
string password = line.Substring(colonIdx + 1);
|
|
if (String.Compare(username, user.Name, true) == 0)
|
|
{
|
|
// already exists
|
|
exists = true;
|
|
|
|
// check if we need to delete this user
|
|
if (deleteUser)
|
|
continue;
|
|
|
|
// change password if required
|
|
if (!String.IsNullOrEmpty(user.Password))
|
|
{
|
|
// hash password
|
|
password = GeneratePasswordHash(user);
|
|
|
|
// update line
|
|
updatedLine = username + ":" + password;
|
|
}
|
|
}
|
|
}
|
|
|
|
updatedLines.Add(updatedLine);
|
|
}
|
|
|
|
if (!exists && !deleteUser)
|
|
{
|
|
// new user has been added
|
|
updatedLines.Add(user.Name + ":" + GeneratePasswordHash(user));
|
|
}
|
|
|
|
// save users file
|
|
HtaccessFolder.WriteLinesFile(usersPath, updatedLines);
|
|
|
|
if (user.Groups == null)
|
|
user.Groups = new string[] { };
|
|
|
|
// update groups
|
|
// open groups file
|
|
string groupsPath = Path.Combine(rootPath, HtaccessFolder.HTGROUPS_FILE);
|
|
List<string> groupLines = HtaccessFolder.ReadLinesFile(groupsPath);
|
|
|
|
for (int i = 0; i < groupLines.Count; i++)
|
|
{
|
|
string groupLine = groupLines[i];
|
|
int colonIdx = groupLine.IndexOf(":");
|
|
if (colonIdx != -1)
|
|
{
|
|
string groupName = groupLine.Substring(0, colonIdx);
|
|
string[] groupMembers = groupLine.Substring(colonIdx + 1).Split(' ');
|
|
|
|
// check if user is assigned to this group
|
|
bool assigned = false;
|
|
for (int j = 0; j < user.Groups.Length; j++)
|
|
{
|
|
if (String.Compare(user.Groups[j], groupName, true) == 0)
|
|
{
|
|
assigned = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// remove current user
|
|
List<string> updatedMembers = new List<string>();
|
|
for (int j = 0; j < groupMembers.Length; j++)
|
|
{
|
|
// user exists in the members
|
|
// check if he should be really added to this group
|
|
if (String.Compare(groupMembers[j], user.Name, true) == 0)
|
|
continue;
|
|
|
|
updatedMembers.Add(groupMembers[j]);
|
|
}
|
|
|
|
if (assigned)
|
|
updatedMembers.Add(user.Name);
|
|
|
|
// modify group line
|
|
groupLines[i] = groupName + ":" + String.Join(" ", updatedMembers.ToArray());
|
|
}
|
|
} // end iterating groups
|
|
|
|
// save group file
|
|
HtaccessFolder.WriteLinesFile(groupsPath, groupLines);
|
|
}
|
|
|
|
public override void DeleteHeliconApeUser(string siteId, string userName)
|
|
{
|
|
string rootPath = GetSiteContentPath(siteId);
|
|
HtaccessUser user = new HtaccessUser();
|
|
user.Name = userName;
|
|
|
|
// update users and groups
|
|
UpdateHeliconApeUser(siteId, user, true);
|
|
|
|
// update foleds
|
|
//DeleteNonexistentUsersAndGroups(rootPath);
|
|
}
|
|
#endregion
|
|
|
|
#region Secured Helicon Ape Groups
|
|
public override List<WebGroup> GetHeliconApeGroups(string siteId)
|
|
{
|
|
string rootPath = GetSiteContentPath(siteId);
|
|
List<WebGroup> groups = new List<WebGroup>();
|
|
|
|
// open groups file
|
|
string groupsPath = Path.Combine(rootPath, HtaccessFolder.HTGROUPS_FILE);
|
|
List<string> groupLines = HtaccessFolder.ReadLinesFile(groupsPath);
|
|
|
|
for (int i = 0; i < groupLines.Count; i++)
|
|
{
|
|
string groupLine = groupLines[i];
|
|
int colonIdx = groupLine.IndexOf(":");
|
|
if (colonIdx != -1)
|
|
{
|
|
string name = groupLine.Substring(0, colonIdx);
|
|
|
|
// add group to the collection
|
|
groups.Add(GetHeliconApeGroup(siteId, name));
|
|
}
|
|
} // end iterating groups
|
|
|
|
return groups;
|
|
}
|
|
|
|
public override WebGroup GetHeliconApeGroup(string siteId, string groupName)
|
|
{
|
|
string rootPath = GetSiteContentPath(siteId);
|
|
// open groups file
|
|
string groupsPath = Path.Combine(rootPath, HtaccessFolder.HTGROUPS_FILE);
|
|
List<string> groupLines = HtaccessFolder.ReadLinesFile(groupsPath);
|
|
|
|
WebGroup group = null;
|
|
for (int i = 0; i < groupLines.Count; i++)
|
|
{
|
|
string groupLine = groupLines[i];
|
|
int colonIdx = groupLine.IndexOf(":");
|
|
if (colonIdx != -1)
|
|
{
|
|
string name = groupLine.Substring(0, colonIdx);
|
|
string[] members = groupLine.Substring(colonIdx + 1).Split(' ');
|
|
|
|
if (String.Compare(groupName, name, true) == 0)
|
|
{
|
|
group = new WebGroup();
|
|
group.Name = groupName;
|
|
group.Users = members;
|
|
}
|
|
}
|
|
} // end iterating groups
|
|
|
|
return group;
|
|
}
|
|
|
|
public override void UpdateHeliconApeGroup(string siteId, WebGroup group)
|
|
{
|
|
UpdateHeliconApeGroup(siteId, group, false);
|
|
}
|
|
|
|
private void UpdateHeliconApeGroup(string siteId, WebGroup group, bool deleteGroup)
|
|
{
|
|
string rootPath = GetSiteContentPath(siteId);
|
|
|
|
if (group.Users == null)
|
|
group.Users = new string[] { };
|
|
|
|
List<string> updatedGroups = new List<string>();
|
|
|
|
// open groups file
|
|
string groupsPath = Path.Combine(rootPath, HtaccessFolder.HTGROUPS_FILE);
|
|
List<string> groupLines = HtaccessFolder.ReadLinesFile(groupsPath);
|
|
|
|
bool exists = false;
|
|
for (int i = 0; i < groupLines.Count; i++)
|
|
{
|
|
string groupLine = groupLines[i];
|
|
int colonIdx = groupLine.IndexOf(":");
|
|
if (colonIdx != -1)
|
|
{
|
|
string name = groupLine.Substring(0, colonIdx);
|
|
|
|
// add group to the collection
|
|
if (String.Compare(group.Name, name, true) == 0)
|
|
{
|
|
exists = true;
|
|
|
|
if (deleteGroup)
|
|
continue;
|
|
|
|
// update group members
|
|
groupLine = group.Name + ":" + String.Join(" ", group.Users);
|
|
}
|
|
}
|
|
|
|
updatedGroups.Add(groupLine);
|
|
} // end iterating groups
|
|
|
|
if (!exists && !deleteGroup)
|
|
updatedGroups.Add(group.Name + ":" + String.Join(" ", group.Users));
|
|
|
|
// save groups
|
|
HtaccessFolder.WriteLinesFile(groupsPath, updatedGroups);
|
|
}
|
|
|
|
public override void DeleteHeliconApeGroup(string siteId, string groupName)
|
|
{
|
|
string rootPath = GetSiteContentPath(siteId);
|
|
|
|
// delete group
|
|
WebGroup group = new WebGroup();
|
|
group.Name = groupName;
|
|
UpdateHeliconApeGroup(siteId, group, true);
|
|
|
|
// update foleds
|
|
//DeleteNonexistentUsersAndGroups(rootPath);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region FrontPage
|
|
|
|
public override bool IsFrontPageInstalled(string siteId)
|
|
{
|
|
using (ServerManager srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
return IsFrontPageInstalled(srvman, siteId);
|
|
}
|
|
}
|
|
|
|
private bool IsFrontPageInstalled(ServerManager srvman, string siteId)
|
|
{
|
|
// Get IIS web site id
|
|
string m_webSiteId = webObjectsSvc.GetWebSiteIdFromIIS(srvman, siteId, "W3SVC/{0}");
|
|
// site port
|
|
RegistryKey sitePortKey = Registry.LocalMachine.OpenSubKey(String.Format("{0}Port /LM/{1}:",
|
|
FRONTPAGE_PORT_REGLOC, m_webSiteId));
|
|
|
|
if (sitePortKey == null)
|
|
return false;
|
|
|
|
// get required keys
|
|
string keyAuthoring = (string)sitePortKey.GetValue("authoring");
|
|
string keyFrontPageRoot = (string)sitePortKey.GetValue("frontpageroot");
|
|
|
|
return (keyAuthoring != null && keyAuthoring.ToUpper() == "ENABLED" &&
|
|
keyFrontPageRoot != null && keyFrontPageRoot.IndexOf("\\50") != -1);
|
|
}
|
|
|
|
public override bool InstallFrontPage(string siteId, string username, string password)
|
|
{
|
|
// Ensure requested user account doesn't exist
|
|
if (SecurityUtils.UserExists(username, ServerSettings, UsersOU))
|
|
return false;
|
|
|
|
// Ensure a web site exists
|
|
if (!SiteExists(siteId))
|
|
return false;
|
|
|
|
// create user account
|
|
SystemUser user = new SystemUser
|
|
{
|
|
Name = username,
|
|
FullName = username,
|
|
Description = "WebsitePanel System Account",
|
|
Password = password,
|
|
PasswordCantChange = true,
|
|
PasswordNeverExpires = true,
|
|
AccountDisabled = false,
|
|
System = true,
|
|
};
|
|
|
|
// create in the system
|
|
SecurityUtils.CreateUser(user, ServerSettings, UsersOU, GroupsOU);
|
|
|
|
try
|
|
{
|
|
using (ServerManager srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
string cmdPath = null;
|
|
string cmdArgs = null;
|
|
//
|
|
string m_webSiteId = webObjectsSvc.GetWebSiteIdFromIIS(srvman, siteId, null);
|
|
|
|
// try to install FPSE2002
|
|
// add registry key for anonymous group if not exists
|
|
RegistryKey portsKey = Registry.LocalMachine.OpenSubKey(FRONTPAGE_ALLPORTS_REGLOC, true);
|
|
portsKey.SetValue("anonusergroupprefix", "anonfp");
|
|
|
|
#region Create anonymous group to get FPSE work
|
|
|
|
string groupName = "anonfp_" + m_webSiteId;
|
|
if (!SecurityUtils.GroupExists(groupName, ServerSettings, GroupsOU))
|
|
{
|
|
SystemGroup fpseGroup = new SystemGroup();
|
|
fpseGroup.Name = groupName;
|
|
fpseGroup.Description = "Anonymous FPSE group for " + siteId + " web site";
|
|
fpseGroup.Members = new string[] { username };
|
|
SecurityUtils.CreateGroup(fpseGroup, ServerSettings, UsersOU, GroupsOU);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Install FPSE 2002 to the website by owsadm.exe install command
|
|
|
|
cmdPath = Environment.ExpandEnvironmentVariables(FPSE2002_OWSADM_PATH);
|
|
cmdArgs = String.Format("-o install -p /LM/W3SVC/{0} -u {1}", m_webSiteId, username);
|
|
Log.WriteInfo("Command path: " + cmdPath);
|
|
Log.WriteInfo("Command path: " + cmdArgs);
|
|
Log.WriteInfo("FPSE2002 Install Log: " + FileUtils.ExecuteSystemCommand(cmdPath, cmdArgs));
|
|
|
|
#endregion
|
|
}
|
|
|
|
// Enable Windows Authentication mode
|
|
winAuthSvc.SetEnabled(siteId, true);
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.WriteError(ex);
|
|
// Signal to the client installation request has been failed.
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public override void UninstallFrontPage(string siteId, string username)
|
|
{
|
|
using (ServerManager srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
// Ensure a web site exists
|
|
if (!webObjectsSvc.SiteExists(srvman, siteId))
|
|
return;
|
|
|
|
try
|
|
{
|
|
string m_webSiteId = webObjectsSvc.GetWebSiteIdFromIIS(srvman, siteId, null);
|
|
|
|
// remove anonymous group
|
|
string groupName = "anonfp_" + m_webSiteId;
|
|
if (SecurityUtils.GroupExists(groupName, ServerSettings, GroupsOU))
|
|
SecurityUtils.DeleteGroup(groupName, ServerSettings, GroupsOU);
|
|
|
|
#region Trying to uninstall FPSE2002 from the web site
|
|
|
|
//
|
|
string cmdPath = null;
|
|
string cmdArgs = null;
|
|
|
|
cmdPath = Environment.ExpandEnvironmentVariables(FPSE2002_OWSADM_PATH);
|
|
cmdArgs = String.Format("-o fulluninstall -p /LM/W3SVC/{0}", m_webSiteId);
|
|
|
|
// launch system process
|
|
Log.WriteInfo("FPSE2002 Uninstall Log: " + FileUtils.ExecuteSystemCommand(cmdPath, cmdArgs));
|
|
|
|
#endregion
|
|
|
|
// delete user account
|
|
if (SecurityUtils.UserExists(username, ServerSettings, UsersOU))
|
|
SecurityUtils.DeleteUser(username, ServerSettings, UsersOU);
|
|
|
|
// Disable Windows Authentication mode
|
|
winAuthSvc.SetEnabled(siteId, false);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.WriteError(String.Format("FPSE2002 uninstall error. Web site: {0}.", siteId), ex);
|
|
}
|
|
}
|
|
}
|
|
|
|
public override bool IsFrontPageSystemInstalled()
|
|
{
|
|
// we will lookup in the registry for the required information
|
|
// check for FPSE 2002
|
|
RegistryKey keyFrontPage = Registry.LocalMachine.OpenSubKey(FRONTPAGE_2002_REGLOC);
|
|
if (keyFrontPage == null)
|
|
return false;
|
|
|
|
string[] subKeys = keyFrontPage.GetSubKeyNames();
|
|
if (subKeys != null && subKeys.Length > 0)
|
|
{
|
|
foreach (string key in subKeys)
|
|
{
|
|
if (key == IIs60.FRONTPAGE_2002_INSTALLED || key == IIs60.SHAREPOINT_INSTALLED)
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ColdFusion
|
|
|
|
public override void CreateCFVirtualDirectories(string siteId)
|
|
{
|
|
WebVirtualDirectory scriptsDirectory = new WebVirtualDirectory();
|
|
scriptsDirectory.Name = "CFIDE";
|
|
scriptsDirectory.ContentPath = CFScriptsDirectoryPath;
|
|
scriptsDirectory.EnableAnonymousAccess = true;
|
|
scriptsDirectory.EnableWindowsAuthentication = true;
|
|
scriptsDirectory.EnableBasicAuthentication = false;
|
|
scriptsDirectory.DefaultDocs = null; // inherit from service
|
|
scriptsDirectory.HttpRedirect = "";
|
|
scriptsDirectory.HttpErrors = null;
|
|
scriptsDirectory.MimeMaps = null;
|
|
|
|
if (!VirtualDirectoryExists(siteId, scriptsDirectory.Name))
|
|
{
|
|
CreateVirtualDirectory(siteId, scriptsDirectory);
|
|
}
|
|
|
|
WebVirtualDirectory flashRemotingDir = new WebVirtualDirectory();
|
|
flashRemotingDir.Name = "JRunScripts";
|
|
flashRemotingDir.ContentPath = CFFlashRemotingDirPath;
|
|
flashRemotingDir.EnableAnonymousAccess = true;
|
|
flashRemotingDir.EnableWindowsAuthentication = true;
|
|
flashRemotingDir.EnableBasicAuthentication = false;
|
|
flashRemotingDir.DefaultDocs = null; // inherit from service
|
|
flashRemotingDir.HttpRedirect = "";
|
|
flashRemotingDir.HttpErrors = null;
|
|
flashRemotingDir.MimeMaps = null;
|
|
|
|
if (!VirtualDirectoryExists(siteId, flashRemotingDir.Name))
|
|
{
|
|
CreateVirtualDirectory(siteId, flashRemotingDir);
|
|
}
|
|
}
|
|
|
|
public override void DeleteCFVirtualDirectories(string siteId)
|
|
{
|
|
DeleteVirtualDirectory(siteId, "CFIDE");
|
|
DeleteVirtualDirectory(siteId, "JRunScripts");
|
|
|
|
}
|
|
|
|
public bool ColdFusionDirectoriesAdded(ServerManager srvman, string siteId)
|
|
{
|
|
int identifier = 0;
|
|
|
|
WebVirtualDirectory[] dirs = GetVirtualDirectories(srvman, siteId);
|
|
|
|
foreach (WebVirtualDirectory dir in dirs)
|
|
{
|
|
if (dir.FullQualifiedPath.Equals("CFIDE") || dir.FullQualifiedPath.Equals("JRunScripts"))
|
|
identifier++;
|
|
}
|
|
return identifier.Equals(2);
|
|
}
|
|
|
|
protected override bool IsColdFusionEnabledOnSite(string siteId)
|
|
{
|
|
bool isCFenabled = false;
|
|
|
|
using (ServerManager srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
string ID = webObjectsSvc.GetWebSiteIdFromIIS(srvman, siteId, "{0}");
|
|
|
|
if (IsColdFusionSystemInstalled())
|
|
{
|
|
string pathWsConfigSettings = Path.Combine(GetColdFusionRootPath(), @"runtime\lib\wsconfig\wsconfig.properties");
|
|
StreamReader file = new StreamReader(pathWsConfigSettings);
|
|
string line = String.Empty;
|
|
int counter = 0;
|
|
while ((line = file.ReadLine()) != null)
|
|
{
|
|
if (line.Contains(String.Format("=IIS,{0},", ID)))
|
|
{
|
|
isCFenabled = true;
|
|
break;
|
|
}
|
|
counter++;
|
|
}
|
|
file.Close();
|
|
}
|
|
|
|
return isCFenabled;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region HostingServiceProvider methods
|
|
public override SettingPair[] GetProviderDefaultSettings()
|
|
{
|
|
List<SettingPair> allSettings = new List<SettingPair>();
|
|
|
|
using (ServerManager srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
allSettings.AddRange(extensionsSvc.GetISAPIExtensionsInstalled(srvman));
|
|
|
|
// add default web management settings
|
|
WebManagementServiceSettings wmSettings = GetWebManagementServiceSettings();
|
|
if (wmSettings != null)
|
|
{
|
|
allSettings.Add(new SettingPair("WmSvc.Port", wmSettings.Port));
|
|
allSettings.Add(new SettingPair("WmSvc.ServiceUrl", wmSettings.ServiceUrl));
|
|
allSettings.Add(new SettingPair("WmSvc.RequiresWindowsCredentials", wmSettings.RequiresWindowsCredentials.ToString()));
|
|
}
|
|
}
|
|
|
|
// return settings
|
|
return allSettings.ToArray();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Installs the provider.
|
|
/// </summary>
|
|
/// <returns>Error messsages if any specified.</returns>
|
|
public override string[] Install()
|
|
{
|
|
List<string> messages = new List<string>();
|
|
|
|
string[] cfgMsgs = webObjectsSvc.GrantConfigurationSectionAccess(INSTALL_SECTIONS_ALLOWED);
|
|
//
|
|
if (cfgMsgs.Length > 0)
|
|
{
|
|
messages.AddRange(cfgMsgs);
|
|
return messages.ToArray();
|
|
}
|
|
|
|
try
|
|
{
|
|
SecurityUtils.EnsureOrganizationalUnitsExist(ServerSettings, UsersOU, GroupsOU);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.WriteError(ex);
|
|
messages.Add(String.Format("Could not check/create Organizational Units: {0}", ex.Message));
|
|
return messages.ToArray();
|
|
}
|
|
|
|
// Create web group name.
|
|
if (String.IsNullOrEmpty(WebGroupName))
|
|
{
|
|
messages.Add("Web Group can not be blank");
|
|
}
|
|
else
|
|
{
|
|
try
|
|
{
|
|
// create group
|
|
if (!SecurityUtils.GroupExists(WebGroupName, ServerSettings, GroupsOU))
|
|
{
|
|
SystemGroup group = new SystemGroup();
|
|
group.Name = WebGroupName;
|
|
group.Members = new string[] { };
|
|
group.Description = "WebsitePanel System Group";
|
|
|
|
SecurityUtils.CreateGroup(group, ServerSettings, UsersOU, GroupsOU);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.WriteError(ex);
|
|
messages.Add(String.Format("There was an error while adding '{0}' group: {1}",
|
|
WebGroupName, ex.Message));
|
|
}
|
|
}
|
|
|
|
// Setting up shared iisAppObject pools.
|
|
try
|
|
{
|
|
WebAppPoolHelper aphl = new WebAppPoolHelper(ProviderSettings);
|
|
// Find shared pools
|
|
var sharedPools = Array.FindAll<WebAppPool>(aphl.SupportedAppPools.ToArray(),
|
|
x => aphl.isolation(x.Mode) == SiteAppPoolMode.Shared);
|
|
//
|
|
foreach (var item in sharedPools)
|
|
{
|
|
using (var srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
// Local variables
|
|
bool enable32BitAppOnWin64 = (aphl.dotNetVersion(item.Mode) == SiteAppPoolMode.dotNetFramework1) ? true : false;
|
|
//
|
|
if (srvman.ApplicationPools[item.Name] == null)
|
|
{
|
|
ApplicationPool pool = srvman.ApplicationPools.Add(item.Name);
|
|
//
|
|
pool.ManagedRuntimeVersion = aphl.aspnet_runtime(item.Mode);
|
|
pool.ManagedPipelineMode = aphl.runtime_pipeline(item.Mode);
|
|
pool.ProcessModel.IdentityType = ProcessModelIdentityType.NetworkService;
|
|
pool.AutoStart = true;
|
|
pool.Enable32BitAppOnWin64 = enable32BitAppOnWin64;
|
|
//
|
|
srvman.CommitChanges();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.WriteError(ex);
|
|
//
|
|
messages.Add(String.Format("There was an error while creating shared iisAppObject pools: {0}", ex.Message));
|
|
}
|
|
|
|
// Ensure logging settings are configured correctly on a web server level
|
|
try
|
|
{
|
|
webObjectsSvc.SetWebServerDefaultLoggingSettings(LogExtFileFlags.SiteName
|
|
| LogExtFileFlags.BytesRecv | LogExtFileFlags.BytesSent | LogExtFileFlags.Date);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.WriteError(ex);
|
|
//
|
|
messages.Add(String.Format(@"There was an error while configure web server's default
|
|
logging settings. Reason: {0}", ex.StackTrace));
|
|
}
|
|
|
|
// Ensure logging settings are configured correctly on a web server level
|
|
try
|
|
{
|
|
webObjectsSvc.SetWebServerDefaultLoggingSettings(LogExtFileFlags.SiteName
|
|
| LogExtFileFlags.BytesRecv | LogExtFileFlags.BytesSent | LogExtFileFlags.Date);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.WriteError(ex);
|
|
//
|
|
messages.Add(String.Format(@"There was an error while configure web server's default
|
|
logging settings. Reason: {0}", ex.StackTrace));
|
|
}
|
|
|
|
// Setup Web Deploy publishing settings and rules
|
|
SetupWebDeployPublishingOnServer(messages);
|
|
|
|
return messages.ToArray();
|
|
}
|
|
|
|
public const string WDeployEnabled = "WDeployEnabled";
|
|
public const string WDeployRepair = "WDeployRepair";
|
|
public const string WDeployAppHostConfigWriter = "WDeployAppHostConfigWriter";
|
|
public const string WDeployAppPoolConfigEditor = "WDeployAppPoolConfigEditor";
|
|
|
|
|
|
private void SetupWebDeployPublishingOnServer(List<string> messages)
|
|
{
|
|
if (IsWebDeployInstalled() == false
|
|
|| String.IsNullOrEmpty(ProviderSettings[WDeployEnabled]))
|
|
return;
|
|
//
|
|
var enableFeature = Convert.ToBoolean(ProviderSettings[WDeployEnabled]);
|
|
var repairFeature = Convert.ToBoolean(ProviderSettings[WDeployRepair]);
|
|
//
|
|
var appHostConfigWriter = "WDeployConfigWriter";
|
|
var appHostConfigWriterPassword = Guid.NewGuid().ToString();
|
|
//
|
|
var appPoolConfigEditor = "WDeployAdmin";
|
|
var appPoolConfigEditorPassword = Guid.NewGuid().ToString();
|
|
//
|
|
var appHostConfigFilePath = FileUtils.EvaluateSystemVariables(@"%WINDIR%\system32\inetsrv\config\applicationHost.config");
|
|
//
|
|
#region Repair feature
|
|
if (repairFeature == true && enableFeature == true)
|
|
{
|
|
// Cleanup NTFS permissions
|
|
SecurityUtils.RemoveNtfsPermissions(appHostConfigFilePath, appHostConfigWriter, ServerSettings, UsersOU, GroupsOU);
|
|
// Remove applicationHost.config writer account
|
|
SecurityUtils.DeleteUser(appHostConfigWriter, ServerSettings, UsersOU);
|
|
// Remove local admin user to recycle app pools
|
|
SecurityUtils.DeleteUser(appPoolConfigEditor, ServerSettings, UsersOU);
|
|
// Remove delegation rules if any
|
|
var moduleService = new DelegationRulesModuleService();
|
|
//
|
|
moduleService.RemoveDelegationRule("contentPath,iisApp", "{userScope}");
|
|
moduleService.RemoveDelegationRule("dbFullSql", "Data Source=");
|
|
moduleService.RemoveDelegationRule("dbMySql", "Server=");
|
|
moduleService.RemoveDelegationRule("createApp", "{userScope}");
|
|
moduleService.RemoveDelegationRule("setAcl", "{userScope}");
|
|
moduleService.RemoveDelegationRule("recycleApp", "{userScope}");
|
|
moduleService.RemoveDelegationRule("appPoolPipeline,appPoolNetFx", "{userScope}");
|
|
}
|
|
#endregion
|
|
|
|
// Create applicationHost.config writer account
|
|
#region appHostConfigWriter account provisioning
|
|
if (enableFeature == true)
|
|
{
|
|
//
|
|
if (SecurityUtils.UserExists(appHostConfigWriter, ServerSettings, UsersOU) == false)
|
|
{
|
|
//
|
|
try
|
|
{
|
|
SecurityUtils.CreateUser(new SystemUser
|
|
{
|
|
Name = appHostConfigWriter,
|
|
FullName = appHostConfigWriter,
|
|
Password = appHostConfigWriterPassword,
|
|
PasswordCantChange = true,
|
|
PasswordNeverExpires = true,
|
|
MemberOf = new string[] { },
|
|
Description = "Web Deploy applicationHost.config writer account",
|
|
},
|
|
ServerSettings,
|
|
UsersOU,
|
|
GroupsOU);
|
|
// Grant appropriate NTFS permissions
|
|
SecurityUtils.GrantNtfsPermissions(appHostConfigFilePath, appHostConfigWriter, NTFSPermission.Modify, true, true, ServerSettings, UsersOU, GroupsOU);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
var errorMessage = "Could not create applicationHost.config writer account";
|
|
//
|
|
Log.WriteError(errorMessage, ex);
|
|
//
|
|
messages.Add(errorMessage);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (SecurityUtils.UserExists(appHostConfigWriter, ServerSettings, UsersOU) == true)
|
|
{
|
|
//
|
|
try
|
|
{
|
|
// Remove NTFS permissions
|
|
SecurityUtils.RemoveNtfsPermissions(appHostConfigFilePath, appHostConfigWriter, ServerSettings, UsersOU, GroupsOU);
|
|
// Remove writer account
|
|
SecurityUtils.DeleteUser(appHostConfigWriter, ServerSettings, UsersOU);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
var errorMessage = "Could not remove applicationHost.config writer user account";
|
|
//
|
|
Log.WriteError(errorMessage, ex);
|
|
//
|
|
messages.Add(errorMessage);
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
// Create local admin user to recycle app pools
|
|
#region appPoolConfigEditor account provisioning
|
|
if (enableFeature)
|
|
{
|
|
//
|
|
if (SecurityUtils.UserExists(appPoolConfigEditor, ServerSettings, UsersOU) == false)
|
|
{
|
|
//
|
|
try
|
|
{
|
|
SecurityUtils.CreateUser(new SystemUser
|
|
{
|
|
Name = appPoolConfigEditor,
|
|
FullName = appPoolConfigEditor,
|
|
Password = appPoolConfigEditorPassword,
|
|
PasswordCantChange = true,
|
|
PasswordNeverExpires = true,
|
|
MemberOf = new string[] { "Administrators" },
|
|
Description = "Web Deploy AppPool configuration editor account",
|
|
},
|
|
ServerSettings,
|
|
UsersOU,
|
|
GroupsOU);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
var errorMessage = "Could not create application pool configuration editor account";
|
|
//
|
|
Log.WriteError(errorMessage, ex);
|
|
//
|
|
messages.Add(errorMessage);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (SecurityUtils.UserExists(appPoolConfigEditor, ServerSettings, UsersOU) == true)
|
|
{
|
|
//
|
|
try
|
|
{
|
|
// Remove appPool config editor account
|
|
SecurityUtils.DeleteUser(appPoolConfigEditor, ServerSettings, UsersOU);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
var errorMessage = "Could not remove applicationHost.config writer user account";
|
|
//
|
|
Log.WriteError(errorMessage, ex);
|
|
//
|
|
messages.Add(errorMessage);
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
// Add delegation rules
|
|
#region Delegation rules provisioning
|
|
if (enableFeature)
|
|
{
|
|
var moduleService = new DelegationRulesModuleService();
|
|
//
|
|
if (moduleService.DelegationRuleExists("contentPath,iisApp", "{userScope}") == false)
|
|
{
|
|
moduleService.AddDelegationRule("contentPath,iisApp", "{userScope}", "PathPrefix", "CurrentUser", String.Empty, String.Empty);
|
|
}
|
|
//
|
|
if (moduleService.DelegationRuleExists("dbFullSql", "Data Source=") == false)
|
|
{
|
|
moduleService.AddDelegationRule("dbFullSql", "Data Source=", "ConnectionString", "CurrentUser", String.Empty, String.Empty);
|
|
}
|
|
//
|
|
if (moduleService.DelegationRuleExists("dbMySql", "Server=") == false)
|
|
{
|
|
moduleService.AddDelegationRule("dbMySql", "Server=", "ConnectionString", "CurrentUser", String.Empty, String.Empty);
|
|
}
|
|
//
|
|
if (moduleService.DelegationRuleExists("createApp", "{userScope}") == false)
|
|
{
|
|
moduleService.AddDelegationRule("createApp", "{userScope}", "PathPrefix", "SpecificUser", appHostConfigWriter, appHostConfigWriterPassword);
|
|
}
|
|
//
|
|
if (moduleService.DelegationRuleExists("setAcl", "{userScope}") == false)
|
|
{
|
|
moduleService.AddDelegationRule("setAcl", "{userScope}", "PathPrefix", "CurrentUser", String.Empty, String.Empty);
|
|
}
|
|
//
|
|
if (moduleService.DelegationRuleExists("recycleApp", "{userScope}") == false)
|
|
{
|
|
moduleService.AddDelegationRule("recycleApp", "{userScope}", "PathPrefix", "SpecificUser", appPoolConfigEditor, appPoolConfigEditorPassword);
|
|
}
|
|
//
|
|
if (moduleService.DelegationRuleExists("appPoolPipeline,appPoolNetFx", "{userScope}") == false)
|
|
{
|
|
moduleService.AddDelegationRule("appPoolPipeline,appPoolNetFx", "{userScope}", "PathPrefix", "SpecificUser", appHostConfigWriter, appHostConfigWriterPassword);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var moduleService = new DelegationRulesModuleService();
|
|
//
|
|
moduleService.RemoveDelegationRule("contentPath,iisApp", "{userScope}");
|
|
moduleService.RemoveDelegationRule("dbFullSql", "Data Source=");
|
|
moduleService.RemoveDelegationRule("dbMySql", "Server=");
|
|
moduleService.RemoveDelegationRule("createApp", "{userScope}");
|
|
moduleService.RemoveDelegationRule("setAcl", "{userScope}");
|
|
moduleService.RemoveDelegationRule("recycleApp", "{userScope}");
|
|
moduleService.RemoveDelegationRule("appPoolPipeline,appPoolNetFx", "{userScope}");
|
|
}
|
|
#endregion
|
|
}
|
|
|
|
public override ServiceProviderItemBandwidth[] GetServiceItemsBandwidth(ServiceProviderItem[] items, DateTime since)
|
|
{
|
|
ServiceProviderItemBandwidth[] itemsBandwidth = new ServiceProviderItemBandwidth[items.Length];
|
|
|
|
// update items with diskspace
|
|
for (int i = 0; i < items.Length; i++)
|
|
{
|
|
ServiceProviderItem item = items[i];
|
|
|
|
// create new bandwidth object
|
|
itemsBandwidth[i] = new ServiceProviderItemBandwidth();
|
|
itemsBandwidth[i].ItemId = item.Id;
|
|
itemsBandwidth[i].Days = new DailyStatistics[0];
|
|
|
|
if (item is WebSite)
|
|
{
|
|
try
|
|
{
|
|
WebSite site = GetSite(item.Name);
|
|
string siteId = site[WebSite.IIS7_SITE_ID];
|
|
string logsPath = Path.Combine(site.LogsPath, siteId);
|
|
|
|
if (!Directory.Exists(logsPath))
|
|
continue;
|
|
|
|
// create parser object
|
|
// and update statistics
|
|
LogParser parser = new LogParser("Web", siteId, logsPath, "s-sitename");
|
|
parser.ParseLogs();
|
|
|
|
// get daily statistics
|
|
itemsBandwidth[i].Days = parser.GetDailyStatistics(since, new string[] { siteId });
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.WriteError(ex);
|
|
}
|
|
}
|
|
}
|
|
return itemsBandwidth;
|
|
}
|
|
|
|
|
|
public override ServiceProviderItemDiskSpace[] GetServiceItemsDiskSpace(ServiceProviderItem[] items)
|
|
{
|
|
List<ServiceProviderItemDiskSpace> itemsDiskspace = new List<ServiceProviderItemDiskSpace>();
|
|
|
|
// update items with diskspace
|
|
foreach (ServiceProviderItem item in items)
|
|
{
|
|
if (item is WebSite)
|
|
{
|
|
try
|
|
{
|
|
Log.WriteStart(String.Format("Calculating '{0}' site logs size", item.Name));
|
|
|
|
WebSite site = GetSite(item.Name);
|
|
//
|
|
string logsPath = Path.Combine(site.LogsPath, site[WebSite.IIS7_SITE_ID]);
|
|
|
|
// calculate disk space
|
|
ServiceProviderItemDiskSpace diskspace = new ServiceProviderItemDiskSpace();
|
|
diskspace.ItemId = item.Id;
|
|
diskspace.DiskSpace = -1 * FileUtils.CalculateFolderSize(logsPath);
|
|
itemsDiskspace.Add(diskspace);
|
|
|
|
Log.WriteEnd(String.Format("Calculating '{0}' site logs size", item.Name));
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.WriteError(ex);
|
|
}
|
|
}
|
|
}
|
|
return itemsDiskspace.ToArray();
|
|
}
|
|
|
|
#endregion
|
|
|
|
public new bool IsIISInstalled()
|
|
{
|
|
int value = 0;
|
|
RegistryKey root = Registry.LocalMachine;
|
|
RegistryKey rk = root.OpenSubKey("SOFTWARE\\Microsoft\\InetStp");
|
|
if (rk != null)
|
|
{
|
|
value = (int)rk.GetValue("MajorVersion", null);
|
|
rk.Close();
|
|
}
|
|
|
|
return value == 7;
|
|
}
|
|
|
|
public override bool IsInstalled()
|
|
{
|
|
return IsIISInstalled();
|
|
}
|
|
|
|
#region Remote Management Access
|
|
|
|
/// <summary>
|
|
/// Provides Windows or IIS Management Users identities credentials mode
|
|
/// </summary>
|
|
public string IdentityCredentialsMode
|
|
{
|
|
get { return ProviderSettings["WmSvc.CredentialsMode"]; }
|
|
}
|
|
|
|
public override bool CheckWebManagementAccountExists(string accountName)
|
|
{
|
|
// Preserve setting to restore it back
|
|
bool adEnabled = ServerSettings.ADEnabled;
|
|
// !!! Bypass AD for WMSVC as it requires full-qualified username to authenticate user
|
|
// against the web server
|
|
//ServerSettings.ADEnabled = false;
|
|
|
|
if (IdentityCredentialsMode == "IISMNGR")
|
|
{
|
|
if (ManagementAuthentication.GetUser(accountName) != null)
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
return SecurityUtils.UserExists(accountName, ServerSettings, String.Empty);
|
|
}
|
|
}
|
|
|
|
public override ResultObject CheckWebManagementPasswordComplexity(string accountPassword)
|
|
{
|
|
// Preserve setting to restore it back
|
|
bool adEnabled = ServerSettings.ADEnabled;
|
|
// !!! Bypass AD for WMSVC as it requires full-qualified username to authenticate user
|
|
// against the web server
|
|
//ServerSettings.ADEnabled = false;
|
|
|
|
//
|
|
ResultObject result = new ResultObject { IsSuccess = true };
|
|
|
|
//
|
|
if (IdentityCredentialsMode == "IISMNGR")
|
|
{
|
|
InvalidPasswordReason reason = ManagementAuthentication.IsPasswordStrongEnough(accountPassword);
|
|
//
|
|
if (reason != InvalidPasswordReason.NoError)
|
|
{
|
|
result.IsSuccess = false;
|
|
result.AddError(reason.ToString(), new Exception("Password complexity check failed"));
|
|
}
|
|
}
|
|
// Restore setting back
|
|
ServerSettings.ADEnabled = adEnabled;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
public override void GrantWebManagementAccess(string siteName, string accountName, string accountPassword)
|
|
{
|
|
// Remote Management Access feature requires Modify permissions on the web site's wwwroot folder
|
|
GrantWebManagementAccessInternally(siteName, accountName, accountPassword, NTFSPermission.Modify);
|
|
}
|
|
|
|
private void GrantWebManagementAccessInternally(string siteName, string accountName, string accountPassword, NTFSPermission permissions)
|
|
{
|
|
// Preserve setting to restore it back
|
|
bool adEnabled = ServerSettings.ADEnabled;
|
|
// !!! Bypass AD for WMSVC as it requires full-qualified username to authenticate user
|
|
// against the web server
|
|
//ServerSettings.ADEnabled = false;
|
|
|
|
//
|
|
string fqWebPath = String.Format("/{0}", siteName);
|
|
|
|
// Trace input parameters
|
|
Log.WriteInfo("Site Name: {0}; Account Name: {1}; Account Password: {2}; FqWebPath: {3};",
|
|
siteName, accountName, accountPassword, fqWebPath);
|
|
|
|
|
|
string contentPath = string.Empty;
|
|
using (ServerManager srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
WebSite site = webObjectsSvc.GetWebSiteFromIIS(srvman, siteName);
|
|
//
|
|
contentPath = webObjectsSvc.GetPhysicalPath(srvman, site);
|
|
//
|
|
Log.WriteInfo("Site Content Path: {0};", contentPath);
|
|
}
|
|
|
|
string FTPRoot = string.Empty;
|
|
string FTPDir = string.Empty;
|
|
|
|
|
|
if (contentPath.IndexOf("\\\\") != -1)
|
|
{
|
|
string[] Tmp = contentPath.Split('\\');
|
|
FTPRoot = "\\\\" + Tmp[2] + "\\" + Tmp[3];
|
|
FTPDir = contentPath.Replace(FTPRoot, "");
|
|
}
|
|
|
|
//
|
|
string accountNameSid = string.Empty;
|
|
|
|
|
|
//
|
|
if (IdentityCredentialsMode == "IISMNGR")
|
|
{
|
|
ManagementAuthentication.CreateUser(accountName, accountPassword);
|
|
}
|
|
else
|
|
{
|
|
// Create Windows user
|
|
SecurityUtils.CreateUser(
|
|
new SystemUser
|
|
{
|
|
Name = accountName,
|
|
FullName = accountName,
|
|
Description = "WMSVC Service Account created by WebsitePanel",
|
|
PasswordCantChange = true,
|
|
PasswordNeverExpires = true,
|
|
AccountDisabled = false,
|
|
Password = accountPassword,
|
|
System = true,
|
|
MsIIS_FTPDir = FTPDir,
|
|
MsIIS_FTPRoot = FTPRoot
|
|
},
|
|
ServerSettings,
|
|
UsersOU,
|
|
GroupsOU);
|
|
|
|
// Convert account name to the full-qualified one
|
|
accountName = GetFullQualifiedAccountName(accountName);
|
|
accountNameSid = GetFullQualifiedAccountNameSid(accountName);
|
|
//
|
|
Log.WriteInfo("FQ Account Name: {0};", accountName);
|
|
}
|
|
|
|
ManagementAuthorization.Grant(accountName, fqWebPath, false);
|
|
//
|
|
|
|
if (IdentityCredentialsMode == "IISMNGR")
|
|
{
|
|
SecurityUtils.GrantNtfsPermissionsBySid(contentPath, SystemSID.LOCAL_SERVICE, permissions, true, true);
|
|
}
|
|
else
|
|
{
|
|
SecurityUtils.GrantNtfsPermissions(contentPath, accountNameSid, NTFSPermission.Modify, true, true, ServerSettings, UsersOU, GroupsOU);
|
|
}
|
|
}
|
|
|
|
|
|
public override void ChangeWebManagementAccessPassword(string accountName, string accountPassword)
|
|
{
|
|
// Preserve setting to restore it back
|
|
bool adEnabled = ServerSettings.ADEnabled;
|
|
// !!! Bypass AD for WMSVC as it requires full-qualified username to authenticate user
|
|
// against the web server
|
|
//ServerSettings.ADEnabled = false;
|
|
|
|
// Trace input parameters
|
|
Log.WriteInfo("Account Name: {0}; Account Password: {1};", accountName, accountPassword);
|
|
|
|
if (IdentityCredentialsMode == "IISMNGR")
|
|
{
|
|
ManagementAuthentication.SetPassword(accountName, accountPassword);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
SystemUser user = SecurityUtils.GetUser(accountName, ServerSettings, String.Empty);
|
|
//
|
|
user.Password = accountPassword;
|
|
//
|
|
SecurityUtils.UpdateUser(user, ServerSettings, String.Empty, String.Empty);
|
|
}
|
|
// Restore setting back
|
|
ServerSettings.ADEnabled = adEnabled;
|
|
}
|
|
|
|
public override void RevokeWebManagementAccess(string siteName, string accountName)
|
|
{
|
|
// Preserve setting to restore it back
|
|
bool adEnabled = ServerSettings.ADEnabled;
|
|
// !!! Bypass AD for WMSVC as it requires full-qualified username to authenticate user
|
|
// against the web server
|
|
//ServerSettings.ADEnabled = false;
|
|
//
|
|
string fqWebPath = String.Format("/{0}", siteName);
|
|
// Trace input parameters
|
|
Log.WriteInfo("Site Name: {0}; Account Name: {1}; FqWebPath: {2};",
|
|
siteName, accountName, fqWebPath);
|
|
|
|
using (ServerManager srvman = webObjectsSvc.GetServerManager())
|
|
{
|
|
//
|
|
WebSite site = webObjectsSvc.GetWebSiteFromIIS(srvman, siteName);
|
|
//
|
|
string contentPath = webObjectsSvc.GetPhysicalPath(srvman, site);
|
|
//
|
|
Log.WriteInfo("Site Content Path: {0};", contentPath);
|
|
// Revoke access permissions
|
|
if (IdentityCredentialsMode == "IISMNGR")
|
|
{
|
|
ManagementAuthorization.Revoke(accountName, fqWebPath);
|
|
ManagementAuthentication.DeleteUser(accountName);
|
|
SecurityUtils.RemoveNtfsPermissionsBySid(contentPath, SystemSID.LOCAL_SERVICE);
|
|
}
|
|
else
|
|
{
|
|
if (adEnabled)
|
|
{
|
|
ManagementAuthorization.Revoke(GetFullQualifiedAccountName(accountName), fqWebPath);
|
|
SecurityUtils.RemoveNtfsPermissions(contentPath, accountName, ServerSettings, UsersOU, GroupsOU);
|
|
SecurityUtils.DeleteUser(accountName, ServerSettings, UsersOU);
|
|
}
|
|
else
|
|
{
|
|
ManagementAuthorization.Revoke(GetFullQualifiedAccountName(accountName), fqWebPath);
|
|
SecurityUtils.RemoveNtfsPermissions(contentPath, accountName, ServerSettings, String.Empty, String.Empty);
|
|
SecurityUtils.DeleteUser(accountName, ServerSettings, String.Empty);
|
|
}
|
|
}
|
|
// Restore setting back
|
|
ServerSettings.ADEnabled = adEnabled;
|
|
}
|
|
}
|
|
|
|
private void ReadWebDeployPublishingAccessDetails(WebVirtualDirectory iisObject)
|
|
{
|
|
iisObject.WebDeployPublishingAvailable = IsWebDeployInstalled() && IsWebManagementServiceInstalled();
|
|
// No way to find out Web Deploy Publishing Access password
|
|
//iisObject.
|
|
}
|
|
|
|
private bool IsWebDeployInstalled()
|
|
{
|
|
// TO-DO: Implement Web Deploy detection (x64/x86)
|
|
var isInstalled = false;
|
|
//
|
|
try
|
|
{
|
|
var msdeployRegKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\IIS Extensions\MSDeploy\2");
|
|
//
|
|
var keyValue = msdeployRegKey.GetValue("Install");
|
|
// We have found the required key in the registry hive
|
|
if (keyValue != null && keyValue.Equals(1))
|
|
{
|
|
isInstalled = true;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.WriteError("Could not retrieve Web Deploy key from the registry", ex);
|
|
}
|
|
//
|
|
return isInstalled;
|
|
}
|
|
|
|
private bool? isWmSvcInstalled;
|
|
|
|
protected void ReadWebManagementAccessDetails(ServerManager srvman, WebVirtualDirectory iisObject)
|
|
{
|
|
bool wmSvcAvailable = IsWebManagementServiceInstalled();
|
|
//
|
|
iisObject.SetValue<bool>(WebSite.WmSvcAvailable, wmSvcAvailable);
|
|
//
|
|
if (wmSvcAvailable)
|
|
{
|
|
//
|
|
iisObject.SetValue<bool>(
|
|
WebVirtualDirectory.WmSvcSiteEnabled,
|
|
IsWebManagementAccessEnabled(iisObject));
|
|
|
|
//
|
|
string fqWebPath = @"/" + iisObject.FullQualifiedPath;
|
|
//
|
|
Configuration config = srvman.GetAdministrationConfiguration();
|
|
ConfigurationSection authorizationSection = config.GetSection("system.webServer/management/authorization");
|
|
ConfigurationElementCollection authorizationRulesCollection = authorizationSection.GetCollection("authorizationRules");
|
|
|
|
ConfigurationElement scopeElement = FindElement(authorizationRulesCollection, "scope", "path", fqWebPath);
|
|
|
|
Log.WriteInfo("FQ WebPath: " + fqWebPath);
|
|
|
|
if (scopeElement != null)
|
|
{
|
|
ConfigurationElementCollection scopeCollection = scopeElement.GetCollection();
|
|
// Retrieve account name
|
|
if (scopeCollection.Count > 0)
|
|
{
|
|
/*
|
|
iisObject.SetValue<string>(
|
|
WebSite.WmSvcAccountName,
|
|
GetNonQualifiedAccountName((String)scopeCollection[0]["name"]));
|
|
*/
|
|
iisObject.SetValue<string>(
|
|
WebSite.WmSvcAccountName, (String)scopeCollection[0]["name"]);
|
|
//
|
|
iisObject.SetValue<string>(
|
|
WebSite.WmSvcServiceUrl, ProviderSettings["WmSvc.ServiceUrl"]);
|
|
//
|
|
iisObject.SetValue<string>(
|
|
WebSite.WmSvcServicePort, ProviderSettings["WmSvc.Port"]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
protected ConfigurationElement FindElement(ConfigurationElementCollection collection, string elementTagName, params string[] keyValues)
|
|
{
|
|
foreach (ConfigurationElement element in collection)
|
|
{
|
|
if (String.Equals(element.ElementTagName, elementTagName, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
bool matches = true;
|
|
for (int i = 0; i < keyValues.Length; i += 2)
|
|
{
|
|
object o = element.GetAttributeValue(keyValues[i]);
|
|
string value = null;
|
|
if (o != null)
|
|
{
|
|
value = o.ToString();
|
|
}
|
|
if (!String.Equals(value, keyValues[i + 1], StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
matches = false;
|
|
break;
|
|
}
|
|
}
|
|
if (matches)
|
|
{
|
|
return element;
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private bool IsWebManagementAccessEnabled(WebVirtualDirectory iisObject)
|
|
{
|
|
using (var serverManager = webObjectsSvc.GetServerManager())
|
|
{
|
|
//
|
|
string fqWebPath = String.Format("/{0}", iisObject.FullQualifiedPath);
|
|
//
|
|
Log.WriteInfo("FQ Web Path: " + fqWebPath);
|
|
//
|
|
Configuration config = serverManager.GetAdministrationConfiguration();
|
|
ConfigurationSection authorizationSection = config.GetSection("system.webServer/management/authorization");
|
|
ConfigurationElementCollection authorizationRulesCollection = authorizationSection.GetCollection("authorizationRules");
|
|
|
|
ConfigurationElement scopeElement = FindElement(authorizationRulesCollection, "scope", "path", fqWebPath);
|
|
|
|
if (scopeElement != null)
|
|
{
|
|
// At least one authorization rule exists
|
|
if (scopeElement.GetCollection().Count > 0)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
return false;
|
|
}
|
|
|
|
private bool IsWebManagementServiceInstalled()
|
|
{
|
|
if (!isWmSvcInstalled.HasValue)
|
|
{
|
|
try
|
|
{
|
|
// Software key has been found, so report the check as succeeded
|
|
if (PInvoke.RegistryHive.HKLM.SubKeyExists_x64(@"SOFTWARE\Microsoft\WebManagement\Server"))
|
|
{
|
|
// Make sure Enable Remote Connections flag is turned on.
|
|
int remoteConnEnabled = PInvoke.RegistryHive.HKLM.GetDwordSubKeyValue_x64(@"SOFTWARE\Microsoft\WebManagement\Server",
|
|
"EnableRemoteManagement");
|
|
//
|
|
if (remoteConnEnabled == 1)
|
|
isWmSvcInstalled = true;
|
|
}
|
|
else
|
|
isWmSvcInstalled = false;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.WriteError("Failed to determine whether Web Management Service is installed", ex);
|
|
}
|
|
}
|
|
|
|
// Service not installed
|
|
return isWmSvcInstalled.GetValueOrDefault();
|
|
}
|
|
|
|
protected WebManagementServiceSettings GetWebManagementServiceSettings()
|
|
{
|
|
WebManagementServiceSettings settings = null;
|
|
|
|
try
|
|
{
|
|
// Trying to retrieve Web Management Server key
|
|
if (PInvoke.RegistryHive.HKLM.SubKeyExists_x64(@"SOFTWARE\Microsoft\WebManagement\Server"))
|
|
{
|
|
settings = new WebManagementServiceSettings();
|
|
|
|
// port number
|
|
settings.Port = PInvoke.RegistryHive.HKLM.GetDwordSubKeyValue_x64(@"SOFTWARE\Microsoft\WebManagement\Server", "Port").ToString();
|
|
|
|
// service URL
|
|
settings.ServiceUrl = PInvoke.RegistryHive.HKLM.GetSubKeyValue_x64(@"SOFTWARE\Microsoft\WebManagement\Server", "IPAddress");
|
|
|
|
// credentials mode
|
|
settings.RequiresWindowsCredentials =
|
|
PInvoke.RegistryHive.HKLM.GetDwordSubKeyValue_x64(@"SOFTWARE\Microsoft\WebManagement\Server", "RequiresWindowsCredentials");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.WriteError("Failed to retrieve Web Management Service settings", ex);
|
|
}
|
|
//
|
|
return settings;
|
|
}
|
|
|
|
protected string GetFullQualifiedAccountName(string accountName)
|
|
{
|
|
//
|
|
if (!ServerSettings.ADEnabled)
|
|
return String.Format(@"{0}\{1}", Environment.MachineName, accountName);
|
|
|
|
if (accountName.IndexOf("\\") != -1)
|
|
return accountName; // already has domain information
|
|
|
|
// DO IT FOR ACTIVE DIRECTORY MODE ONLY
|
|
string domainName = null;
|
|
try
|
|
{
|
|
DirectoryContext objContext = new DirectoryContext(DirectoryContextType.Domain, ServerSettings.ADRootDomain);
|
|
Domain objDomain = Domain.GetDomain(objContext);
|
|
domainName = objDomain.Name;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.WriteError("Get domain name error", ex);
|
|
}
|
|
|
|
return domainName != null ? domainName + "\\" + accountName : accountName;
|
|
}
|
|
|
|
|
|
protected string GetFullQualifiedAccountNameSid(string accountName)
|
|
{
|
|
//
|
|
if (!ServerSettings.ADEnabled)
|
|
return String.Format(@"{0}\{1}", Environment.MachineName, accountName);
|
|
|
|
if (accountName.IndexOf("\\") != -1)
|
|
return accountName; // already has domain information
|
|
|
|
// DO IT FOR ACTIVE DIRECTORY MODE ONLY
|
|
string domainName = null;
|
|
try
|
|
{
|
|
DirectoryContext objContext = new DirectoryContext(DirectoryContextType.Domain, ServerSettings.ADRootDomain);
|
|
Domain objDomain = Domain.GetDomain(objContext);
|
|
domainName = objDomain.Name;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.WriteError("Get domain name error", ex);
|
|
}
|
|
|
|
return domainName != null ? domainName + "\\" + accountName : accountName;
|
|
}
|
|
#endregion
|
|
|
|
#region SSL
|
|
public override SSLCertificate generateCSR(SSLCertificate certificate)
|
|
{
|
|
var sslObjectService = new SSLModuleService();
|
|
//
|
|
sslObjectService.GenerateCsr(certificate);
|
|
|
|
return certificate;
|
|
|
|
}
|
|
|
|
public override SSLCertificate installCertificate(SSLCertificate certificate, WebSite website)
|
|
{
|
|
var sslObjectService = new SSLModuleService();
|
|
//
|
|
return sslObjectService.InstallCertificate(certificate, website);
|
|
}
|
|
|
|
public override List<SSLCertificate> getServerCertificates()
|
|
{
|
|
var sslObjectService = new SSLModuleService();
|
|
//
|
|
return sslObjectService.GetServerCertificates();
|
|
}
|
|
|
|
public override SSLCertificate installPFX(byte[] certificate, string password, WebSite website)
|
|
{
|
|
var sslObjectService = new SSLModuleService();
|
|
//
|
|
return sslObjectService.InstallPfx(certificate, password, website);
|
|
}
|
|
|
|
public override byte[] exportCertificate(string serialNumber, string password)
|
|
{
|
|
var sslObjectService = new SSLModuleService();
|
|
//
|
|
return sslObjectService.ExportPfx(serialNumber, password);
|
|
}
|
|
|
|
public override ResultObject DeleteCertificate(SSLCertificate certificate, WebSite website)
|
|
{
|
|
var sslObjectService = new SSLModuleService();
|
|
//
|
|
return sslObjectService.DeleteCertificate(certificate, website);
|
|
}
|
|
|
|
public override SSLCertificate ImportCertificate(WebSite website)
|
|
{
|
|
var sslObjectService = new SSLModuleService();
|
|
//
|
|
return sslObjectService.ImportCertificate(website);
|
|
}
|
|
|
|
public override bool CheckCertificate(WebSite webSite)
|
|
{
|
|
var sslObjectService = new SSLModuleService();
|
|
//
|
|
return sslObjectService.CheckCertificate(webSite);
|
|
}
|
|
#endregion
|
|
|
|
#region Web Platform Installer Application Gallery
|
|
|
|
// moved down to IIs60
|
|
|
|
#endregion
|
|
}
|
|
}
|