Changes to IIS70 provider, etc for changing PHP versions among installed versions. Mimics the behaviour of IIS PHP Manager and works with it, i.e. changes made in PHP Manager is visible in WSP and vice versa.

This commit is contained in:
Olov Karlsson 2014-10-03 10:18:33 +02:00
parent 2d48b7fb33
commit d7ac9fa36f
8 changed files with 266 additions and 44 deletions

View file

@ -0,0 +1,42 @@
// Copyright (c) 2014, Outercurve Foundation.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// - Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// - Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// - Neither the name of the Outercurve Foundation nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using System;
using System.Net;
using System.Text;
using System.Xml.Serialization;
namespace WebsitePanel.Providers.Web
{
public class PhpVersion
{
public string HandlerName { get; set; }
public string Version { get; set; }
public string ExecutionPath { get; set; }
}
}

View file

@ -81,6 +81,7 @@ namespace WebsitePanel.Providers.Web
private bool sharePointInstalled; private bool sharePointInstalled;
private bool iis7; private bool iis7;
private string consoleUrl; private string consoleUrl;
private string php5VersionsInstalled;
public string AnonymousUsername public string AnonymousUsername
{ {
@ -285,6 +286,12 @@ namespace WebsitePanel.Providers.Web
set { consoleUrl = value; } set { consoleUrl = value; }
} }
public string Php5VersionsInstalled
{
get { return php5VersionsInstalled; }
set { php5VersionsInstalled = value; }
}
#region Web Deploy Publishing Properties #region Web Deploy Publishing Properties
/// <summary> /// <summary>
/// Gets or sets Web Deploy publishing account name /// Gets or sets Web Deploy publishing account name

View file

@ -329,6 +329,7 @@
<Compile Include="WebAppGallery\GalleryApplication.cs" /> <Compile Include="WebAppGallery\GalleryApplication.cs" />
<Compile Include="WebAppGallery\GalleryCategory.cs" /> <Compile Include="WebAppGallery\GalleryCategory.cs" />
<Compile Include="WebAppGallery\GalleryErrors.cs" /> <Compile Include="WebAppGallery\GalleryErrors.cs" />
<Compile Include="Web\PhpVersion.cs" />
<Compile Include="Web\HtaccessFolder.cs" /> <Compile Include="Web\HtaccessFolder.cs" />
<Compile Include="Web\HttpError.cs" /> <Compile Include="Web\HttpError.cs" />
<Compile Include="Web\HttpHeader.cs" /> <Compile Include="Web\HttpHeader.cs" />

View file

@ -26,6 +26,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using System.Linq;
namespace WebsitePanel.Providers.Web.Handlers namespace WebsitePanel.Providers.Web.Handlers
{ {
using System; using System;
@ -241,5 +243,69 @@ namespace WebsitePanel.Providers.Web.Handlers
// //
return null; return null;
} }
internal void CopyInheritedHandlers(string siteName, string vDirPath)
{
if (string.IsNullOrEmpty(siteName))
{
return;
}
if (string.IsNullOrEmpty(vDirPath))
{
vDirPath = "/";
}
using (var srvman = GetServerManager())
{
var config = srvman.GetWebConfiguration(siteName, vDirPath);
var handlersSection = (HandlersSection)config.GetSection(Constants.HandlersSection, typeof(HandlersSection));
var handlersCollection = handlersSection.Handlers;
var list = new HandlerAction[handlersCollection.Count];
((System.Collections.ICollection) handlersCollection).CopyTo(list, 0);
handlersCollection.Clear();
foreach (var handler in list)
{
handlersCollection.AddCopy(handler);
}
srvman.CommitChanges();
}
}
internal void MoveHandlerToTop(string handlerName, string siteName, string vDirPath)
{
if (string.IsNullOrEmpty(siteName))
{
return;
}
if (string.IsNullOrEmpty(vDirPath))
{
vDirPath = "/";
}
using (var srvman = GetServerManager())
{
var config = srvman.GetWebConfiguration(siteName, vDirPath);
var handlersSection = (HandlersSection)config.GetSection(Constants.HandlersSection, typeof(HandlersSection));
var handlersCollection = handlersSection.Handlers;
var handlerElement = handlersCollection[handlerName];
handlersCollection.Remove(handlerElement);
handlersCollection.AddCopyAt(0, handlerElement);
srvman.CommitChanges();
}
}
} }
} }

View file

