Initial project's source code check-in.

This commit is contained in:
ptsurbeleu 2011-07-13 16:07:32 -07:00
commit b03b0b373f
4573 changed files with 981205 additions and 0 deletions

View file

@ -0,0 +1,365 @@
// Copyright (c) 2011, Outercurve Foundation.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// - Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// - Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// - Neither the name of the Outercurve Foundation nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using System;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.Text;
using WebsitePanel.Providers;
using WebsitePanel.Providers.Web;
using WebsitePanel.Providers.FTP;
using WebsitePanel.Providers.Mail;
using WebsitePanel.Providers.OS;
namespace WebsitePanel.EnterpriseServer
{
public class UserCreationWizard
{
public UserCreationWizard()
{
}
public static int CreateUserAccount(int parentPackageId, string username, string password,
int roleId, string firstName, string lastName, string email, string secondaryEmail, bool htmlMail,
bool sendAccountLetter,
bool createPackage, int planId, bool sendPackageLetter,
string domainName, bool tempDomain, bool createWebSite,
bool createFtpAccount, string ftpAccountName, bool createMailAccount)
{
UserCreationWizard wizard = new UserCreationWizard();
return wizard.CreateUserAccountInternal(parentPackageId, username, password,
roleId, firstName, lastName, email, secondaryEmail, htmlMail,
sendAccountLetter,
createPackage, planId, sendPackageLetter,
domainName, tempDomain, createWebSite,
createFtpAccount, ftpAccountName, createMailAccount);
}
// private fields
bool userCreated = false;
int createdUserId = 0;
int createdPackageId = 0;
public int CreateUserAccountInternal(int parentPackageId, string username, string password,
int roleId, string firstName, string lastName, string email, string secondaryEmail, bool htmlMail,
bool sendAccountLetter,
bool createPackage, int planId, bool sendPackageLetter,
string domainName, bool tempDomain, bool createWebSite,
bool createFtpAccount, string ftpAccountName, bool createMailAccount)
{
// check account
int accountCheck = SecurityContext.CheckAccount(DemandAccount.NotDemo | DemandAccount.IsActive
| DemandAccount.IsReseller);
if (accountCheck < 0) return accountCheck;
// check package
int packageCheck = SecurityContext.CheckPackage(parentPackageId, DemandPackage.IsActive);
if (packageCheck < 0) return packageCheck;
// check if username exists
if (UserController.UserExists(username))
return BusinessErrorCodes.ERROR_ACCOUNT_WIZARD_USER_EXISTS;
// check if domain exists
int checkDomainResult = ServerController.CheckDomain(domainName);
if (checkDomainResult < 0)
return checkDomainResult;
// check if FTP account exists
if (String.IsNullOrEmpty(ftpAccountName))
ftpAccountName = username;
if (FtpServerController.FtpAccountExists(ftpAccountName))
return BusinessErrorCodes.ERROR_ACCOUNT_WIZARD_FTP_ACCOUNT_EXISTS;
// load parent package
PackageInfo parentPackage = PackageController.GetPackage(parentPackageId);
/********************************************
* CREATE USER ACCOUNT
* *****************************************/
UserInfo user = new UserInfo();
user.RoleId = roleId;
user.StatusId = (int)UserStatus.Active;
user.OwnerId = parentPackage.UserId;
user.IsDemo = false;
user.IsPeer = false;
// account info
user.FirstName = firstName;
user.LastName = lastName;
user.Email = email;
user.SecondaryEmail = secondaryEmail;
user.Username = username;
user.Password = password;
user.HtmlMail = htmlMail;
// add a new user
createdUserId = UserController.AddUser(user, false);
if (createdUserId < 0)
{
// exit
return createdUserId;
}
userCreated = true;
// create package
// load hosting plan
createdPackageId = -1;
if (createPackage)
{
try
{
HostingPlanInfo plan = PackageController.GetHostingPlan(planId);
PackageResult packageResult = PackageController.AddPackage(
createdUserId, planId, plan.PlanName, "", (int)PackageStatus.Active, DateTime.Now, false);
createdPackageId = packageResult.Result;
}
catch (Exception ex)
{
// error while adding package
// remove user account
UserController.DeleteUser(createdUserId);
throw ex;
}
if (createdPackageId < 0)
{
// rollback wizard
Rollback();
// return code
return createdPackageId;
}
// create domain
int domainId = 0;
if ((createWebSite || createMailAccount) && !String.IsNullOrEmpty(domainName))
{
try
{
DomainInfo domain = new DomainInfo();
domain.PackageId = createdPackageId;
domain.DomainName = domainName;
domain.HostingAllowed = false;
domainId = ServerController.AddDomain(domain, !tempDomain);
if (domainId < 0)
{
// rollback wizard
Rollback();
// return
return domainId;
}
}
catch (Exception ex)
{
// rollback wizard
Rollback();
// error while adding domain
throw new Exception("Could not add domain", ex);
}
}
if (createWebSite && !String.IsNullOrEmpty(domainName))
{
// create web site
try
{
int webSiteId = WebServerController.AddWebSite(
createdPackageId, domainId, 0, true);
if (webSiteId < 0)
{
// rollback wizard
Rollback();
// return
return webSiteId;
}
}
catch (Exception ex)
{
// rollback wizard
Rollback();
// error while creating web site
throw new Exception("Could not create web site", ex);
}
}
// create FTP account
if (createFtpAccount)
{
try
{
FtpAccount ftpAccount = new FtpAccount();
ftpAccount.PackageId = createdPackageId;
ftpAccount.Name = ftpAccountName;
ftpAccount.Password = password;
ftpAccount.Folder = "\\";
ftpAccount.CanRead = true;
ftpAccount.CanWrite = true;
int ftpAccountId = FtpServerController.AddFtpAccount(ftpAccount);
if (ftpAccountId < 0)
{
// rollback wizard
Rollback();
// return
return ftpAccountId;
}
}
catch (Exception ex)
{
// rollback wizard
Rollback();
// error while creating ftp account
throw new Exception("Could not create FTP account", ex);
}
}
if (createMailAccount && !String.IsNullOrEmpty(domainName))
{
// create default mailbox
try
{
// load mail policy
UserSettings settings = UserController.GetUserSettings(createdUserId, UserSettings.MAIL_POLICY);
string catchAllName = !String.IsNullOrEmpty(settings["CatchAllName"])
? settings["CatchAllName"] : "mail";
MailAccount mailbox = new MailAccount();
mailbox.Name = catchAllName + "@" + domainName;
mailbox.PackageId = createdPackageId;
// gather information from the form
mailbox.Enabled = true;
mailbox.ResponderEnabled = false;
mailbox.ReplyTo = "";
mailbox.ResponderSubject = "";
mailbox.ResponderMessage = "";
// password
mailbox.Password = password;
// redirection
mailbox.ForwardingAddresses = new string[] { };
mailbox.DeleteOnForward = false;
mailbox.MaxMailboxSize = 0;
int mailAccountId = MailServerController.AddMailAccount(mailbox);
if (mailAccountId < 0)
{
// rollback wizard
Rollback();
// return
return mailAccountId;
}
// set catch-all account
MailDomain mailDomain = MailServerController.GetMailDomain(createdPackageId, domainName);
mailDomain.CatchAllAccount = "mail";
mailDomain.PostmasterAccount = "mail";
mailDomain.AbuseAccount = "mail";
MailServerController.UpdateMailDomain(mailDomain);
int mailDomainId = mailDomain.Id;
// set mail domain pointer
// load domain instant alias
string instantAlias = ServerController.GetDomainAlias(createdPackageId, domainName);
DomainInfo instantDomain = ServerController.GetDomain(instantAlias);
if (instantDomain == null || instantDomain.MailDomainId > 0)
instantAlias = "";
if (!String.IsNullOrEmpty(instantAlias))
MailServerController.AddMailDomainPointer(mailDomainId, instantDomain.DomainId);
}
catch (Exception ex)
{
// rollback wizard
Rollback();
// error while creating mail account
throw new Exception("Could not create mail account", ex);
}
}
}
// send welcome letters
if (sendAccountLetter)
{
int result = PackageController.SendAccountSummaryLetter(createdUserId, null, null, true);
if (result < 0)
{
// rollback wizard
Rollback();
// return
return result;
}
}
if (createPackage && sendPackageLetter)
{
int result = PackageController.SendPackageSummaryLetter(createdPackageId, null, null, true);
if (result < 0)
{
// rollback wizard
Rollback();
// return
return result;
}
}
return createdUserId;
}
public void Rollback()
{
if (userCreated)
{
// delete user account and all its packages
UserController.DeleteUser(createdUserId);
}
}
}
}

