diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/Web/PhpVersion.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/Web/PhpVersion.cs
new file mode 100644
index 00000000..5648842e
--- /dev/null
+++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/Web/PhpVersion.cs
@@ -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; }
+ }
+}
diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/Web/WebVirtualDirectory.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/Web/WebVirtualDirectory.cs
index 912d58f6..244b8940 100644
--- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/Web/WebVirtualDirectory.cs
+++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/Web/WebVirtualDirectory.cs
@@ -81,6 +81,7 @@ namespace WebsitePanel.Providers.Web
private bool sharePointInstalled;
private bool iis7;
private string consoleUrl;
+ private string php5VersionsInstalled;
public string AnonymousUsername
{
@@ -285,7 +286,13 @@ namespace WebsitePanel.Providers.Web
set { consoleUrl = value; }
}
- #region Web Deploy Publishing Properties
+ public string Php5VersionsInstalled
+ {
+ get { return php5VersionsInstalled; }
+ set { php5VersionsInstalled = value; }
+ }
+
+ #region Web Deploy Publishing Properties
///
/// Gets or sets Web Deploy publishing account name
///
diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj b/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj
index 2ab48c12..3f7049a0 100644
--- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj
+++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj
@@ -329,6 +329,7 @@
+
diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Web.IIS70/Handlers/HandlersModuleService.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Web.IIS70/Handlers/HandlersModuleService.cs
index 12a7b902..d2a7c783 100644
--- a/WebsitePanel/Sources/WebsitePanel.Providers.Web.IIS70/Handlers/HandlersModuleService.cs
+++ b/WebsitePanel/Sources/WebsitePanel.Providers.Web.IIS70/Handlers/HandlersModuleService.cs
@@ -26,6 +26,8 @@
// (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.Linq;
+
namespace WebsitePanel.Providers.Web.Handlers
{
using System;
@@ -178,7 +180,7 @@ namespace WebsitePanel.Providers.Web.Handlers
}
}
- internal void InheritScriptMapsFromParent(string fqPath)
+ internal void InheritScriptMapsFromParent(string fqPath)
{
if (String.IsNullOrEmpty(fqPath))
return;
@@ -241,5 +243,69 @@ namespace WebsitePanel.Providers.Web.Handlers
//
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();
+ }
+ }
}
}
diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Web.IIS70/IIs70.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Web.IIS70/IIs70.cs
index 22f33a5b..bb0376a4 100644
--- a/WebsitePanel/Sources/WebsitePanel.Providers.Web.IIS70/IIs70.cs
+++ b/WebsitePanel/Sources/WebsitePanel.Providers.Web.IIS70/IIs70.cs
@@ -28,6 +28,8 @@
using System;
using System.Collections;
+using System.Diagnostics;
+using System.Linq;
using System.Management;
using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory;
@@ -280,7 +282,7 @@ namespace WebsitePanel.Providers.Web
Name = settings[Constants.IntegratedAspNet40Pool].Trim()
});
}
- #endregion
+ #endregion
#region Populate Dedicated Application Pools
// ASP.NET 1.1
@@ -711,9 +713,9 @@ namespace WebsitePanel.Providers.Web
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 5 scripting is enabled (non fast_cgi)
+ if (PhpMode != Constants.PhpMode.FastCGI && !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))
@@ -727,7 +729,18 @@ namespace WebsitePanel.Providers.Web
if (!String.IsNullOrEmpty(PerlPath) && String.Equals(PerlPath, processor, StringComparison.InvariantCultureIgnoreCase))
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;
if (!fqPath.EndsWith(@"/"))
@@ -865,32 +878,63 @@ namespace WebsitePanel.Providers.Web
#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);
- }
- }
- //
+ if (virtualDir.PhpInstalled.StartsWith(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)
+ {
+ 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
+ {
+ 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
+ {
+ handlersSvc.RemoveScriptMaps(virtualDir, PHP_EXTENSIONS, PhpExecutablePath);
+ }
+ }
+
+ //
#endregion
#region PHP 4 script mappings (IsapiModule only)
@@ -4437,5 +4481,59 @@ 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();
+
+ // 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
+ }
}
diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebSitesExtensionsControl.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebSitesExtensionsControl.ascx
index fbf46c81..d725cd82 100644
--- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebSitesExtensionsControl.ascx
+++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebSitesExtensionsControl.ascx
@@ -30,8 +30,6 @@
None
- 4
- 5
|
diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebSitesExtensionsControl.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebSitesExtensionsControl.ascx.cs
index 74a074e5..6db36a40 100644
--- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebSitesExtensionsControl.ascx.cs
+++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebSitesExtensionsControl.ascx.cs
@@ -30,6 +30,7 @@ using System;
using System.Data;
using System.Configuration;
using System.Collections;
+using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
@@ -98,13 +99,23 @@ namespace WebsitePanel.Portal
if (!IIs7 || !PackagesHelper.CheckGroupQuotaEnabled(packageId, ResourceGroups.Web, Quotas.WEB_ASPNET40))
ddlAspNet.Items.Remove(ddlAspNet.Items.FindByValue("4I"));
- rowAspNet.Visible = ddlAspNet.Items.Count > 1;
-
// php
- if (!PackagesHelper.CheckGroupQuotaEnabled(packageId, ResourceGroups.Web, Quotas.WEB_PHP4))
- ddlPhp.Items.Remove(ddlPhp.Items.FindByValue("4"));
- if (!PackagesHelper.CheckGroupQuotaEnabled(packageId, ResourceGroups.Web, Quotas.WEB_PHP5))
- ddlPhp.Items.Remove(ddlPhp.Items.FindByValue("5"));
+ if (PackagesHelper.CheckGroupQuotaEnabled(packageId, ResourceGroups.Web, Quotas.WEB_PHP4))
+ ddlPhp.Items.Add("4");
+ if (PackagesHelper.CheckGroupQuotaEnabled(packageId, ResourceGroups.Web, Quotas.WEB_PHP5))
+ {
+ 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;
rowPerl.Visible = PackagesHelper.CheckGroupQuotaEnabled(packageId, ResourceGroups.Web, Quotas.WEB_PERL);
diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebSitesExtensionsControl.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebSitesExtensionsControl.ascx.designer.cs
index a9216e87..48e610df 100644
--- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebSitesExtensionsControl.ascx.designer.cs
+++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebSitesExtensionsControl.ascx.designer.cs
@@ -1,10 +1,9 @@
//------------------------------------------------------------------------------
//
// 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
-// the code is regenerated.
+// the code is regenerated.
//
//------------------------------------------------------------------------------