@ -28,6 +28,8 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Diagnostics;
using System.Linq;
using System.Management; using System.Management;
using System.DirectoryServices; using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory; using System.DirectoryServices.ActiveDirectory;
@ -711,8 +713,8 @@ namespace WebsitePanel.Providers.Web
if (!String.IsNullOrEmpty(AspPath) && String.Equals(AspPath, processor, StringComparison.InvariantCultureIgnoreCase)) if (!String.IsNullOrEmpty(AspPath) && String.Equals(AspPath, processor, StringComparison.InvariantCultureIgnoreCase))
virtualDir.AspInstalled = true; virtualDir.AspInstalled = true;
// Detect whether PHP 5 scripting is enabled //// Detect whether PHP 5 scripting is enabled (non fast_cgi)
if (!String.IsNullOrEmpty(PhpExecutablePath) && String.Equals(PhpExecutablePath, processor, StringComparison.InvariantCultureIgnoreCase)) if (PhpMode != Constants.PhpMode.FastCGI && !String.IsNullOrEmpty(PhpExecutablePath) && String.Equals(PhpExecutablePath, processor, StringComparison.InvariantCultureIgnoreCase))
virtualDir.PhpInstalled = PHP_5; virtualDir.PhpInstalled = PHP_5;
// Detect whether PHP 4 scripting is enabled // Detect whether PHP 4 scripting is enabled
@ -728,6 +730,17 @@ namespace WebsitePanel.Providers.Web
virtualDir.PerlInstalled = true; virtualDir.PerlInstalled = true;
} }
// Detect PHP 5 Fast_cgi version(s)
var activePhp5Handler = GetActivePhpHandlerName(srvman, virtualDir);
if (!string.IsNullOrEmpty(activePhp5Handler))
{
virtualDir.PhpInstalled = PHP_5 + "|" + activePhp5Handler;
var versions = GetPhpVersions(srvman, virtualDir);
// This versionstring is used in UI to view and change php5 version.
var versionString = string.Join("|", versions.Select(v => v.HandlerName + ";" + v.Version).ToArray());
virtualDir.Php5VersionsInstalled = versionString;
}
// //
string fqPath = virtualDir.FullQualifiedPath; string fqPath = virtualDir.FullQualifiedPath;
if (!fqPath.EndsWith(@"/")) if (!fqPath.EndsWith(@"/"))
@ -865,9 +878,31 @@ namespace WebsitePanel.Providers.Web
#endregion #endregion
#region PHP 5 script mappings #region PHP 5 script mappings
if (!String.IsNullOrEmpty(PhpExecutablePath) && File.Exists(PhpExecutablePath)) if (virtualDir.PhpInstalled.StartsWith(PHP_5))
{ {
if (virtualDir.PhpInstalled == PHP_5) if (PhpMode == Constants.PhpMode.FastCGI && virtualDir.PhpInstalled.Contains('|'))
{
var path = PhpExecutablePath;
var args = virtualDir.PhpInstalled.Split('|');
if (args.Count() > 1)
{
// Handler name is present, let us try to find the corresponding path to executable
var phpVersion = GetPhpVersions(virtualDir).SingleOrDefault(p => p.HandlerName == args[1]);
if (phpVersion != null)
{
path = phpVersion.ExecutionPath;
}
}
if (!String.IsNullOrEmpty(path) && File.Exists(path))
{
handlersSvc.CopyInheritedHandlers(((WebSite)virtualDir).SiteId, virtualDir.VirtualPath);
handlersSvc.MoveHandlerToTop(args[1], ((WebSite) virtualDir).SiteId, virtualDir.VirtualPath);
}
}
else
{
if (!String.IsNullOrEmpty(PhpExecutablePath) && File.Exists(PhpExecutablePath))
{ {
switch (PhpMode) switch (PhpMode)
{ {
@ -885,11 +920,20 @@ namespace WebsitePanel.Providers.Web
break; break;
} }
} }
}
}
else
{
if (PhpMode == Constants.PhpMode.FastCGI && GetPhpVersions(virtualDir).Any())
{
// Don't erase handler mappings, if we do, the virtualDir cannot see and choose what version of PHP to run later
}
else else
{ {
handlersSvc.RemoveScriptMaps(virtualDir, PHP_EXTENSIONS, PhpExecutablePath); handlersSvc.RemoveScriptMaps(virtualDir, PHP_EXTENSIONS, PhpExecutablePath);
} }
} }
// //
#endregion #endregion
@ -4436,6 +4480,60 @@ namespace WebsitePanel.Providers.Web
} }
#endregion
#region Php Management
protected PhpVersion[] GetPhpVersions(ServerManager srvman, WebVirtualDirectory virtualDir)
{
var config = srvman.GetWebConfiguration(((WebSite)virtualDir).SiteId, virtualDir.VirtualPath);
//var config = srvman.GetApplicationHostConfiguration();
var handlersSection = config.GetSection(Constants.HandlersSection);
var result = new List<PhpVersion>();
// Loop through available maps and fill installed processors
foreach (var handler in handlersSection.GetCollection())
{
if (string.Equals(handler["path"].ToString(), "*.php", StringComparison.OrdinalIgnoreCase))
{
var executable = handler["ScriptProcessor"].ToString().Split('|')[0];
if (string.Equals(handler["Modules"].ToString(), "FastCgiModule", StringComparison.OrdinalIgnoreCase) && File.Exists(executable))
{
var handlerName = handler["Name"].ToString();
result.Add(new PhpVersion() {HandlerName = handlerName, Version = GetPhpExecutableVersion(executable), ExecutionPath = handler["ScriptProcessor"].ToString()});
}
}
}
return result.ToArray();
}
protected PhpVersion[] GetPhpVersions(WebVirtualDirectory virtualDir)
{
using (var srvman = new ServerManager())
{
return GetPhpVersions(srvman, virtualDir);
}
}
protected string GetActivePhpHandlerName(ServerManager srvman, WebVirtualDirectory virtualDir)
{
var config = srvman.GetWebConfiguration(((WebSite)virtualDir).SiteId, virtualDir.VirtualPath);
var handlersSection = config.GetSection(Constants.HandlersSection);
// Find first handler for *.php
return (from handler in handlersSection.GetCollection()
where string.Equals(handler["path"].ToString(), "*.php", StringComparison.OrdinalIgnoreCase) && string.Equals(handler["Modules"].ToString(), "FastCgiModule", StringComparison.OrdinalIgnoreCase)
select handler["name"].ToString()
).FirstOrDefault();
}
private static string GetPhpExecutableVersion(string phpexePath)
{
return FileVersionInfo.GetVersionInfo(phpexePath).ProductVersion;
}
#endregion #endregion
} }
} }