View file

@ -0,0 +1,876 @@
// Copyright (c) 2011, 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.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Data;
using System.Reflection;
using System.Collections;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.Xml;
using System.Net.Mail;
using System.Web;
using System.Web.Caching;
using WebsitePanel.Providers;
using WebsitePanel.Providers.Web;
using WebsitePanel.Providers.FTP;
using WebsitePanel.Providers.Mail;
using WebsitePanel.Providers.Database;
using WebsitePanel.Providers.OS;
using OS = WebsitePanel.Providers.OS;
namespace WebsitePanel.EnterpriseServer
{
public class WebApplicationsInstaller
{
public const string PROPERTY_CONTENT_PATH = "installer.contentpath";
public const string PROPERTY_ABSOLUTE_CONTENT_PATH = "installer.absolute.contentpath";
public const string PROPERTY_VDIR_CREATED = "installer.virtualdircreated";
public const string PROPERTY_DATABASE_CREATED = "installer.databasecreated";
public const string PROPERTY_USER_CREATED = "installer.usercreated";
public const string PROPERTY_INSTALLED_FILES = "installer.installedfiles";
public const string PROPERTY_DELETE_FILES = "installer.deletefiles";
public const string PROPERTY_DELETE_VDIR = "installer.deletevdir";
public const string PROPERTY_DELETE_SQL = "installer.deletesql";
public const string PROPERTY_DELETE_DATABASE = "installer.deletedatabase";
public const string PROPERTY_DELETE_USER = "installer.deleteuser";
public static int InstallApplication(InstallationInfo inst)
{
// check account
int accountCheck = SecurityContext.CheckAccount(DemandAccount.NotDemo | DemandAccount.IsActive);
if (accountCheck < 0) return accountCheck;
// check package
int packageCheck = SecurityContext.CheckPackage(inst.PackageId, DemandPackage.IsActive);
if (packageCheck < 0) return packageCheck;
// install application
WebApplicationsInstaller installer = new WebApplicationsInstaller();
return installer.InstallWebApplication(inst);
}
ApplicationInfo app = null;
private string contentPath = null;
private string siteId = null;
private OS.OperatingSystem os = null;
private DatabaseServer sql = null;
private string serverIpAddressExternal = null;
private string serverIpAddressInternal = null;
private string webSiteName = "";
public int InstallWebApplication(InstallationInfo inst)
{
// place log record
TaskManager.StartTask("APP_INSTALLER", "INSTALL_APPLICATION");
TaskManager.WriteParameter("Virtual directory", inst.VirtualDir);
TaskManager.WriteParameter("Database group", inst.DatabaseGroup);
TaskManager.ItemId = inst.PackageId;
try
{
// get application info
app = GetApplication(inst.PackageId, inst.ApplicationId);
TaskManager.ItemName = app.Name;
// check web site for existance
WebSite webSite = WebServerController.GetWebSite(inst.WebSiteId);
if (webSite == null)
return BusinessErrorCodes.ERROR_WEB_INSTALLER_WEBSITE_NOT_EXISTS;
TaskManager.WriteParameter("Web site", webSite.Name);
webSiteName = webSite.Name;
siteId = webSite.SiteId;
// change web site properties if required
if (String.IsNullOrEmpty(inst.VirtualDir))
{
ChangeVirtualDirectoryProperties(webSite, app.WebSettings);
WebServerController.UpdateWebSite(webSite);
}
// get OS service
int osId = PackageController.GetPackageServiceId(inst.PackageId, "os");
os = new OS.OperatingSystem();
ServiceProviderProxy.Init(os, osId);
// get remote content path
contentPath = webSite.ContentPath;
// create virtual dir if required
if (!String.IsNullOrEmpty(inst.VirtualDir))
{
// check if the required virtual dir already exists
contentPath = Path.Combine(contentPath, inst.VirtualDir);
WebVirtualDirectory vdir = null;
int result = WebServerController.AddVirtualDirectory(inst.WebSiteId, inst.VirtualDir, contentPath);
if (result == BusinessErrorCodes.ERROR_VDIR_ALREADY_EXISTS)
{
// the directory alredy exists
vdir = WebServerController.GetVirtualDirectory(
inst.WebSiteId, inst.VirtualDir);
contentPath = vdir.ContentPath;
}
else
{
vdir = WebServerController.GetVirtualDirectory(
inst.WebSiteId, inst.VirtualDir);
inst[PROPERTY_VDIR_CREATED] = "True";
}
// change virtual directory properties if required
ChangeVirtualDirectoryProperties(vdir, app.WebSettings);
WebServerController.UpdateVirtualDirectory(inst.WebSiteId, vdir);
}
// deploy application codebase ZIP and then unpack it
string codebasePath = app.Codebase;
string remoteCodebasePath = Path.Combine(contentPath, Path.GetFileName(app.Codebase));
// make content path absolute
string absContentPath = FilesController.GetFullPackagePath(inst.PackageId, contentPath);
// save content path
inst[PROPERTY_CONTENT_PATH] = contentPath;
inst[PROPERTY_ABSOLUTE_CONTENT_PATH] = absContentPath;
// copy ZIP to the target server
FileStream stream = File.OpenRead(codebasePath);
int BUFFER_LENGTH = 5000000;
byte[] buffer = new byte[BUFFER_LENGTH];
int readBytes = 0;
while (true)
{
readBytes = stream.Read(buffer, 0, BUFFER_LENGTH);
if (readBytes < BUFFER_LENGTH)
Array.Resize<byte>(ref buffer, readBytes);
FilesController.AppendFileBinaryChunk(inst.PackageId, remoteCodebasePath, buffer);
if (readBytes < BUFFER_LENGTH)
break;
}
// unpack codebase
inst[PROPERTY_INSTALLED_FILES] = String.Join(";",
FilesController.UnzipFiles(inst.PackageId, new string[] { remoteCodebasePath }));
// delete codebase zip
FilesController.DeleteFiles(inst.PackageId, new string[] { remoteCodebasePath });
// check/create databases
if (!String.IsNullOrEmpty(inst.DatabaseGroup) &&
String.Compare(inst.DatabaseGroup, "None", true) != 0)
{
// database
if (inst.DatabaseId == 0)
{
TaskManager.WriteParameter("Database name", inst.DatabaseName);
// we should create a new database
SqlDatabase db = new SqlDatabase();
db.PackageId = inst.PackageId;
db.Name = inst.DatabaseName;
inst.DatabaseId = DatabaseServerController.AddSqlDatabase(db, inst.DatabaseGroup);
if (inst.DatabaseId < 0)
{
// rollback installation
RollbackInstallation(inst);
// return error
return inst.DatabaseId; // there was an error when creating database
}
inst[PROPERTY_DATABASE_CREATED] = "True";
}
else
{
// existing database
SqlDatabase db = DatabaseServerController.GetSqlDatabase(inst.DatabaseId);
inst.DatabaseName = db.Name;
TaskManager.WriteParameter("Database name", inst.DatabaseName);
}
SqlUser user = null;
// database user
if (inst.UserId == 0)
{
TaskManager.WriteParameter("Database user", inst.Username);
// NEW USER
user = new SqlUser();
user.PackageId = inst.PackageId;
user.Name = inst.Username;
user.Databases = new string[] { inst.DatabaseName };
user.Password = inst.Password;
inst.UserId = DatabaseServerController.AddSqlUser(user, inst.DatabaseGroup);
if (inst.UserId < 0)
{
// rollback installation
RollbackInstallation(inst);
// return error
return inst.UserId; // error while adding user
}
inst[PROPERTY_USER_CREATED] = "True";
}
else
{
// EXISTING USER
user = DatabaseServerController.GetSqlUser(inst.UserId);
inst.Username = user.Name;
TaskManager.WriteParameter("Database user", inst.Username);
List<string> databases = new List<string>();
databases.AddRange(user.Databases);
if (!databases.Contains(inst.DatabaseName))
{
databases.Add(inst.DatabaseName);
user.Databases = databases.ToArray();
DatabaseServerController.UpdateSqlUser(user);
}
}
// check connectivity with SQL Server and credentials provided
// load user item
int sqlServiceId = PackageController.GetPackageServiceId(inst.PackageId, inst.DatabaseGroup);
sql = new DatabaseServer();
ServiceProviderProxy.Init(sql, sqlServiceId);
if (!sql.CheckConnectivity(inst.DatabaseName, inst.Username,
inst.Password))
{
// can't connect to the database
RollbackInstallation(inst);
return BusinessErrorCodes.ERROR_WEB_INSTALLER_CANT_CONNECT_DATABASE;
}
// read SQL server settings
StringDictionary settings = ServerController.GetServiceSettings(sqlServiceId);
serverIpAddressExternal = settings["ExternalAddress"];
if (settings.ContainsKey("InternalAddress"))
{
serverIpAddressInternal = settings["InternalAddress"];
}
}
// ********* RUN INSTALL SCENARIO ***********
int scriptResult = RunInstallScenario(inst);
if (scriptResult < 0)
{
// rollback installation
RollbackInstallation(inst);
// return error
return scriptResult;
}
// add new installation to the database
return 0;
}
catch (Exception ex)
{
// rollback installation
RollbackInstallation(inst);
throw TaskManager.WriteError(ex);
}
finally
{
TaskManager.CompleteTask();
}
}
private void ChangeVirtualDirectoryProperties(WebVirtualDirectory vdir,
ApplicationWebSetting[] settings)
{
if (settings == null)
return;
// get type properties
Type vdirType = vdir.GetType();
foreach (ApplicationWebSetting setting in settings)
{
PropertyInfo prop = vdirType.GetProperty(setting.Name,
BindingFlags.Public | BindingFlags.Instance);
if (prop != null)
{
prop.SetValue(vdir, ObjectUtils.Cast(setting.Value, prop.PropertyType), null);
}
}
}
private int RunInstallScenario(InstallationInfo inst)
{
string scenarioPath = Path.Combine(app.Folder, "Install.xml");
return RunScenario(scenarioPath, inst, true);
}
private string GetFullPathToInstallFolder(int userId)
{
string userhomeFolder = String.Empty;
string[] osSesstings = os.ServiceProviderSettingsSoapHeaderValue.Settings;
foreach (string s in osSesstings)
{
if (s.Contains("usershome"))
{
string[] split = s.Split(new char[] {'='});
userhomeFolder = split[1];
}
}
UserInfo info = UserController.GetUser(userId);
return Path.Combine(userhomeFolder, info.Username);
}
private int RunScenario(string scenarioPath, InstallationInfo inst, bool throwExceptions)
{
// load XML document
XmlDocument docScenario = new XmlDocument();
docScenario.Load(scenarioPath);
// go through "check" section
XmlNode nodeCheck = docScenario.SelectSingleNode("//check");
if (nodeCheck != null)
{
foreach (XmlNode nodeStep in nodeCheck.ChildNodes)
{
if (nodeStep.Name == "fileExists")
{
/*
// check if the specified file exists
string fileName = nodeStep.Attributes["path"].Value;
fileName = ExpandVariables(fileName, inst);
if (fileName.StartsWith("\\"))
{
fileName = fileName.Substring(1);
}
//get full path to instal folder
PackageInfo package = PackageController.GetPackage(inst.PackageId);
string fullPath = Path.Combine(GetFullPathToInstallFolder(package.UserId), fileName);
if (os.FileExists(fullPath))
return BusinessErrorCodes.ERROR_WEB_INSTALLER_TARGET_WEBSITE_UNSUITABLE;
*/
}
else if (nodeStep.Name == "sql")
{
string cmdText = nodeStep.InnerText;
cmdText = ExpandVariables(cmdText, inst);
DataSet dsResults = sql.ExecuteSqlQuery(inst.DatabaseName, cmdText);
if (dsResults.Tables[0].Rows.Count > 0)
return BusinessErrorCodes.ERROR_WEB_INSTALLER_TARGET_DATABASE_UNSUITABLE;
}
}
}
// go through "commands" section
XmlNode nodeCommands = docScenario.SelectSingleNode("//commands");
if (nodeCommands != null)
{
foreach (XmlNode nodeCommand in nodeCommands.ChildNodes)
{
if (nodeCommand.Name == "processFile")
{
// process remote file
string fileName = nodeCommand.Attributes["path"].Value;
fileName = ExpandVariables(fileName, inst);
byte[] fileBinaryContent = FilesController.GetFileBinaryContent(inst.PackageId, fileName);
if (fileBinaryContent == null)
throw new Exception("Could not process scenario file: " + fileName);
string fileContent = Encoding.UTF8.GetString(fileBinaryContent);
fileContent = ExpandVariables(fileContent, inst);
FilesController.UpdateFileBinaryContent(inst.PackageId, fileName,
Encoding.UTF8.GetBytes(fileContent));
}
else if (nodeCommand.Name == "runSql")
{
string cmdText = nodeCommand.InnerText;
if (nodeCommand.Attributes["path"] != null)
{
// load SQL from file
string sqlPath = Path.Combine(app.Folder, nodeCommand.Attributes["path"].Value);
if (!File.Exists(sqlPath))
continue;
StreamReader reader = new StreamReader(sqlPath);
cmdText = reader.ReadToEnd();
reader.Close();
}
bool run = true;
if (nodeCommand.Attributes["dependsOnProperty"] != null)
{
string[] propNames = nodeCommand.Attributes["dependsOnProperty"].Value.Split(',');
foreach (string propName in propNames)
{
if (inst[propName.Trim()] == null)
{
run = false;
break;
}
}
}
if (run)
{
try
{
cmdText = ExpandVariables(cmdText, inst);
sql.ExecuteSqlNonQuerySafe(inst.DatabaseName, inst.Username, inst.Password, cmdText);
}
catch (Exception ex)
{
if (throwExceptions)
throw ex;
}
}
}
}
}
return 0;
}
string appUrls = null;
private string ExpandVariables(string str, InstallationInfo inst)
{
str = ReplaceTemplateVariable(str, "installer.contentpath", inst[PROPERTY_CONTENT_PATH]);
str = ReplaceTemplateVariable(str, "installer.website", webSiteName);
str = ReplaceTemplateVariable(str, "installer.virtualdir", inst.VirtualDir);
string fullWebPath = webSiteName;
if (!String.IsNullOrEmpty(inst.VirtualDir))
fullWebPath += "/" + inst.VirtualDir;
// try to load domain info
DomainInfo domain = ServerController.GetDomain(webSiteName);
string fullWebPathPrefix = (domain != null && domain.IsSubDomain) ? "" : "www.";
// app URLs
if (appUrls == null)
{
// read web pointers
List<DomainInfo> sitePointers = WebServerController.GetWebSitePointers(inst.WebSiteId);
StringBuilder sb = new StringBuilder();
sb.Append("<urls>");
sb.Append("<url value=\"").Append(fullWebPath).Append("\"/>");
foreach (DomainInfo pointer in sitePointers)
{
string pointerWebPath = pointer.DomainName;
if (!String.IsNullOrEmpty(inst.VirtualDir))
pointerWebPath += "/" + inst.VirtualDir;
sb.Append("<url value=\"").Append(pointerWebPath).Append("\"/>");
}
sb.Append("</urls>");
appUrls = sb.ToString();
}
str = ReplaceTemplateVariable(str, "installer.appurls", appUrls);
string slashVirtualDir = "";
if (!String.IsNullOrEmpty(inst.VirtualDir))
slashVirtualDir = "/" + inst.VirtualDir;
str = ReplaceTemplateVariable(str, "installer.slashvirtualdir", slashVirtualDir);
str = ReplaceTemplateVariable(str, "installer.website.www", fullWebPathPrefix + webSiteName);
str = ReplaceTemplateVariable(str, "installer.fullwebpath", fullWebPath);
str = ReplaceTemplateVariable(str, "installer.fullwebpath.www", fullWebPathPrefix + fullWebPath);
//Replace ObjectQualifierNormalized which is not defined on portal
str = ReplaceTemplateVariable(str, "ObjectQualifierNormalized", "");
/*
* Application installer variable 'installer.database.server' is obsolete
* and should not be used to install Application Packs.
* Instead, please use the following two variables:
* - installer.database.server.external - defines external database address
* - installer.database.server.internal - defines internal database address
*
* See TFS Issue 952 for details.
*/
//apply external database address
str = ReplaceTemplateVariable(str, "installer.database.server",
((serverIpAddressExternal != null) ? serverIpAddressExternal : ""));
str = ReplaceTemplateVariable(str, "installer.database.server.external",
((serverIpAddressExternal != null) ? serverIpAddressExternal : String.Empty));
//apply internal database address
str = ReplaceTemplateVariable(str, "installer.database.server.internal",
((serverIpAddressInternal != null) ? serverIpAddressInternal : String.Empty));
str = ReplaceTemplateVariable(str, "installer.database", inst.DatabaseName);
str = ReplaceTemplateVariable(str, "installer.database.user", inst.Username);
str = ReplaceTemplateVariable(str, "installer.database.password",
((inst.Password != null) ? inst.Password : ""));
foreach (string[] pair in inst.PropertiesArray)
str = ReplaceTemplateVariable(str, pair[0], pair[1]);
return str;
}
private string ReplaceTemplateVariable(string str, string varName, string varValue)
{
if (String.IsNullOrEmpty(str) || String.IsNullOrEmpty(varName))
return str;
str = Regex.Replace(str, "\\$\\{" + varName + "\\}+", varValue, RegexOptions.IgnoreCase);
str = Regex.Replace(str, "\\$\\{" + varName + ".mysql-escaped\\}+", EscapeMySql(varValue), RegexOptions.IgnoreCase);
return Regex.Replace(str, "\\$\\{" + varName + ".mssql-escaped\\}+", EscapeMsSql(varValue), RegexOptions.IgnoreCase);
}
private string EscapeMySql(string str)
{
if (String.IsNullOrEmpty(str))
return str;
return str.Replace("'", "\\'")
.Replace("\"", "\\\"")
.Replace("\n", "\\n")
.Replace("\r", "\\r")
.Replace("\t", "\\t")
.Replace("\\", "\\\\")
.Replace("\0", "\\0");
}
private string EscapeMsSql(string str)
{
if (String.IsNullOrEmpty(str))
return str;
return str.Replace("'", "''");
}
private void RollbackInstallation(InstallationInfo inst)
{
// remove virtual dir
if (inst[PROPERTY_VDIR_CREATED] != null)
{
// delete virtual directory
WebServerController.DeleteVirtualDirectory(inst.WebSiteId, inst.VirtualDir);
// delete folder
FilesController.DeleteFiles(inst.PackageId, new string[] { inst[PROPERTY_CONTENT_PATH] });
}
// remove database
if (inst[PROPERTY_DATABASE_CREATED] != null)
DatabaseServerController.DeleteSqlDatabase(inst.DatabaseId);
// remove database user
if (inst[PROPERTY_USER_CREATED] != null)
DatabaseServerController.DeleteSqlUser(inst.UserId);
}
public static List<ApplicationCategory> GetCategories()
{
List<ApplicationCategory> categories = null;
string key = "WebApplicationCategories";
// look up in the cache
if (HttpContext.Current != null)
categories = (List<ApplicationCategory>)HttpContext.Current.Cache[key];
if (categories == null)
{
string catsPath = Path.Combine(ConfigSettings.WebApplicationsPath, "Applications.xml");
if (File.Exists(catsPath))
{
categories = new List<ApplicationCategory>();
// parse file
XmlDocument doc = new XmlDocument();
doc.Load(catsPath);
XmlNodeList nodesCategories = doc.SelectNodes("categories/category");
foreach (XmlNode nodeCategory in nodesCategories)
{
ApplicationCategory category = new ApplicationCategory();
category.Id = nodeCategory.Attributes["id"].Value;
category.Name = GetNodeValue(nodeCategory, "name", category.Id);
categories.Add(category);
// read applications
List<string> catApps = new List<string>();
XmlNodeList nodesApps = nodeCategory.SelectNodes("applications/application");
foreach (XmlNode nodeApp in nodesApps)
catApps.Add(nodeApp.Attributes["name"].Value);
category.Applications = catApps.ToArray();
}
}
// place to the cache
if (HttpContext.Current != null)
HttpContext.Current.Cache.Insert(key, categories, new CacheDependency(catsPath));
}
return categories;
}
public static List<ApplicationInfo> GetApplications(int packageId)
{
return GetApplications(packageId, null);
}
public static List<ApplicationInfo> GetApplications(int packageId, string categoryId)
{
string key = "WebApplicationsList";
Dictionary<string, ApplicationInfo> apps = null;
// look up in the cache
if(HttpContext.Current != null)
apps = (Dictionary<string, ApplicationInfo>)HttpContext.Current.Cache[key];
if (apps == null)
{
// create apps list
apps = new Dictionary<string, ApplicationInfo>();
string appsRoot = ConfigSettings.WebApplicationsPath;
string[] dirs = Directory.GetDirectories(appsRoot);
foreach (string dir in dirs)
{
string appFile = Path.Combine(dir, "Application.xml");
if (!File.Exists(appFile))
continue;
// read and parse web applications xml file
XmlDocument doc = new XmlDocument();
doc.Load(appFile);
XmlNode nodeApp = doc.SelectSingleNode("//application");
string appFolder = dir;
// parse node
ApplicationInfo app = CreateApplicationInfoFromXml(appFolder, nodeApp);
// add to the collection
apps.Add(app.Id, app);
}
// place to the cache
if (HttpContext.Current != null)
HttpContext.Current.Cache.Insert(key, apps, new CacheDependency(appsRoot));
}
// filter applications based on category
List<ApplicationInfo> categoryApps = new List<ApplicationInfo>();
// check if the application fits requirements
PackageContext cntx = PackageController.GetPackageContext(packageId);
List<ApplicationCategory> categories = GetCategories();
foreach (ApplicationCategory category in categories)
{
// skip category if required
if (!String.IsNullOrEmpty(categoryId)
&& String.Compare(category.Id, categoryId, true) != 0)
continue;
// iterate through applications
foreach (string appId in category.Applications)
{
if (apps.ContainsKey(appId)
&& IsApplicattionFitsRequirements(cntx, apps[appId]))
categoryApps.Add(apps[appId]);
}
}
return categoryApps;
}
public static ApplicationInfo GetApplication(int packageId, string applicationId)
{
// get all applications
List<ApplicationInfo> apps = GetApplications(packageId);
// check if the application fits requirements
PackageContext cntx = PackageController.GetPackageContext(packageId);
// find the application
foreach (ApplicationInfo app in apps)
{
if (app.Id.ToLower() == applicationId.ToLower())
{
return IsApplicattionFitsRequirements(cntx, app) ? app : null;
}
}
return null;
}
public static bool IsApplicattionFitsRequirements(PackageContext cntx, ApplicationInfo app)
{
if (app.Requirements == null)
return true; // empty requirements
foreach (ApplicationRequirement req in app.Requirements)
{
// check if this is a group
if (req.Groups != null)
{
bool groupFits = false;
foreach (string group in req.Groups)
{
if (cntx.Groups.ContainsKey(group))
{
groupFits = true;
break;
}
}
if (!groupFits)
return false;
}
// check if this is a quota
if (req.Quotas != null)
{
bool quotaFits = false;
foreach (string quota in req.Quotas)
{
if (cntx.Quotas.ContainsKey(quota) &&
!cntx.Quotas[quota].QuotaExhausted)
{
quotaFits = true;
break;
}
}
if (!quotaFits)
return false;
}
}
return true;
}
#region private helper methods
private static ApplicationInfo CreateApplicationInfoFromXml(string appFolder, XmlNode nodeApp)
{
ApplicationInfo app = new ApplicationInfo();
// category name
app.CategoryName = GetNodeValue(nodeApp, "category", "");
// attributes
app.Id = nodeApp.Attributes["id"].Value;
app.Codebase = nodeApp.Attributes["codebase"].Value;
app.SettingsControl = nodeApp.Attributes["settingsControl"].Value;
app.Folder = appFolder;
// child nodes
app.Name = GetNodeValue(nodeApp, "name", "");
app.ShortDescription = GetNodeValue(nodeApp, "shortDescription", "");
app.FullDescription = GetNodeValue(nodeApp, "fullDescription", "");
app.Logo = GetNodeValue(nodeApp, "logo", "");
app.Version = GetNodeValue(nodeApp, "version", "");
app.Size = Int32.Parse(GetNodeValue(nodeApp, "size", "0"));
app.HomeSite = GetNodeValue(nodeApp, "homeSite", "");
app.SupportSite = GetNodeValue(nodeApp, "supportSite", "");
app.DocsSite = GetNodeValue(nodeApp, "docSite", "");
app.Manufacturer = GetNodeValue(nodeApp, "manufacturer", "");
app.License = GetNodeValue(nodeApp, "license", "");
// process codebase path
app.Codebase = Path.Combine(appFolder, app.Codebase);
// web settings
List<ApplicationWebSetting> settings = new List<ApplicationWebSetting>();
XmlNodeList nodesWebSettings = nodeApp.SelectNodes("webSettings/add");
foreach (XmlNode nodeSetting in nodesWebSettings)
{
ApplicationWebSetting setting = new ApplicationWebSetting();
setting.Name = nodeSetting.Attributes["name"].Value;
setting.Value = nodeSetting.Attributes["value"].Value;
settings.Add(setting);
}
app.WebSettings = settings.ToArray();
// requirements
List<ApplicationRequirement> requirements = new List<ApplicationRequirement>();
XmlNodeList nodesRequirements = nodeApp.SelectNodes("requirements/add");
foreach (XmlNode nodesRequirement in nodesRequirements)
{
ApplicationRequirement req = new ApplicationRequirement();
if (nodesRequirement.Attributes["group"] != null)
req.Groups = nodesRequirement.Attributes["group"].Value.Split('|');
if (nodesRequirement.Attributes["quota"] != null)
req.Quotas = nodesRequirement.Attributes["quota"].Value.Split('|');
req.Display = true;
if (nodesRequirement.Attributes["display"] != null)
req.Display = Utils.ParseBool(nodesRequirement.Attributes["display"].Value, true);
requirements.Add(req);
}
app.Requirements = requirements.ToArray();
return app;
}
private static string GetNodeValue(XmlNode parentNode, string nodeName, string defaultValue)
{
XmlNode node = parentNode.SelectSingleNode(nodeName);
if (node != null)
{
return node.InnerText.Trim();
}
// return default value
return defaultValue;
}
#endregion
}
}