PdIISManager

using System;
using System.Linq;
using System.Windows.Forms;
using System.Collections.Generic;
using Microsoft.Web.Administration;
namespace PdMagic.Windows
{
public class VirtualFolder
{
public VirtualFolder(string aAlias, string aPhysicalFolder)
{
Alias = aAlias;
PhysicalFolder = aPhysicalFolder;
}
public string Alias { get; set; }
public string PhysicalFolder { get; set; }
}
public class MimeEntry
{
public MimeEntry(string aExtension, string aMIMEType)
{
Extension = aExtension;
MimeType = aMIMEType;
}
public string Extension { get; set; }
public string MimeType { get; set; }
}
public class PdIISManager
{
private ServerManager mServerManager;
public PdIISManager( )
{
mServerManager = new ServerManager();
}
public void ReLoad()
{
mServerManager = new ServerManager();
}
public SiteCollection Sites
{
get { return mServerManager.Sites; }
}
public ApplicationPoolCollection ApplicationPools
{
get { return mServerManager.ApplicationPools; }
}
public void AddNewSite(string aName, string aFolder, List<string> aStatus)
{
aStatus.Add("NEW SITE");
try
{
// Create and add site
const string lProtocol = "http";
const string lBinding = "*:80:";
mServerManager.Sites.Add(aName, lProtocol, lBinding, aFolder);
mServerManager.CommitChanges();
aStatus.Add($"+ Name: ({aName})");
aStatus.Add($"+ Protocol: ({lProtocol}), binding: ({lBinding})");
}
catch (Exception lAddNewSite)
{
throw new Exception("AddNewSite", lAddNewSite);
}
}
public void DeleteSite(string aName, List<string> aStatus)
{
aStatus.Add("DELETE SITE");
try
{
var lSite = mServerManager.Sites[aName];
mServerManager.Sites.Remove(lSite);
mServerManager.CommitChanges();
aStatus.Add($"+ Name: ({aName})");
}
catch (Exception lDeleteSite)
{
throw new Exception( "DeleteSite", lDeleteSite);
}
}
public void VerifyDLLAllowed(string aName, string aDLLPath, string aDescription, List<string> aStatus)
{
aStatus.Add("NEW ISAPI CGI RESTRICTION");
const string lSection = "system.webServer/security/isapiCgiRestriction";
var lConfig = mServerManager.GetApplicationHostConfiguration();
var lIsapiCgiRestrictionSection = lConfig.GetSection(lSection);
ConfigurationElementCollection lIsapiCgiRestrictionCollection = lIsapiCgiRestrictionSection.GetCollection();
aStatus.Add( $"* Section: ({lSection})");
var lExists = lIsapiCgiRestrictionCollection.Any(
aConfigurationElement => aConfigurationElement.Attributes["path"].Value.Equals(aDLLPath));
if (lExists)
{
aStatus.Add($"= An element already exists that points to ({aDLLPath})");
}
else
{
ConfigurationElement lAddElement = lIsapiCgiRestrictionCollection.CreateElement("add");
lAddElement["groupId"] = aName;
lAddElement["path"] = aDLLPath;
lAddElement["allowed"] = true;
lAddElement["description"] = aDescription;
lIsapiCgiRestrictionCollection.Add(lAddElement);
mServerManager.CommitChanges();
aStatus.Add($"+ GroupId: ({lAddElement["groupId"]})");
aStatus.Add($"+ Path=({lAddElement["path"]})");
aStatus.Add($"+ Allowed=({lAddElement["allowed"]})");
aStatus.Add($"+ Description=({lAddElement["description"]})");
}
}
public void CreateISAPIHandler(string aSiteName, string aVirtualPath,string aHandlerName, string aDLLPath, List<string> aStatus)
{
aStatus.Add("ADD ISAPI HANDLER");
var lParams = $"(SiteName={aSiteName}, VirtualPath={aVirtualPath}, Handler={aHandlerName}, DllPath={aDLLPath})";
try
{
Configuration lSiteConfig;
ConfigurationSection lHandlersSection;
ConfigurationElementCollection lHandlersCollection;
bool lExists;
//var lSiteConfig = mServerManager.GetApplicationHostConfiguration();
try
{
lSiteConfig = mServerManager.GetWebConfiguration(aSiteName, aVirtualPath);
aStatus.Add($"* Site / Path: ({aSiteName}{aVirtualPath})");
}
catch (Exception lGetWebConfiguration)
{
throw new Exception("GetWebConfiguration()", lGetWebConfiguration);
}
try
{
const string lSection = "system.webServer/handlers";
const string lPolicy = "Read, Script, Execute";
lHandlersSection = lSiteConfig.GetSection(lSection);
lHandlersSection["accessPolicy"] = lPolicy;
aStatus.Add($"* Set {lSection}/accessPolicy to ({lPolicy})");
}
catch (Exception lGetSection)
{
throw new Exception("GetSection() and set accessPolicy", lGetSection);
}
try
{
lHandlersCollection = lHandlersSection.GetCollection();
}
catch (Exception lGetCollection)
{
throw new Exception("GetCollection()", lGetCollection);
}
try
{
lExists = lHandlersCollection.Any(
aConfigurationElement => aConfigurationElement.Attributes["name"].Value.Equals(aHandlerName));
}
catch (Exception lCheckExists)
{
throw new Exception("Check Handler Exists", lCheckExists);
}
if (lExists)
{
aStatus.Add($"= Handler: ({aHandlerName}) already exists");
}
else
{
try
{
ConfigurationElement lAddElement = lHandlersCollection.CreateElement("add");
lAddElement["name"] = aHandlerName;
lAddElement["path"] = "CrashMagicOnline_ISAPI.dll";
lAddElement["allowPathInfo"] = "true";
lAddElement["verb"] = "*";
lAddElement["modules"] = "IsapiModule";
lAddElement["scriptProcessor"] = aDLLPath;
lAddElement["resourceType"] = "File";
lAddElement["requireAccess"] = "Execute";
lAddElement["preCondition"] = "bitness32";
lHandlersCollection.Add(lAddElement);
mServerManager.CommitChanges();
aStatus.Add($"+ name: ({lAddElement["name"]})");
aStatus.Add($"+ path: ({ lAddElement["path"]})");
aStatus.Add($"+ allowPathInfo: ({ lAddElement["allowPathInfo"]})");
aStatus.Add($"+ verb: ({ lAddElement["verb"]})");
aStatus.Add($"+ modules: ({ lAddElement["modules"]})");
aStatus.Add($"+ scriptProcessor: ({ lAddElement["scriptProcessor"]})");
aStatus.Add($"+ resourceType: ({ lAddElement["resourceType"]})");
aStatus.Add($"+ requireAccess: ({ lAddElement["requireAccess"]})");
aStatus.Add($"+ preCondition: ({ lAddElement["preCondition"]})");
}
catch (Exception lAddHandler)
{
throw new Exception("Add Handler", lAddHandler);
}
}
}
catch (Exception lException)
{
throw new Exception($"CreateISAPIHandler{lParams}", lException);   
}
}
public void SetMaxAllowedContentLength(string aSiteName, int aLength, List<string> aStatus)
{
aStatus.Add("SET MAX ALLOWED CONTENT LENGTH");
const string lSectionPath = "system.webServer/security/requestFiltering";
var lStatus = new List<string>();
// Unlock section:
var lConf = mServerManager.GetApplicationHostConfiguration();
var lSection = lConf.RootSectionGroup.SectionGroups["system.webServer"].SectionGroups["security"].Sections["requestFiltering"];
lSection.OverrideModeDefault = "Allow";
mServerManager.CommitChanges();
aStatus.Add($"* Section: ({lSectionPath}) Set OverrideModeDefault to (Allow).");
// Set value:
var lConfig = mServerManager.GetWebConfiguration(aSiteName);
var lRequestFilteringSection = lConfig.GetSection(lSectionPath);
var lRequestLimitsElement = lRequestFilteringSection.GetChildElement("requestLimits");
var lOldLength = Convert.ToInt64(lRequestLimitsElement.GetAttributeValue("maxAllowedContentLength"));
if (lOldLength == aLength)
{
aStatus.Add($"= requestLimits/maxAllowedContentLength already set to ({lOldLength})");
}
else
{
lRequestLimitsElement.SetAttributeValue("maxAllowedContentLength", aLength);
mServerManager.CommitChanges();
aStatus.Add($"+ Set requestLimits/maxAllowedContentLength to ({lRequestLimitsElement.GetAttributeValue("maxAllowedContentLength")})");
}
}
public void SetServerRuntimeValues(string aSiteName, uint aUploadReadAheadSize, uint aMaxRequestEntityAllowed, List<string> aStatus)
{
aStatus.Add("SET SERVER RUNTIME PARAMETERS");
const string lSectionPath = "system.webServer/serverRuntime";
// Unlock section:
var lConf = mServerManager.GetApplicationHostConfiguration();
var lSection = lConf.RootSectionGroup.SectionGroups["system.webServer"].Sections["serverRuntime"];
lSection.OverrideModeDefault = "Allow";
mServerManager.CommitChanges();
aStatus.Add($"* Section ({lSectionPath}) Set OverrideModeDefault to (Allow).");
// Set value:
var lConfig = mServerManager.GetWebConfiguration(aSiteName);
var lServerRuntimeSection = lConfig.GetSection(lSectionPath);
var lOldReadAheadSize = Convert.ToInt64(lServerRuntimeSection.GetAttributeValue("uploadReadAheadSize"));
if (lOldReadAheadSize == aUploadReadAheadSize)
{
aStatus.Add($"= uploadReadAheadSize already set to ({lOldReadAheadSize})");
}
else
{
lServerRuntimeSection.SetAttributeValue("uploadReadAheadSize", aUploadReadAheadSize);
aStatus.Add($"+ Set uploadReadAheadSize: ({lServerRuntimeSection.GetAttributeValue("uploadReadAheadSize")})");
}
var lOldMaxRequestEntity = Convert.ToInt64(lServerRuntimeSection.GetAttributeValue("maxRequestEntityAllowed"));
if (lOldMaxRequestEntity == aMaxRequestEntityAllowed) {
aStatus.Add($"= uploadReadAheadSize already set to ({lOldMaxRequestEntity})");
}
else
{
lServerRuntimeSection.SetAttributeValue("maxRequestEntityAllowed", aMaxRequestEntityAllowed);
mServerManager.CommitChanges();
aStatus.Add($"+ Set maxRequestEntityAllowed: ({lServerRuntimeSection.GetAttributeValue("maxRequestEntityAllowed")})");
}
}
public void VerifyDefaultDocument(string aSiteName, string aVirtualPath, string aFileName, List<string> aStatus)
{
aStatus.Add("SET DEFAULT DOCUMENT");
const string lSectionPath = "system.webServer/defaultDocument";
var lConfig = mServerManager.GetWebConfiguration(aSiteName, aVirtualPath);
var lDefaultDocumentSection = lConfig.GetSection(lSectionPath);
lDefaultDocumentSection["enabled"] = true;
aStatus.Add($"* Section: ({lSectionPath}) Set enabled = true");
aStatus.Add($"* Site / Path: ({aSiteName}{aVirtualPath})");
var lExists = false;
var lFilesCollection = lDefaultDocumentSection.GetCollection("files");
foreach (var lDefaultPage in lFilesCollection)
{
if (aFileName.ToLower() == ((string)lDefaultPage["value"]).ToLower())
lExists = true;
}
if (lExists)
{
aStatus.Add($"= ({aFileName}) already exists as default");
}
else
{
ConfigurationElement lAddElement = lFilesCollection.CreateElement("add");
lAddElement["value"] = aFileName;
lFilesCollection.AddAt(0, lAddElement);
mServerManager.CommitChanges();
aStatus.Add($"+ Inserted ({aFileName}) as the first default document");
}
}
public bool MimeTypeRegistered(string aSiteName, string aVirtualPath, string aExtension, string aMimeType)
{
bool lExists = false;
if (aVirtualPath != "/")
lExists = MimeTypeRegistered(aSiteName, "/", aExtension, aMimeType);
if (!lExists)
{
var lVDirConfig = mServerManager.GetWebConfiguration(aSiteName, aVirtualPath);
var lStaticContentSection = lVDirConfig.GetSection("system.webServer/staticContent");
var lMimeMap = lStaticContentSection.GetCollection();
var lMt =
lMimeMap.FirstOrDefault(
aMapEntry => (string) aMapEntry.Attributes["fileExtension"].Value == aExtension);
lExists = lMt != null;
}
return lExists;
}
public void VerifyMimeType(string aSiteName, string aVirtualPath, string aExtension, string aMimeType, List<string> aStatus)
{
const string lSectionPath = "system.webServer/staticContent";
if (MimeTypeRegistered(aSiteName, aVirtualPath, aExtension, aMimeType))
{
aStatus.Add($"= Mime entry already exists for ({aExtension})");
}
else
{
var lVDirConfig = mServerManager.GetWebConfiguration(aSiteName, aVirtualPath);
var lStaticContentSection = lVDirConfig.GetSection(lSectionPath);
var lMimeMap = lStaticContentSection.GetCollection();
var lMimeMapElement = lMimeMap.CreateElement("mimeMap");
lMimeMapElement["fileExtension"] = aExtension;
lMimeMapElement["mimeType"] = aMimeType;
lMimeMap.Add(lMimeMapElement);
mServerManager.CommitChanges();
aStatus.Add($"+ Added mime type: ({aMimeType}) for ({aExtension})");
}
}
public void VerifyMimeTypes(string aSiteName, string aApplicationPath, List<MimeEntry> aMimeEntries, List<string> aStatus)
{
const string lSectionPath = "system.webServer/staticContent";
aStatus.Add("SET MIME TYPES");
aStatus.Add($"* Section: ({lSectionPath})");
aStatus.Add($"* Site / Path: ({aSiteName}{aApplicationPath})");
foreach (MimeEntry lEntry in aMimeEntries)
{
VerifyMimeType(aSiteName, aApplicationPath, lEntry.Extension, lEntry.MimeType, aStatus);
}
}
private static ConfigurationElement FindElement(ConfigurationElementCollection aCollection, string aElementTagName, params string[] aKeyValues)
{
foreach (ConfigurationElement lElement in aCollection)
{
if (String.Equals(lElement.ElementTagName, aElementTagName, StringComparison.OrdinalIgnoreCase))
{
bool lMatches = true;
for (int i = 0; i < aKeyValues.Length; i += 2)
{
object o = lElement.GetAttributeValue(aKeyValues[i]);
string lValue = null;
if (o != null)
{
lValue = o.ToString();
}
if (!String.Equals(lValue, aKeyValues[i + 1], StringComparison.OrdinalIgnoreCase))
{
lMatches = false;
break;
}
}
if (lMatches)
{
return lElement;
}
}
}
return null;
}
public void SetApplicationUser(string aSite, string aApplication, string aUserName, string aPassword, List<string> aStatus)
{
aStatus.Add("SET APPLICATION USER");
try
{
const string lSectionPath = "system.applicationHost/sites";
var lConfig = mServerManager.GetApplicationHostConfiguration();
var lSitesSection = lConfig.GetSection(lSectionPath);
var lSitesCollection = lSitesSection.GetCollection();
var lSiteElement = FindElement(lSitesCollection, "site", "name", aSite);
var lApplicationCollection = lSiteElement.GetCollection();
ConfigurationElement lApplicationElement = FindElement(lApplicationCollection, "application", "path", aApplication);
ConfigurationElementCollection lVirtualDirCollection = lApplicationElement.GetCollection();
ConfigurationElement lVirtualDirElement = FindElement(lVirtualDirCollection, "virtualDirectory", "path", @"/");
aStatus.Add($"* Application: ({aApplication})");
aStatus.Add($"* Site: ({aSite})");
if (lVirtualDirElement.Attributes["userName"].Value.Equals(aUserName))
{
aStatus.Add($"= UserName: ({lVirtualDirElement.Attributes["userName"].Value}) already set");
}
else
{
lVirtualDirElement.Attributes["userName"].Value = aUserName;
lVirtualDirElement.Attributes["password"].Value = aPassword;
aStatus.Add($"+ Set userName: ({lVirtualDirElement.Attributes["userName"].Value})");
aStatus.Add($"+ Set password: (***)");
}
}
catch (Exception lSetApplicationUser)
{
throw new Exception("SetApplicationUser", lSetApplicationUser);
}
}
public void AddNewApplication(string aSite, string aApplication, string aPath, List<string> aStatus)
{
aStatus.Add("ADD APPLICATION");
try
{
mServerManager.Sites[aSite].Applications.Add(aApplication, aPath);
mServerManager.CommitChanges();
aStatus.Add($"+ Site / Path: ({ aSite}{aPath})");
aStatus.Add($"+ Application: ({aApplication})"); 
}
catch (Exception lAddNewApplication)
{
throw new Exception("Add New Application", lAddNewApplication);
}
}
private void VerifyVirtualDirectory(string aSite, string aApplication, string aVirtualName, string aPhysicalDir, List<string> aStatus )
{
try
{
var lExists = false;
var lApplication = mServerManager.Sites[aSite].Applications[aApplication];
foreach (var lDirectory in lApplication.VirtualDirectories)
{
if (lDirectory.PhysicalPath.ToLower() == aPhysicalDir.ToLower())
lExists = true;
}
if (lExists)
{
aStatus.Add($"= Virtual directory ({aVirtualName}) already exists");
}
else
{
lApplication.VirtualDirectories.Add(aVirtualName, aPhysicalDir);
mServerManager.CommitChanges();
aStatus.Add($"+ Added virtual directory ({aVirtualName}={aPhysicalDir})");
}
}
catch (Exception lAddNewVirtualDirectory)
{
throw new Exception("Add New Virtual Directory ", lAddNewVirtualDirectory);
}
}
public void VerifyVirtualFolders( string aSiteName, string aApplicationPath, List<VirtualFolder> aFolders, List<string> aStatus)
{
aStatus.Add($"ADD VIRTUAL FOLDERS");
aStatus.Add($"* Site / Path: ({aSiteName}{aApplicationPath})");
foreach (VirtualFolder lVirtualFolder in aFolders)
{
VerifyVirtualDirectory( aSiteName, aApplicationPath, $"/{lVirtualFolder.Alias}",
lVirtualFolder.PhysicalFolder, aStatus);
}
}
public void SetUpApplicationPool(string aApplicationPoolName, string aUserName, string aPassword, List<string> aStatus)
{
aStatus.Add("PREPARE APPLICATION POOL");
try
{
aStatus.Add($"* Pool name: ({aApplicationPoolName})");
var lAppPool = mServerManager.ApplicationPools[aApplicationPoolName];
lAppPool.ManagedRuntimeVersion = "v4.0";
aStatus.Add($"+ Set ManagedRuntimeVersion: ({lAppPool.ManagedRuntimeVersion})");
lAppPool.ManagedPipelineMode = ManagedPipelineMode.Integrated;
aStatus.Add($"+ Set ManagedPipelineMode: ({lAppPool.ManagedPipelineMode})");
lAppPool.Enable32BitAppOnWin64 = true;
aStatus.Add($"+ Set Enable32BitAppOnWin64: ({lAppPool.Enable32BitAppOnWin64})");
lAppPool.AutoStart = true;
aStatus.Add($"+ Set AutoStart: ({lAppPool.AutoStart})");
lAppPool.ProcessModel.IdleTimeout = new TimeSpan(0, 360, 0);
aStatus.Add($"+ Set ProcessModel.IdleTimeout: ({lAppPool.ProcessModel.IdleTimeout})");
lAppPool.Recycling.DisallowOverlappingRotation = true;
aStatus.Add($"+ Set Recycling.DisallowoverlappingRotation: ({lAppPool.Recycling.DisallowOverlappingRotation})");
lAppPool.Recycling.PeriodicRestart.Time = new TimeSpan(0, 0, 0);
aStatus.Add($"+ Set Recycling.PeriodicRestart.Time: ({new TimeSpan(0, 0, 0)})");
lAppPool.Recycling.PeriodicRestart.Schedule.Clear();
lAppPool.Recycling.PeriodicRestart.Schedule.Add(new TimeSpan(3,0,0));
aStatus.Add($"+ Set Recycling.PeriodicRestart.Schedule: ({new TimeSpan(3,0,0)})");
if (aUserName != string.Empty)
{
lAppPool.ProcessModel.UserName = Environment.MachineName + "\\" + aUserName;
lAppPool.ProcessModel.IdentityType = ProcessModelIdentityType.SpecificUser;
lAppPool.ProcessModel.Password = aPassword;
aStatus.Add($"+ Set ProcessModelUserName: ({lAppPool.ProcessModel.UserName}) Password: (***)");
aStatus.Add($"+ Set IdentityType: (SpecificUser)");
}
else
{
aStatus.Add("* No User Name sent");
}
mServerManager.CommitChanges();
}
catch (Exception lSetUpApplicationPool)
{
throw new Exception("Set Up ApplicationPool", lSetUpApplicationPool);
}
}
public void AddNewApplicationPool(string aApplicationPoolName, List<string> aStatus)
{
aStatus.Add("ADD APPLICATION POOL");
try
{
mServerManager.ApplicationPools.Add(aApplicationPoolName);
mServerManager.CommitChanges();
aStatus.Add($"+ Pool name: ({aApplicationPoolName})");
}
catch (Exception lAddNewApplicationPool)
{
throw new Exception("Add New ApplicationPool", lAddNewApplicationPool);
}
}
public void DeleteApplicationPool(string aApplicationPoolName, List<string> aStatus)
{
aStatus.Add("DELETE APPLICATION POOL");
try
{
ApplicationPool lAppPool = mServerManager.ApplicationPools[aApplicationPoolName];
if (lAppPool == null)
{
throw new Exception("DeleteApplicationPool - Application pool not found");
}
ApplicationPoolCollection lAppColl = mServerManager.ApplicationPools;
lAppColl.Remove(lAppPool);
mServerManager.CommitChanges();
aStatus.Add($"+ Pool name: ({aApplicationPoolName})");
}
catch (Exception lDeleteApplication)
{
throw new Exception("Delete Application", lDeleteApplication);
}
}
public void AttachSiteToApplicationPool(string aSite, string aApplicationPath, string aApplicationPool, List<string> aStatus)
{
aStatus.Add("ADD SITE TO APPLICATION POOL");
try
{
mServerManager.Sites[aSite].Applications[aApplicationPath].ApplicationPoolName = aApplicationPool;
ApplicationPool lAppPool = mServerManager.ApplicationPools[aApplicationPool];
aStatus.Add($"+ Site: ({mServerManager.Sites[aSite].Name}) added to pool: ({lAppPool.Name})");
mServerManager.CommitChanges();
}
catch (Exception lAttachSiteToAppPool)
{
throw new Exception("Attach Site To Application Pool", lAttachSiteToAppPool);
}
}
}
}