View file

@ -30,8 +30,6 @@
<td class="Normal"> <td class="Normal">
<asp:DropDownList ID="ddlPhp" runat="server" CssClass="NormalTextBox" resourcekey="ddlPhp"> <asp:DropDownList ID="ddlPhp" runat="server" CssClass="NormalTextBox" resourcekey="ddlPhp">
<asp:ListItem Value="">None</asp:ListItem> <asp:ListItem Value="">None</asp:ListItem>
<asp:ListItem Value="4">4</asp:ListItem>
<asp:ListItem Value="5">5</asp:ListItem>
</asp:DropDownList> </asp:DropDownList>
</td> </td>
</tr> </tr>

View file

@ -30,6 +30,7 @@ using System;
using System.Data; using System.Data;
using System.Configuration; using System.Configuration;
using System.Collections; using System.Collections;
using System.Linq;
using System.Web; using System.Web;
using System.Web.Security; using System.Web.Security;
using System.Web.UI; using System.Web.UI;
@ -98,13 +99,23 @@ namespace WebsitePanel.Portal
if (!IIs7 || !PackagesHelper.CheckGroupQuotaEnabled(packageId, ResourceGroups.Web, Quotas.WEB_ASPNET40)) if (!IIs7 || !PackagesHelper.CheckGroupQuotaEnabled(packageId, ResourceGroups.Web, Quotas.WEB_ASPNET40))
ddlAspNet.Items.Remove(ddlAspNet.Items.FindByValue("4I")); ddlAspNet.Items.Remove(ddlAspNet.Items.FindByValue("4I"));
rowAspNet.Visible = ddlAspNet.Items.Count > 1;
// php // php
if (!PackagesHelper.CheckGroupQuotaEnabled(packageId, ResourceGroups.Web, Quotas.WEB_PHP4)) if (PackagesHelper.CheckGroupQuotaEnabled(packageId, ResourceGroups.Web, Quotas.WEB_PHP4))
ddlPhp.Items.Remove(ddlPhp.Items.FindByValue("4")); ddlPhp.Items.Add("4");
if (!PackagesHelper.CheckGroupQuotaEnabled(packageId, ResourceGroups.Web, Quotas.WEB_PHP5)) if (PackagesHelper.CheckGroupQuotaEnabled(packageId, ResourceGroups.Web, Quotas.WEB_PHP5))
ddlPhp.Items.Remove(ddlPhp.Items.FindByValue("5")); {
if (!string.IsNullOrEmpty(item.Php5VersionsInstalled))
{
// Add items from list
ddlPhp.Items.Remove(ddlPhp.Items.FindByValue(""));
ddlPhp.Items.AddRange(item.Php5VersionsInstalled.Split('|').Select(v => new ListItem(v.Split(';')[1], "5|" + v.Split(';')[0])).OrderBy(i => i.Text).ToArray());
}
else
{
ddlPhp.Items.Add("5");
}
}
Utils.SelectListItem(ddlPhp, item.PhpInstalled);
rowPhp.Visible = ddlPhp.Items.Count > 1; rowPhp.Visible = ddlPhp.Items.Count > 1;
rowPerl.Visible = PackagesHelper.CheckGroupQuotaEnabled(packageId, ResourceGroups.Web, Quotas.WEB_PERL); rowPerl.Visible = PackagesHelper.CheckGroupQuotaEnabled(packageId, ResourceGroups.Web, Quotas.WEB_PERL);

View file

@ -1,7 +1,6 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// This code was generated by a tool. // This code was generated by a tool.
// Runtime Version:2.0.50727.3053
// //
// Changes to this file may cause incorrect behavior and will be lost if // Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated. // the code is regenerated.