merge commit

This commit is contained in:
robvde 2014-10-17 20:40:22 +08:00
commit 41a1b59c85
17 changed files with 668 additions and 183 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,7 +286,13 @@ namespace WebsitePanel.Providers.Web
set { consoleUrl = value; } set { consoleUrl = value; }
} }
#region Web Deploy Publishing Properties public string Php5VersionsInstalled
{
get { return php5VersionsInstalled; }
set { php5VersionsInstalled = value; }
}
#region Web Deploy Publishing Properties
/// <summary> /// <summary>
/// Gets or sets Web Deploy publishing account name /// Gets or sets Web Deploy publishing account name
/// </summary> /// </summary>

View file

@ -333,6 +333,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

@ -30,6 +30,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.DirectoryServices.ActiveDirectory; using System.DirectoryServices.ActiveDirectory;
using System.IO; using System.IO;
using System.Linq;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using WebsitePanel.Providers.FTP.IIs70; using WebsitePanel.Providers.FTP.IIs70;
@ -99,6 +100,20 @@ namespace WebsitePanel.Providers.FTP
{ {
get { return ProviderSettings["ADGroupsOU"]; } get { return ProviderSettings["ADGroupsOU"]; }
} }
protected string AdFtpRoot
{
get { return ProviderSettings["AdFtpRoot"]; }
}
protected Mode UserIsolationMode
{
get
{
var site = GetSite(ProviderSettings["SiteId"]);
return (Mode)Enum.Parse(typeof(Mode), site["UserIsolationMode"]);
}
}
#endregion #endregion
#region IFtpServer Members #region IFtpServer Members
@ -291,134 +306,275 @@ namespace WebsitePanel.Providers.FTP
this.ftpSitesService.DeleteSite(siteId); this.ftpSitesService.DeleteSite(siteId);
} }
/// <summary> /// <summary>
/// Checks whether account with given name exists. /// Checks whether account with given name exists.
/// </summary> /// </summary>
/// <param name="accountName">Account name to check.</param> /// <param name="accountName">Account name to check.</param>
/// <returns>true - if it exists; false - otherwise.</returns> /// <returns>true - if it exists; false - otherwise.</returns>
public bool AccountExists(string accountName) public bool AccountExists(string accountName)
{ {
if (String.IsNullOrEmpty(accountName)) if (String.IsNullOrEmpty(accountName))
{ {
return false; return false;
} }
// check acocunt on FTP server switch (UserIsolationMode)
bool ftpExists = this.ftpSitesService.VirtualDirectoryExists(this.SiteId, accountName); {
case Mode.ActiveDirectory:
return SecurityUtils.UserExists(accountName, ServerSettings, UsersOU);
// check account in the system default:
bool systemExists = SecurityUtils.UserExists(accountName, ServerSettings, UsersOU); // check acocunt on FTP server
return (ftpExists || systemExists); bool ftpExists = this.ftpSitesService.VirtualDirectoryExists(this.SiteId, accountName);
// check account in the system
bool systemExists = SecurityUtils.UserExists(accountName, ServerSettings, UsersOU);
return (ftpExists || systemExists);
}
} }
/// <summary> /// <summary>
/// Gets available ftp accounts. /// Gets available ftp accounts.
/// </summary> /// </summary>
/// <returns>List of avaialble accounts.</returns> /// <returns>List of avaialble accounts.</returns>
public FtpAccount[] GetAccounts() public FtpAccount[] GetAccounts()
{ {
List<FtpAccount> accounts = new List<FtpAccount>(); switch (UserIsolationMode)
{
case Mode.ActiveDirectory:
return SecurityUtils.GetUsers(ServerSettings, UsersOU).Select(GetAccount).ToArray();
default:
List<FtpAccount> accounts = new List<FtpAccount>();
foreach (string directory in this.ftpSitesService.GetVirtualDirectoriesNames(this.SiteId)) foreach (string directory in this.ftpSitesService.GetVirtualDirectoriesNames(this.SiteId))
{ {
// Skip root virtual directory // Skip root virtual directory
if (String.Equals(directory, "/")) if (String.Equals(directory, "/"))
continue; continue;
// //
accounts.Add(this.GetAccount(directory.Substring(1))); accounts.Add(this.GetAccount(directory.Substring(1)));
} }
return accounts.ToArray(); return accounts.ToArray();
}
} }
/// <summary> /// <summary>
/// Gets account with given name. /// Gets account with given name.
/// </summary> /// </summary>
/// <param name="accountName">Account's name to get.</param> /// <param name="accountName">Account's name to get.</param>
/// <returns>Ftp account.</returns> /// <returns>Ftp account.</returns>
public FtpAccount GetAccount(string accountName) public FtpAccount GetAccount(string accountName)
{ {
FtpAccount acc = new FtpAccount(); switch (UserIsolationMode)
acc.Name = accountName; {
this.FillFtpAccountFromIis(acc); case Mode.ActiveDirectory:
return acc; var user = SecurityUtils.GetUser(accountName, ServerSettings, UsersOU);
var path = Path.Combine(user.MsIIS_FTPRoot, user.MsIIS_FTPDir);
var permission = GetUserPermission(accountName, path);
var account = new FtpAccount()
{
CanRead = permission.Read,
CanWrite = permission.Write,
CreatedDate = user.CreatedDate,
Enabled = !user.AccountDisabled,
Folder = path,
GroupName = user.GroupName,
Name = user.Name
};
return account;
default:
FtpAccount acc = new FtpAccount();
acc.Name = accountName;
this.FillFtpAccountFromIis(acc);
return acc;
}
} }
/// <summary> protected UserPermission GetUserPermission(string accountName, string folder)
{
var userPermission = new UserPermission {AccountName = accountName};
return SecurityUtils.GetGroupNtfsPermissions(folder, new[] {userPermission}, ServerSettings, UsersOU, GroupsOU)[0];
}
/// <summary>
/// Creates ftp account under root ftp site. /// Creates ftp account under root ftp site.
/// </summary> /// </summary>
/// <param name="account">Ftp account to create.</param> /// <param name="account">Ftp account to create.</param>
public void CreateAccount(FtpAccount account) public void CreateAccount(FtpAccount account)
{ {
// Create user account. switch (UserIsolationMode)
SystemUser user = new SystemUser(); {
user.Name = account.Name; case Mode.ActiveDirectory:
user.FullName = account.Name; SecurityUtils.EnsureOrganizationalUnitsExist(ServerSettings, UsersOU, GroupsOU);
user.Description = "WebsitePanel System Account";
user.MemberOf = new string[] { FtpGroupName };
user.Password = account.Password;
user.PasswordCantChange = true;
user.PasswordNeverExpires = true;
user.AccountDisabled = !account.Enabled;
user.System = true;
// Create in the operating system. var systemUser = SecurityUtils.GetUser(account.Name, ServerSettings, UsersOU);
if (SecurityUtils.UserExists(user.Name, ServerSettings, UsersOU))
{
SecurityUtils.DeleteUser(user.Name, ServerSettings, UsersOU);
}
SecurityUtils.CreateUser(user, ServerSettings, UsersOU, GroupsOU);
// Prepare account's home folder. if (systemUser == null)
this.EnsureUserHomeFolderExists(account.Folder, account.Name, account.CanRead, account.CanWrite); {
systemUser = new SystemUser
{
Name = account.Name,
FullName = account.Name,
Password = account.Password,
PasswordCantChange = true,
PasswordNeverExpires = true,
System = true
};
// Future account will be given virtual directory under default ftp web site. SecurityUtils.CreateUser(systemUser, ServerSettings, UsersOU, GroupsOU);
this.ftpSitesService.CreateFtpAccount(this.SiteId, account); }
//
this.ftpSitesService.ConfigureConnectAs(account.Folder, this.SiteId, account.VirtualPath,
this.GetQualifiedAccountName(account.Name), account.Password, true);
}
/// <summary> UpdateAccount(account);
/// Updates ftp account.
/// </summary> break;
/// <param name="account">Accoun to update.</param>
default:
// Create user account.
SystemUser user = new SystemUser();
user.Name = account.Name;
user.FullName = account.Name;
user.Description = "WebsitePanel System Account";
user.MemberOf = new string[] {FtpGroupName};
user.Password = account.Password;
user.PasswordCantChange = true;
user.PasswordNeverExpires = true;
user.AccountDisabled = !account.Enabled;
user.System = true;
// Create in the operating system.
if (SecurityUtils.UserExists(user.Name, ServerSettings, UsersOU))
{
SecurityUtils.DeleteUser(user.Name, ServerSettings, UsersOU);
}
SecurityUtils.CreateUser(user, ServerSettings, UsersOU, GroupsOU);
// Prepare account's home folder.
this.EnsureUserHomeFolderExists(account.Folder, account.Name, account.CanRead, account.CanWrite);
// Future account will be given virtual directory under default ftp web site.
this.ftpSitesService.CreateFtpAccount(this.SiteId, account);
//
this.ftpSitesService.ConfigureConnectAs(account.Folder, this.SiteId, account.VirtualPath,
this.GetQualifiedAccountName(account.Name), account.Password, true);
break;
}
}
/// <summary>
/// Updates ftp account.
/// </summary>
/// <param name="account">Accoun to update.</param>
public void UpdateAccount(FtpAccount account) public void UpdateAccount(FtpAccount account)
{ {
// Change user account state and password (if required). var user = SecurityUtils.GetUser(account.Name, ServerSettings, UsersOU);
SystemUser user = SecurityUtils.GetUser(account.Name, ServerSettings, UsersOU);
user.Password = account.Password; switch (UserIsolationMode)
user.AccountDisabled = !account.Enabled; {
SecurityUtils.UpdateUser(user, ServerSettings, UsersOU, GroupsOU); case Mode.ActiveDirectory:
// Update iis configuration. var ftpRoot = AdFtpRoot.ToLower();
this.FillIisFromFtpAccount(account); var ftpDir = account.Folder.ToLower().Replace(ftpRoot, "");
var oldDir = user.MsIIS_FTPDir;
user.Password = account.Password;
user.PasswordCantChange = true;
user.PasswordNeverExpires = true;
user.Description = "WebsitePanel FTP Account with AD User Isolation";
user.MemberOf = new[] {FtpGroupName};
user.AccountDisabled = !account.Enabled;
user.MsIIS_FTPRoot = ftpRoot;
user.MsIIS_FTPDir = ftpDir;
user.System = true;
SecurityUtils.UpdateUser(user, ServerSettings, UsersOU, GroupsOU);
// Set NTFS permissions
var userPermission = GetUserPermission(account.Name, account.Folder);
// Do we need to change the NTFS permissions? i.e. is users home dir changed or are permissions changed?
if (oldDir != ftpDir || account.CanRead != userPermission.Read || account.CanWrite != userPermission.Write)
{
// First get sid of user account
var sid = SecurityUtils.GetAccountSid(account.Name, ServerSettings, UsersOU, GroupsOU);
// Remove the permissions set for this account on previous folder
SecurityUtils.RemoveNtfsPermissionsBySid(Path.Combine(ftpRoot, oldDir), sid);
// If no permissions is to be set, exit
if (!account.CanRead && !account.CanWrite)
{
return;
}
// Add the new permissions
var ntfsPermissions = account.CanRead ? NTFSPermission.Read : NTFSPermission.Write;
if (account.CanRead && account.CanWrite)
{
ntfsPermissions = NTFSPermission.Modify;
}
SecurityUtils.GrantNtfsPermissionsBySid(account.Folder, sid, ntfsPermissions, true, true);
}
break;
default:
// Change user account state and password (if required).
user.Password = account.Password;
user.AccountDisabled = !account.Enabled;
SecurityUtils.UpdateUser(user, ServerSettings, UsersOU, GroupsOU);
// Update iis configuration.
this.FillIisFromFtpAccount(account);
break;
}
} }
/// <summary> /// <summary>
/// Deletes account with given name. /// Deletes account with given name.
/// </summary> /// </summary>
/// <param name="accountName">Account's name to be deleted.</param> /// <param name="accountName">Account's name to be deleted.</param>
public void DeleteAccount(string accountName) public void DeleteAccount(string accountName)
{ {
string virtualDirectory = String.Format("/{0}", accountName); switch (UserIsolationMode)
string currentPhysicalPath = this.ftpSitesService.GetSitePhysicalPath(this.SiteId, virtualDirectory); {
case Mode.ActiveDirectory:
var account = GetAccount(accountName);
// Delete virtual directory // Remove the NTFS permissions first
this.ftpSitesService.DeleteFtpAccount(this.SiteId, virtualDirectory); SecurityUtils.RemoveNtfsPermissions(account.Folder, account.Name, ServerSettings, UsersOU, GroupsOU);
this.ftpSitesService.CommitChanges(); if (SecurityUtils.UserExists(accountName, ServerSettings, UsersOU))
{
SecurityUtils.DeleteUser(accountName, ServerSettings, UsersOU);
}
break;
// Remove permissions default:
RemoveFtpFolderPermissions(currentPhysicalPath, accountName); string virtualDirectory = String.Format("/{0}", accountName);
string currentPhysicalPath = this.ftpSitesService.GetSitePhysicalPath(this.SiteId, virtualDirectory);
// Delete system user account // Delete virtual directory
if (SecurityUtils.UserExists(accountName, ServerSettings, UsersOU)) this.ftpSitesService.DeleteFtpAccount(this.SiteId, virtualDirectory);
{
SecurityUtils.DeleteUser(accountName, ServerSettings, UsersOU); this.ftpSitesService.CommitChanges();
}
// Remove permissions
RemoveFtpFolderPermissions(currentPhysicalPath, accountName);
// Delete system user account
if (SecurityUtils.UserExists(accountName, ServerSettings, UsersOU))
{
SecurityUtils.DeleteUser(accountName, ServerSettings, UsersOU);
}
break;
}
} }
/// <summary> /// <summary>
/// Fills iis configuration from ftp account. /// Fills iis configuration from ftp account.
/// </summary> /// </summary>
/// <param name="ftpAccount">Ftp account to fill from.</param> /// <param name="ftpAccount">Ftp account to fill from.</param>
@ -519,6 +675,7 @@ namespace WebsitePanel.Providers.FTP
ftpSite.AllowAnonymous = iisFtpSite.Security.Authentication.AnonymousAuthentication.Enabled; ftpSite.AllowAnonymous = iisFtpSite.Security.Authentication.AnonymousAuthentication.Enabled;
ftpSite.AnonymousUsername = iisFtpSite.Security.Authentication.AnonymousAuthentication.UserName; ftpSite.AnonymousUsername = iisFtpSite.Security.Authentication.AnonymousAuthentication.UserName;
ftpSite.AnonymousUserPassword = iisFtpSite.Security.Authentication.AnonymousAuthentication.Password; ftpSite.AnonymousUserPassword = iisFtpSite.Security.Authentication.AnonymousAuthentication.Password;
ftpSite["UserIsolationMode"] = iisFtpSite.UserIsolation.Mode.ToString();
// Logging settings. // Logging settings.
ftpSite[FtpSite.MSFTP7_SITE_ID] = iisFtpSite.SiteServiceId; ftpSite[FtpSite.MSFTP7_SITE_ID] = iisFtpSite.SiteServiceId;
if (iisFtpSite.LogFile.Enabled) if (iisFtpSite.LogFile.Enabled)

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;
@ -178,7 +180,7 @@ namespace WebsitePanel.Providers.Web.Handlers
} }
} }
internal void InheritScriptMapsFromParent(string fqPath) internal void InheritScriptMapsFromParent(string fqPath)
{ {
if (String.IsNullOrEmpty(fqPath)) if (String.IsNullOrEmpty(fqPath))
return; return;
@ -241,5 +243,40 @@ 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();
}
}
} }
} }

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;
@ -280,7 +282,7 @@ namespace WebsitePanel.Providers.Web
Name = settings[Constants.IntegratedAspNet40Pool].Trim() Name = settings[Constants.IntegratedAspNet40Pool].Trim()
}); });
} }
#endregion #endregion
#region Populate Dedicated Application Pools #region Populate Dedicated Application Pools
// ASP.NET 1.1 // ASP.NET 1.1
@ -711,9 +713,9 @@ 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
if (!String.IsNullOrEmpty(Php4Path) && String.Equals(Php4Path, processor, StringComparison.InvariantCultureIgnoreCase)) 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)) if (!String.IsNullOrEmpty(PerlPath) && String.Equals(PerlPath, processor, StringComparison.InvariantCultureIgnoreCase))
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,32 +878,60 @@ 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('|'))
{ {
switch (PhpMode) var args = virtualDir.PhpInstalled.Split('|');
{
case Constants.PhpMode.FastCGI: if (args.Count() > 1)
handlersSvc.AddScriptMaps(virtualDir, PHP_EXTENSIONS, {
PhpExecutablePath, Constants.HandlerAlias.PHP_FASTCGI, Constants.FastCgiModule); // Handler name is present, use it to set choosen version
break; var handlerName = args[1];
case Constants.PhpMode.CGI:
handlersSvc.AddScriptMaps(virtualDir, PHP_EXTENSIONS, if (handlerName != GetActivePhpHandlerName(virtualDir))
PhpExecutablePath, Constants.HandlerAlias.PHP_CGI, Constants.CgiModule); {
break; // Only change handler if it is different from the current one
case Constants.PhpMode.ISAPI: handlersSvc.CopyInheritedHandlers(((WebSite)virtualDir).SiteId, virtualDir.VirtualPath);
handlersSvc.AddScriptMaps(virtualDir, PHP_EXTENSIONS, MakeHandlerActive(handlerName, virtualDir);
PhpExecutablePath, Constants.HandlerAlias.PHP_ISAPI, Constants.IsapiModule); }
break; }
} }
} else
else {
{ if (!String.IsNullOrEmpty(PhpExecutablePath) && File.Exists(PhpExecutablePath))
handlersSvc.RemoveScriptMaps(virtualDir, PHP_EXTENSIONS, 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 #endregion
#region PHP 4 script mappings (IsapiModule only) #region PHP 4 script mappings (IsapiModule only)
@ -4437,5 +4478,91 @@ namespace WebsitePanel.Providers.Web
#endregion #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 = webObjectsSvc.GetServerManager())
{
return GetPhpVersions(srvman, virtualDir);
}
}
protected string GetActivePhpHandlerName(WebVirtualDirectory virtualDir)
{
using (var srvman = webObjectsSvc.GetServerManager())
{
return GetActivePhpHandlerName(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();
}
protected static string GetPhpExecutableVersion(string phpexePath)
{
return FileVersionInfo.GetVersionInfo(phpexePath).ProductVersion;
}
protected void MakeHandlerActive(string handlerName, WebVirtualDirectory virtualDir)
{
using (var srvman = webObjectsSvc.GetServerManager())
{
var config = srvman.GetWebConfiguration(((WebSite)virtualDir).SiteId, virtualDir.VirtualPath);
var handlersSection = (HandlersSection)config.GetSection(Constants.HandlersSection, typeof(HandlersSection));
var handlersCollection = handlersSection.Handlers;
var handlerElement = handlersCollection[handlerName];
var activeHandlerElement = handlersCollection[GetActivePhpHandlerName(srvman, virtualDir)];
var activeHandlerIndex = handlersCollection.IndexOf(activeHandlerElement);
handlersCollection.Remove(handlerElement);
handlersCollection.AddCopyAt(activeHandlerIndex, handlerElement);
srvman.CommitChanges();
}
}
#endregion
}
} }

View file

@ -511,6 +511,8 @@ namespace WebsitePanel.Providers.Utils
user.PasswordCantChange = ((userFlags & ADAccountOptions.UF_PASSWD_CANT_CHANGE) != 0); user.PasswordCantChange = ((userFlags & ADAccountOptions.UF_PASSWD_CANT_CHANGE) != 0);
user.PasswordNeverExpires = ((userFlags & ADAccountOptions.UF_DONT_EXPIRE_PASSWD) != 0); user.PasswordNeverExpires = ((userFlags & ADAccountOptions.UF_DONT_EXPIRE_PASSWD) != 0);
user.AccountDisabled = ((userFlags & ADAccountOptions.UF_ACCOUNTDISABLE) != 0); user.AccountDisabled = ((userFlags & ADAccountOptions.UF_ACCOUNTDISABLE) != 0);
user.MsIIS_FTPDir = GetObjectProperty(objUser, "msIIS-FTPDir").ToString();
user.MsIIS_FTPRoot = GetObjectProperty(objUser, "msIIS-FTPRoot").ToString();
// get user groups // get user groups
user.MemberOf = GetUserGroups(objUser); user.MemberOf = GetUserGroups(objUser);
@ -727,6 +729,12 @@ namespace WebsitePanel.Providers.Utils
objUser.Properties["description"].Value = String.IsNullOrEmpty(user.Description) ? "WebsitePanel System Account" : user.Description; objUser.Properties["description"].Value = String.IsNullOrEmpty(user.Description) ? "WebsitePanel System Account" : user.Description;
if (user.MsIIS_FTPDir != string.Empty)
{
SetObjectProperty(objUser, "msIIS-FTPDir", user.MsIIS_FTPDir);
SetObjectProperty(objUser, "msIIS-FTPRoot", user.MsIIS_FTPRoot);
}
ADAccountOptions userFlags = ADAccountOptions.UF_NORMAL_ACCOUNT; ADAccountOptions userFlags = ADAccountOptions.UF_NORMAL_ACCOUNT;
if (user.PasswordCantChange) if (user.PasswordCantChange)

View file

@ -256,7 +256,10 @@
<data name="txtPublicSharedIP.Text" xml:space="preserve"> <data name="txtPublicSharedIP.Text" xml:space="preserve">
<value>Web Sites Public Shared Address:</value> <value>Web Sites Public Shared Address:</value>
</data> </data>
<data name="chkHeliconApeGlobalRegistration.Text"> <data name="chkHeliconApeGlobalRegistration.Text" xml:space="preserve">
<value xml:space="preserve">Register Helicon Ape module globally:</value> <value>Register Helicon Ape module globally:</value>
</data>
<data name="litPHP5Info.Text" xml:space="preserve">
<value>If any PHP5 FastCGI handlers are present on the server, the PHP 5.x Executable Path given above will be ignored and not used.</value>
</data> </data>
</root> </root>

View file

@ -112,10 +112,10 @@
<value>2.0</value> <value>2.0</value>
</resheader> </resheader>
<resheader name="reader"> <resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="chkBuildUncFilesPath.Text" xml:space="preserve"> <data name="chkBuildUncFilesPath.Text" xml:space="preserve">
<value>Yes</value> <value>Yes</value>
@ -138,4 +138,7 @@
<data name="Text.SelectSite" xml:space="preserve"> <data name="Text.SelectSite" xml:space="preserve">
<value>&lt;Select FTP Site&gt;</value> <value>&lt;Select FTP Site&gt;</value>
</data> </data>
<data name="lblAdFtpRoot.Text" xml:space="preserve">
<value>FTP RootDir:</value>
</data>
</root> </root>

View file

@ -291,6 +291,11 @@
</asp:DropDownList> </asp:DropDownList>
</td> </td>
</tr> </tr>
<tr>
<td colspan="2" class="Normal">
<asp:Literal ID="litPHP5Info" runat="server" meta:resourcekey="litPHP5Info" Text="If any PHP5 FastCGI handlers are present on the server, the PHP 5.x Executable Path given above will be ignored and not used."></asp:Literal>
</td>
</tr>
<tr> <tr>
<td class="Normal" valign="top"> <td class="Normal" valign="top">
<asp:Label runat="server" meta:resourcekey="perlPathLabel" Text="Perl Executable Path:"></asp:Label> <asp:Label runat="server" meta:resourcekey="perlPathLabel" Text="Perl Executable Path:"></asp:Label>

View file

@ -490,6 +490,15 @@ namespace WebsitePanel.Portal.ProviderControls {
/// </remarks> /// </remarks>
protected global::System.Web.UI.WebControls.DropDownList ddlPhpMode; protected global::System.Web.UI.WebControls.DropDownList ddlPhpMode;
/// <summary>
/// litPHP5Info control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.Literal litPHP5Info;
/// <summary> /// <summary>
/// perlPath control. /// perlPath control.
/// </summary> /// </summary>

View file

@ -1,45 +1,61 @@
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="MSFTP70_Settings.ascx.cs" Inherits="WebsitePanel.Portal.ProviderControls.MSFTP70_Settings" %> <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="MSFTP70_Settings.ascx.cs" Inherits="WebsitePanel.Portal.ProviderControls.MSFTP70_Settings" %>
<%@ Register Src="Common_ActiveDirectoryIntegration.ascx" TagName="ActiveDirectoryIntegration" TagPrefix="uc1" %> <%@ Register Src="Common_ActiveDirectoryIntegration.ascx" TagName="ActiveDirectoryIntegration" TagPrefix="uc1" %>
<%@ Register Src="../UserControls/SelectIPAddress.ascx" TagName="SelectIPAddress" TagPrefix="uc1" %> <%@ Register Src="../UserControls/SelectIPAddress.ascx" TagName="SelectIPAddress" TagPrefix="uc1" %>
<table cellpadding="4" cellspacing="0" width="100%"> <table width="100%">
<tr> <tr>
<td class="Normal" width="200" nowrap> <td class="SubHead" width="150">
<asp:Label ID="lblSharedIP" runat="server" meta:resourcekey="lblSharedIP" Text="Web Sites Shared IP Address:"></asp:Label> <asp:Label ID="lblSharedIP" runat="server" meta:resourcekey="lblSharedIP" Text="Web Sites Shared IP Address:"></asp:Label>
</td> </td>
<td width="100%"> <td class="Normal">
<uc1:SelectIPAddress ID="ipAddress" runat="server" ServerIdParam="ServerID" /> <uc1:SelectIPAddress ID="ipAddress" runat="server" ServerIdParam="ServerID" />
</td>
</tr>
<tr>
<td class="SubHead" width="200" nowrap>
<asp:Label ID="lblSite" runat="server" meta:resourcekey="lblSite" Text="FTP Accounts Site:"></asp:Label>
</td>
<td width="100%">
<asp:TextBox ID="txtSiteId" runat="server" CssClass="NormalTextBox" Width="200px"></asp:TextBox>
</td> </td>
</tr> </tr>
<tr> </table>
<td class="SubHead"> <asp:UpdatePanel runat="server" UpdateMode="Conditional">
<asp:Label ID="lblGroupName" runat="server" meta:resourcekey="lblGroupName" Text="FTP Users Group Name:"></asp:Label> <ContentTemplate>
</td> <table width="100%">
<td class="Normal"> <tr>
<td class="SubHead" width="150">
<asp:Label ID="lblSite" runat="server" meta:resourcekey="lblSite" Text="FTP Accounts Site:"></asp:Label>
</td>
<td class="Normal">
<asp:DropDownList runat="server" ID="ddlSite" AutoPostBack="True" OnSelectedIndexChanged="ddlSite_SelectedIndexChanged" />
</td>
</tr>
<tr runat="server" id="FtpRootRow" visible="False">
<td class="SubHead">
<asp:Label ID="lblAdFtpRoot" runat="server" meta:resourcekey="lblAdFtpRoot" Text="FTP RootDir:"></asp:Label>
</td>
<td class="Normal">
<asp:TextBox ID="txtAdFtpRoot" runat="server" CssClass="NormalTextBox" Width="200px"></asp:TextBox>
<asp:RequiredFieldValidator runat="server" ID="txtAdFtpRootReqValidator" ControlToValidate="txtAdFtpRoot" Enabled="False" ErrorMessage="*"></asp:RequiredFieldValidator>
</td>
</tr>
</table>
</ContentTemplate>
</asp:UpdatePanel>
<table width="100%">
<tr>
<td class="SubHead" width="150">
<asp:Label ID="lblGroupName" runat="server" meta:resourcekey="lblGroupName" Text="FTP Users Group Name:"></asp:Label>
</td>
<td class="Normal">
<asp:TextBox ID="txtFtpGroupName" runat="server" CssClass="NormalTextBox" Width="200px"></asp:TextBox></td> <asp:TextBox ID="txtFtpGroupName" runat="server" CssClass="NormalTextBox" Width="200px"></asp:TextBox></td>
</tr> </tr>
<tr> <tr>
<td class="SubHead"> <td class="SubHead">
<asp:Label ID="lblBuildUncFilesPath" runat="server" meta:resourcekey="lblBuildUncFilesPath" Text="Build UNC Path to Space Files:"></asp:Label> <asp:Label ID="lblBuildUncFilesPath" runat="server" meta:resourcekey="lblBuildUncFilesPath" Text="Build UNC Path to Space Files:"></asp:Label>
</td>
<td>
<asp:CheckBox ID="chkBuildUncFilesPath" runat="server" meta:resourcekey="chkBuildUncFilesPath" Text="Yes" />
</td>
</tr>
<tr>
<td class="SubHead">
<asp:Label ID="lblADIntegration" runat="server" meta:resourcekey="lblADIntegration" Text="Active Directory Integration:"></asp:Label>
</td>
<td class="Normal">
<uc1:ActiveDirectoryIntegration ID="ActiveDirectoryIntegration" runat="server" />
</td> </td>
</tr> <td>
</table> <asp:CheckBox ID="chkBuildUncFilesPath" runat="server" meta:resourcekey="chkBuildUncFilesPath" Text="Yes" />
</td>
</tr>
<tr>
<td class="SubHead">
<asp:Label ID="lblADIntegration" runat="server" meta:resourcekey="lblADIntegration" Text="Active Directory Integration:"></asp:Label>
</td>
<td class="Normal">
<uc1:ActiveDirectoryIntegration ID="ActiveDirectoryIntegration" runat="server" />
</td>
</tr>
</table>

View file

@ -27,10 +27,12 @@
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using System; using System;
using System.Collections.Generic;
using System.Data; using System.Data;
using System.Configuration; using System.Configuration;
using System.Collections; using System.Collections;
using System.Collections.Specialized; using System.Collections.Specialized;
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;
@ -51,7 +53,8 @@ namespace WebsitePanel.Portal.ProviderControls
{ {
int selectedAddressid = this.FindAddressByText(settings["SharedIP"]); int selectedAddressid = this.FindAddressByText(settings["SharedIP"]);
ipAddress.AddressId = (selectedAddressid > 0) ? selectedAddressid : 0; ipAddress.AddressId = (selectedAddressid > 0) ? selectedAddressid : 0;
txtSiteId.Text = settings["SiteId"]; BindSiteId(settings);
txtAdFtpRoot.Text = settings["AdFtpRoot"];
txtFtpGroupName.Text = settings["FtpGroupName"]; txtFtpGroupName.Text = settings["FtpGroupName"];
chkBuildUncFilesPath.Checked = Utils.ParseBool(settings["BuildUncFilesPath"], false); chkBuildUncFilesPath.Checked = Utils.ParseBool(settings["BuildUncFilesPath"], false);
ActiveDirectoryIntegration.BindSettings(settings); ActiveDirectoryIntegration.BindSettings(settings);
@ -75,7 +78,11 @@ namespace WebsitePanel.Portal.ProviderControls
{ {
settings["SharedIP"] = String.Empty; settings["SharedIP"] = String.Empty;
} }
settings["SiteId"] = txtSiteId.Text.Trim(); settings["SiteId"] = ddlSite.SelectedValue;
if (!string.IsNullOrWhiteSpace(txtAdFtpRoot.Text))
{
settings["AdFtpRoot"] = txtAdFtpRoot.Text.Trim();
}
settings["FtpGroupName"] = txtFtpGroupName.Text.Trim(); settings["FtpGroupName"] = txtFtpGroupName.Text.Trim();
settings["BuildUncFilesPath"] = chkBuildUncFilesPath.Checked.ToString(); settings["BuildUncFilesPath"] = chkBuildUncFilesPath.Checked.ToString();
ActiveDirectoryIntegration.SaveSettings(settings); ActiveDirectoryIntegration.SaveSettings(settings);
@ -92,5 +99,31 @@ namespace WebsitePanel.Portal.ProviderControls
} }
return 0; return 0;
} }
private void BindSiteId(StringDictionary settings)
{
var sites = ES.Services.FtpServers.GetFtpSites(PanelRequest.ServiceId);
foreach (var site in sites)
{
var item = new ListItem(site.Name + " (User Isolation Mode: " + site["UserIsolationMode"] + ")", site.Name);
if (item.Value == settings["SiteId"])
{
item.Selected = true;
}
ddlSite.Items.Add(item);
}
ddlSite_SelectedIndexChanged(this, null);
}
protected void ddlSite_SelectedIndexChanged(object sender, EventArgs e)
{
var isActiveDirectoryUserIsolated = ddlSite.SelectedItem.Text.Contains("ActiveDirectory");
FtpRootRow.Visible = isActiveDirectoryUserIsolated;
txtAdFtpRootReqValidator.Enabled= isActiveDirectoryUserIsolated;
}
} }
} }

View file

@ -1,22 +1,15 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// This code was generated by a tool. // This code was generated by a tool.
// Runtime Version:2.0.50727.1378
// //
// 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.
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
namespace WebsitePanel.Portal.ProviderControls { namespace WebsitePanel.Portal.ProviderControls {
/// <summary>
/// MSFTP70_Settings class.
/// </summary>
/// <remarks>
/// Auto-generated class.
/// </remarks>
public partial class MSFTP70_Settings { public partial class MSFTP70_Settings {
/// <summary> /// <summary>
@ -47,13 +40,49 @@ namespace WebsitePanel.Portal.ProviderControls {
protected global::System.Web.UI.WebControls.Label lblSite; protected global::System.Web.UI.WebControls.Label lblSite;
/// <summary> /// <summary>
/// txtSiteId control. /// ddlSite control.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// Auto-generated field. /// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file. /// To modify move field declaration from designer file to code-behind file.
/// </remarks> /// </remarks>
protected global::System.Web.UI.WebControls.TextBox txtSiteId; protected global::System.Web.UI.WebControls.DropDownList ddlSite;
/// <summary>
/// FtpRootRow control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.HtmlControls.HtmlTableRow FtpRootRow;
/// <summary>
/// lblAdFtpRoot control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.Label lblAdFtpRoot;
/// <summary>
/// txtAdFtpRoot control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.TextBox txtAdFtpRoot;
/// <summary>
/// txtAdFtpRootReqValidator control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.RequiredFieldValidator txtAdFtpRootReqValidator;
/// <summary> /// <summary>
/// lblGroupName control. /// lblGroupName control.

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,10 +1,9 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <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.
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------