From 7bc0cc88fa651c7e556ef175f432eebf690e87f7 Mon Sep 17 00:00:00 2001 From: rdolezel Date: Tue, 11 Sep 2012 22:09:03 +0200 Subject: [PATCH 01/13] Work item 175 Exchange Accepted Domain can be switched between Authoritative and InternalRelay --- WebsitePanel/Database/install_db.sql | 29 ++++++++- WebsitePanel/Database/update_db.sql | 60 ++++++++++++++++++ .../OrganizationProxy.cs | 11 ++++ .../Code/Data/DataProvider.cs | 12 ++++ .../ExchangeServerController.cs | 62 ++++++++++++++++++- .../HostedSolution/OrganizationController.cs | 31 ++++++++++ .../Code/Servers/ServerController.cs | 4 +- .../esOrganizations.asmx.cs | 6 ++ .../ExchangeAcceptedDomainType.cs | 37 +++++++++++ .../HostedSolution/IExchangeServer.cs | 1 + .../HostedSolution/OrganizationDomainName.cs | 17 +++++ .../WebsitePanel.Providers.Base.csproj | 1 + .../Exchange2007.cs | 41 ++++++++++++ .../ExchangeServerProxy.cs | 12 +++- .../ExchangeServer.asmx.cs | 15 +++++ .../ExchangeServer/ExchangeDomainNames.ascx | 18 +++++- .../ExchangeDomainNames.ascx.cs | 32 ++++++++++ .../ExchangeDomainNames.ascx.designer.cs | 9 --- 18 files changed, 382 insertions(+), 16 deletions(-) create mode 100644 WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/ExchangeAcceptedDomainType.cs diff --git a/WebsitePanel/Database/install_db.sql b/WebsitePanel/Database/install_db.sql index a8b29b45..735ecd50 100644 --- a/WebsitePanel/Database/install_db.sql +++ b/WebsitePanel/Database/install_db.sql @@ -6508,6 +6508,7 @@ CREATE TABLE [dbo].[ExchangeOrganizationDomains]( [ItemID] [int] NOT NULL, [DomainID] [int] NULL, [IsHost] [bit] NULL, + [DomainTypeID] [int] NOT NULL, CONSTRAINT [PK_ExchangeOrganizationDomains] PRIMARY KEY CLUSTERED ( [OrganizationDomainID] ASC @@ -6634,7 +6635,8 @@ AS SELECT ED.DomainID, D.DomainName, - ED.IsHost + ED.IsHost, + ED.DomainTypeID FROM ExchangeOrganizationDomains AS ED INNER JOIN Domains AS D ON ED.DomainID = D.DomainID @@ -45799,6 +45801,29 @@ GO +CREATE PROCEDURE [dbo].ChangeExchangeAcceptedDomainType +( + @ItemID int, + @DomainID int, + @DomainTypeID int +) +AS +UPDATE ExchangeOrganizationDomains +SET DomainTypeID=@DomainTypeID +WHERE ItemID=ItemID AND DomainID=@DomainID +RETURN +GO + + + + + + + + + + + @@ -46064,6 +46089,8 @@ ALTER TABLE [dbo].[ExchangeOrganizationDomains] CHECK CONSTRAINT [FK_ExchangeOrg GO ALTER TABLE [dbo].[ExchangeOrganizationDomains] ADD CONSTRAINT [DF_ExchangeOrganizationDomains_IsHost] DEFAULT ((0)) FOR [IsHost] GO +ALTER TABLE [dbo].[ExchangeOrganizationDomains] ADD CONSTRAINT [DF_ExchangeOrganizationDomains_DomainTypeID] DEFAULT ((0)) FOR [DomainTypeID] +GO ALTER TABLE [dbo].[PrivateIPAddresses] WITH CHECK ADD CONSTRAINT [FK_PrivateIPAddresses_ServiceItems] FOREIGN KEY([ItemID]) REFERENCES [dbo].[ServiceItems] ([ItemID]) ON DELETE CASCADE diff --git a/WebsitePanel/Database/update_db.sql b/WebsitePanel/Database/update_db.sql index a19a94b4..de26ee66 100644 --- a/WebsitePanel/Database/update_db.sql +++ b/WebsitePanel/Database/update_db.sql @@ -5211,6 +5211,66 @@ GO +IF NOT EXISTS(select 1 from sys.columns COLS INNER JOIN sys.objects OBJS ON OBJS.object_id=COLS.object_id and OBJS.type='U' AND OBJS.name='ExchangeOrganizationDomains' AND COLS.name='DomainTypeID') +BEGIN +ALTER TABLE [dbo].[ExchangeOrganizationDomains] ADD + [DomainTypeID] [int] NOT NULL CONSTRAINT DF_ExchangeOrganizationDomains_DomainTypeID DEFAULT 0 +END +GO + + + + +ALTER PROCEDURE [dbo].[GetExchangeOrganizationDomains] +( + @ItemID int +) +AS +SELECT + ED.DomainID, + D.DomainName, + ED.IsHost, + ED.DomainTypeID +FROM + ExchangeOrganizationDomains AS ED +INNER JOIN Domains AS D ON ED.DomainID = D.DomainID +WHERE ED.ItemID = @ItemID +RETURN + +GO + + + + + + + +IF NOT EXISTS (SELECT * FROM sys.objects WHERE type_desc = N'SQL_STORED_PROCEDURE' AND name = N'ChangeExchangeAcceptedDomainType') +BEGIN +EXEC sp_executesql N' +CREATE PROCEDURE [dbo].ChangeExchangeAcceptedDomainType +( + @ItemID int, + @DomainID int, + @DomainTypeID int +) +AS +UPDATE ExchangeOrganizationDomains +SET DomainTypeID=@DomainTypeID +WHERE ItemID=ItemID AND DomainID=@DomainID +RETURN' +END +GO + + + + + + + + + + ALTER PROCEDURE [dbo].[GetPackages] ( @ActorID int, diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Client/OrganizationProxy.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Client/OrganizationProxy.cs index 78934577..8cf5ab0d 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Client/OrganizationProxy.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Client/OrganizationProxy.cs @@ -735,6 +735,17 @@ namespace WebsitePanel.EnterpriseServer.HostedSolution { domainId}); return ((int)(results[0])); } + + /// + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/ChangeOrganizationDomainType", RequestNamespace = "http://tempuri.org/", ResponseNamespace = "http://tempuri.org/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + public int ChangeOrganizationDomainType(int itemId, int domainId, ExchangeAcceptedDomainType newDomainType) + { + object[] results = this.Invoke("ChangeOrganizationDomainType", new object[] { + itemId, + domainId, + newDomainType}); + return ((int)(results[0])); + } /// public System.IAsyncResult BeginDeleteOrganizationDomain(int itemId, int domainId, System.AsyncCallback callback, object asyncState) { diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Data/DataProvider.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Data/DataProvider.cs index 336f9a1c..1539cb04 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Data/DataProvider.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Data/DataProvider.cs @@ -2152,6 +2152,18 @@ namespace WebsitePanel.EnterpriseServer ); } + public static void ChangeExchangeAcceptedDomainType(int itemId, int domainId, int domainTypeId) + { + SqlHelper.ExecuteNonQuery( + ConnectionString, + CommandType.StoredProcedure, + "ChangeExchangeAcceptedDomainType", + new SqlParameter("@ItemID", itemId), + new SqlParameter("@DomainID", domainId), + new SqlParameter("@DomainTypeID", domainTypeId) + ); + } + public static IDataReader GetExchangeOrganizationStatistics(int itemId) { return SqlHelper.ExecuteReader( diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/ExchangeServer/ExchangeServerController.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/ExchangeServer/ExchangeServerController.cs index 9fe58540..797af2f3 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/ExchangeServer/ExchangeServerController.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/ExchangeServer/ExchangeServerController.cs @@ -446,6 +446,10 @@ namespace WebsitePanel.EnterpriseServer { hubTransportRole.AddAuthoritativeDomain(domain.DomainName); } + if (domain.DomainType != ExchangeAcceptedDomainType.Authoritative) + { + hubTransportRole.ChangeAcceptedDomainType(domain.DomainName, domain.DomainType); + } } authDomainCreated = true; break; @@ -1423,8 +1427,64 @@ namespace WebsitePanel.EnterpriseServer TaskManager.CompleteTask(); } } - + public static int ChangeAcceptedDomainType(int itemId, int domainId, ExchangeAcceptedDomainType domainType) + { + // check account + int accountCheck = SecurityContext.CheckAccount(DemandAccount.NotDemo | DemandAccount.IsActive); + if (accountCheck < 0) return accountCheck; + + // place log record + TaskManager.StartTask("EXCHANGE", "CHANGE_DOMAIN_TYPE"); + TaskManager.TaskParameters["Domain ID"] = domainId; + TaskManager.TaskParameters["Domain Type"] = domainType.ToString(); + TaskManager.ItemId = itemId; + + try + { + // load organization + Organization org = (Organization)PackageController.GetPackageItem(itemId); + if (org == null) + return -1; + + // load domain + DomainInfo domain = ServerController.GetDomain(domainId); + if (domain == null) + return -1; + + int[] hubTransportServiceIds; + int[] clientAccessServiceIds; + int exchangeServiceId = GetExchangeServiceID(org.PackageId); + GetExchangeServices(exchangeServiceId, out hubTransportServiceIds, out clientAccessServiceIds); + + foreach (int id in hubTransportServiceIds) + { + ExchangeServer hubTransportRole = null; + try + { + hubTransportRole = GetExchangeServer(id, org.ServiceId); + } + catch (Exception ex) + { + TaskManager.WriteError(ex); + continue; + } + + hubTransportRole.ChangeAcceptedDomainType(domain.DomainName, domainType); + break; + + } + return 0; + } + catch (Exception ex) + { + throw TaskManager.WriteError(ex); + } + finally + { + TaskManager.CompleteTask(); + } + } public static int DeleteAuthoritativeDomain(int itemId, int domainId) { diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/HostedSolution/OrganizationController.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/HostedSolution/OrganizationController.cs index 824e058a..13057b80 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/HostedSolution/OrganizationController.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/HostedSolution/OrganizationController.cs @@ -1042,6 +1042,37 @@ namespace WebsitePanel.EnterpriseServer } } + public static int ChangeOrganizationDomainType(int itemId, int domainId, ExchangeAcceptedDomainType newDomainType) + { + // check account + int accountCheck = SecurityContext.CheckAccount(DemandAccount.NotDemo | DemandAccount.IsActive); + if (accountCheck < 0) return accountCheck; + + // place log record + TaskManager.StartTask("ORGANIZATION", "CHANGE_DOMAIN_TYPE", domainId); + TaskManager.ItemId = itemId; + + try + { + // change accepted domain type on Exchange + int checkResult = ExchangeServerController.ChangeAcceptedDomainType(itemId, domainId, newDomainType); + + + // change accepted domain type in DB + int domainTypeId= (int) newDomainType; + DataProvider.ChangeExchangeAcceptedDomainType(itemId, domainId, domainTypeId); + + return checkResult; + } + catch (Exception ex) + { + throw TaskManager.WriteError(ex); + } + finally + { + TaskManager.CompleteTask(); + } + } public static int AddOrganizationDomain(int itemId, string domainName) { diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Servers/ServerController.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Servers/ServerController.cs index bf469d50..1e053087 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Servers/ServerController.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Servers/ServerController.cs @@ -1588,8 +1588,8 @@ namespace WebsitePanel.EnterpriseServer return BusinessErrorCodes.ERROR_RESTRICTED_DOMAIN; else return checkDomainResult; - } - + } + public static List GetDomains(int packageId, bool recursive) { return ObjectUtils.CreateListFromDataSet( diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/esOrganizations.asmx.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/esOrganizations.asmx.cs index 9cd223ce..f81ad8cf 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/esOrganizations.asmx.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/esOrganizations.asmx.cs @@ -122,6 +122,12 @@ namespace WebsitePanel.EnterpriseServer return OrganizationController.AddOrganizationDomain(itemId, domainName); } + [WebMethod] + public int ChangeOrganizationDomainType(int itemId, int domainId, ExchangeAcceptedDomainType newDomainType) + { + return OrganizationController.ChangeOrganizationDomainType(itemId, domainId, newDomainType); + } + [WebMethod] public List GetOrganizationDomains(int itemId) { diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/ExchangeAcceptedDomainType.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/ExchangeAcceptedDomainType.cs new file mode 100644 index 00000000..2d6e897e --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/ExchangeAcceptedDomainType.cs @@ -0,0 +1,37 @@ +// Copyright (c) 2012, 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. + +namespace WebsitePanel.Providers.HostedSolution + { + public enum ExchangeAcceptedDomainType + { + Authoritative = 0, + InternalRelay = 1, + ExternalRelay = 2 + } + } diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/IExchangeServer.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/IExchangeServer.cs index 72fdcafd..dbbefc58 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/IExchangeServer.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/IExchangeServer.cs @@ -53,6 +53,7 @@ namespace WebsitePanel.Providers.HostedSolution // Domains void AddAuthoritativeDomain(string domain); void DeleteAuthoritativeDomain(string domain); + void ChangeAcceptedDomainType(string domain, ExchangeAcceptedDomainType domainType); string[] GetAuthoritativeDomains(); // Mailboxes diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/OrganizationDomainName.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/OrganizationDomainName.cs index 68587c08..323e7d48 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/OrganizationDomainName.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/OrganizationDomainName.cs @@ -26,6 +26,7 @@ // (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; namespace WebsitePanel.Providers.HostedSolution { public class OrganizationDomainName @@ -33,6 +34,7 @@ namespace WebsitePanel.Providers.HostedSolution int organizationDomainId; int itemId; int domainId; + int domainTypeId; string domainName; bool isHost; bool isDefault; @@ -55,6 +57,21 @@ namespace WebsitePanel.Providers.HostedSolution set { domainId = value; } } + public int DomainTypeId + { + get { return domainTypeId; } + set { domainTypeId = value; } + } + + public ExchangeAcceptedDomainType DomainType + { + get + { + ExchangeAcceptedDomainType type = (ExchangeAcceptedDomainType)domainTypeId; + return type; + } + } + public int OrganizationDomainId { get { return organizationDomainId; } diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj b/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj index 3fed47eb..b8623bcf 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj @@ -80,6 +80,7 @@ + diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/Exchange2007.cs b/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/Exchange2007.cs index e48e2dca..046c5a44 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/Exchange2007.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/Exchange2007.cs @@ -230,6 +230,11 @@ namespace WebsitePanel.Providers.HostedSolution { DeleteAuthoritativeDomainInternal(domain); } + + public void ChangeAcceptedDomainType(string domainName, ExchangeAcceptedDomainType domainType) + { + ChangeAcceptedDomainTypeInternal(domainName, domainType); + } #endregion #region Mailboxes @@ -5916,6 +5921,31 @@ namespace WebsitePanel.Providers.HostedSolution ExchangeLog.LogEnd("CreateAuthoritativeDomainInternal"); } + private void ChangeAcceptedDomainTypeInternal(string domainName, ExchangeAcceptedDomainType domainType) + { + ExchangeLog.LogStart("ChangeAcceptedDomainType"); + + Runspace runSpace = null; + try + { + runSpace = OpenRunspace(); + + SetAcceptedDomainType(runSpace, domainName,domainType); + } + catch (Exception ex) + { + ExchangeLog.LogError("ChangeAcceptedDomainType", ex); + throw; + } + finally + { + + CloseRunspace(runSpace); + } + + ExchangeLog.LogEnd("ChangeAcceptedDomainType"); + } + private void DeleteAcceptedDomain(string domainName) { ExchangeLog.LogStart("DeleteAcceptedDomain"); @@ -5980,6 +6010,17 @@ namespace WebsitePanel.Providers.HostedSolution ExchangeLog.LogEnd("RemoveAcceptedDomain"); } + private void SetAcceptedDomainType(Runspace runSpace, string id, ExchangeAcceptedDomainType domainType) + { + ExchangeLog.LogStart("SetAcceptedDomainType"); + Command cmd = new Command("Set-AcceptedDomain"); + cmd.Parameters.Add("Identity", id); + cmd.Parameters.Add("DomainType", domainType.ToString()); + cmd.Parameters.Add("Confirm", false); + ExecuteShellCommand(runSpace, cmd); + ExchangeLog.LogEnd("SetAcceptedDomainType"); + } + #endregion #region ActiveSync diff --git a/WebsitePanel/Sources/WebsitePanel.Server.Client/ExchangeServerProxy.cs b/WebsitePanel/Sources/WebsitePanel.Server.Client/ExchangeServerProxy.cs index 31142263..64a9509c 100644 --- a/WebsitePanel/Sources/WebsitePanel.Server.Client/ExchangeServerProxy.cs +++ b/WebsitePanel/Sources/WebsitePanel.Server.Client/ExchangeServerProxy.cs @@ -1032,7 +1032,17 @@ namespace WebsitePanel.Providers.Exchange this.Invoke("AddAuthoritativeDomain", new object[] { domain}); } - + + /// + [System.Web.Services.Protocols.SoapHeaderAttribute("ServiceProviderSettingsSoapHeaderValue")] + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://smbsaas/websitepanel/server/ChangeAcceptedDomainType", RequestNamespace = "http://smbsaas/websitepanel/server/", ResponseNamespace = "http://smbsaas/websitepanel/server/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + public void ChangeAcceptedDomainType(string domain, ExchangeAcceptedDomainType domainType) + { + this.Invoke("ChangeAcceptedDomainType", new object[] { + domain, + domainType}); + } + /// public System.IAsyncResult BeginAddAuthoritativeDomain(string domain, System.AsyncCallback callback, object asyncState) { return this.BeginInvoke("AddAuthoritativeDomain", new object[] { diff --git a/WebsitePanel/Sources/WebsitePanel.Server/ExchangeServer.asmx.cs b/WebsitePanel/Sources/WebsitePanel.Server/ExchangeServer.asmx.cs index 3c5c5a1f..8553b61f 100644 --- a/WebsitePanel/Sources/WebsitePanel.Server/ExchangeServer.asmx.cs +++ b/WebsitePanel/Sources/WebsitePanel.Server/ExchangeServer.asmx.cs @@ -265,6 +265,21 @@ namespace WebsitePanel.Server } } + [WebMethod, SoapHeader("settings")] + public void ChangeAcceptedDomainType(string domain, ExchangeAcceptedDomainType domainType) + { + try + { + LogStart("ChangeAcceptedDomainType"); + ES.ChangeAcceptedDomainType(domain, domainType); + LogEnd("ChangeAcceptedDomainType"); + } + catch (Exception ex) + { + LogError("ChangeAcceptedDomainType", ex); + throw; + } + } [WebMethod, SoapHeader("settings")] public string[] GetAuthoritativeDomains() diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/ExchangeDomainNames.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/ExchangeDomainNames.ascx index 54abfc9d..1ab3e776 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/ExchangeDomainNames.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/ExchangeDomainNames.ascx @@ -33,7 +33,7 @@ Width="100%" EmptyDataText="gvDomains" CssSelectorClass="NormalGridView" OnRowCommand="gvDomains_RowCommand"> - + @@ -41,13 +41,27 @@ + + +
+ +
+
+
+ + +
+ +
+
+
/>
-
+   protected global::WebsitePanel.Portal.QuotaViewer domainsQuota; - - /// - /// FormComments control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Localize FormComments; } } From b95cdf59b37087cc8b6607578b4629177e86d699 Mon Sep 17 00:00:00 2001 From: rdolezel Date: Wed, 12 Sep 2012 15:10:12 +0200 Subject: [PATCH 02/13] Forgotten localization --- .../App_LocalResources/ExchangeDomainNames.ascx.resx | 9 +++++++++ .../WebsitePanel/ExchangeServer/ExchangeDomainNames.ascx | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/App_LocalResources/ExchangeDomainNames.ascx.resx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/App_LocalResources/ExchangeDomainNames.ascx.resx index d8f453a2..77fff6cd 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/App_LocalResources/ExchangeDomainNames.ascx.resx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/App_LocalResources/ExchangeDomainNames.ascx.resx @@ -155,4 +155,13 @@ Domain Names + + Domain Type + + + Change Type + ¨ + + Change + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/ExchangeDomainNames.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/ExchangeDomainNames.ascx index 1ab3e776..c060f31b 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/ExchangeDomainNames.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/ExchangeDomainNames.ascx @@ -51,7 +51,7 @@
- +
From f7d7bcfafc5d9210653a7c9774036c9e1c5dd22e Mon Sep 17 00:00:00 2001 From: Haya Nmeir Date: Sun, 16 Sep 2012 02:22:05 +0300 Subject: [PATCH 03/13] This built contains the functionality to set hard quota on the website content folder. It requires FSRM to be installed on the File Server, Name of the share where the home folders are create should contain the drive name preceeded by _ e.g. SharedConfig_C. Quota is retrieved from OS disk space quota, quota unit is retrieved from quota description field in the quotas table, this info is fed to Dirquota command and the quota is set accordingly. --- .../Code/Files/FilesController.cs | 71 +++++++++++ .../Code/WebServers/WebServerController.cs | 3 + .../WebsitePanel.EnterpriseServer/Web.config | 40 +++--- .../WebsitePanel.EnterpriseServer.csproj | 6 + .../OS/IOperatingSystem.cs | 1 + .../WebsitePanel.Providers.Base.csproj | 9 ++ .../Windows2003.cs | 11 ++ .../OperatingSystemProxy.cs | 87 ++++++++++++- .../WebsitePanel.Server.Utils/FileUtils.cs | 116 ++++++++++++++++++ .../OperatingSystem.asmx.cs | 17 +++ .../Sources/WebsitePanel.Server/Web.config | 2 +- .../WebsitePanel.Server.csproj | 5 + .../WebsitePanel.WebPortal.csproj | 1 + 13 files changed, 347 insertions(+), 22 deletions(-) diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Files/FilesController.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Files/FilesController.cs index 7784cad8..4314bcd0 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Files/FilesController.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Files/FilesController.cs @@ -912,5 +912,76 @@ namespace WebsitePanel.EnterpriseServer return users.ToArray(); } + + public static int SetFolderQuota(int packageId, string path) + { + + // check account + int accountCheck = SecurityContext.CheckAccount(DemandAccount.NotDemo | DemandAccount.IsActive); + if (accountCheck < 0) return accountCheck; + + // check package + int packageCheck = SecurityContext.CheckPackage(packageId, DemandPackage.IsActive); + if (packageCheck < 0) return packageCheck; + + // place log record + TaskManager.StartTask("FILES", "SET_QUOTA_ON_FOLDER", path); + TaskManager.ItemId = packageId; + + try + { + + // file server cluster name + string fileServerClusterName = String.Empty; + + // Share Name where home folders are created + string shareName = String.Empty; + + string[] splits = GetHomeFolder(packageId).Split('\\'); + + if (splits.Length > 4) + { + fileServerClusterName = splits[2]; + shareName = splits[3]; + } + + // disk space quota + QuotaValueInfo diskSpaceQuota = PackageController.GetPackageQuota(packageId, Quotas.OS_DISKSPACE); + + // bat file pat + string cmdFilePath = @"\\" + fileServerClusterName + @"\" + shareName + @"\" + "Process.bat"; + + #region figure Quota Unit + + // Quota Unit + string unit = String.Empty; + if (diskSpaceQuota.QuotaDescription.ToLower().Contains("gb")) + unit = "GB"; + else if (diskSpaceQuota.QuotaDescription.ToLower().Contains("mb")) + unit = "MB"; + else + unit = "KB"; + + #endregion + + OS.OperatingSystem os = GetOS(packageId); + os.SetQuotaLimitOnFolder(cmdFilePath, fileServerClusterName, path, diskSpaceQuota.QuotaAllocatedValue.ToString() + unit, 0, String.Empty, String.Empty); + + return 0; + } + catch (Exception ex) + { + //Log and return a generic error rather than throwing an exception + TaskManager.WriteError(ex); + return BusinessErrorCodes.ERROR_FILE_GENERIC_LOGGED; + } + finally + { + TaskManager.CompleteTask(); + } + + + } + } } diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/WebServers/WebServerController.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/WebServers/WebServerController.cs index 5ea67ab0..a703fa4f 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/WebServers/WebServerController.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/WebServers/WebServerController.cs @@ -377,6 +377,9 @@ namespace WebsitePanel.EnterpriseServer // CREATE WEB SITE siteId = web.CreateSite(site); + // Set hard quota on the website content folder + FilesController.SetFolderQuota(packageId, site.DataPath); + // register item site.ServiceId = serviceId; site.PackageId = packageId; diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Web.config b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Web.config index b78330c8..56350e5d 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Web.config +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Web.config @@ -1,56 +1,56 @@ - + -
+
- + - + - + - + - + - + - + - + - - - + + + - + - + - + - - + + - + - + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/WebsitePanel.EnterpriseServer.csproj b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/WebsitePanel.EnterpriseServer.csproj index 52285130..ac8ea558 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/WebsitePanel.EnterpriseServer.csproj +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/WebsitePanel.EnterpriseServer.csproj @@ -19,6 +19,11 @@ v4.0 + false + + + + true @@ -410,6 +415,7 @@ + diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/OS/IOperatingSystem.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/OS/IOperatingSystem.cs index fc9f3076..73088563 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/OS/IOperatingSystem.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/OS/IOperatingSystem.cs @@ -81,5 +81,6 @@ namespace WebsitePanel.Providers.OS // Synchronizing FolderGraph GetFolderGraph(string path); void ExecuteSyncActions(FileSyncAction[] actions); + void SetQuotaLimitOnFolder(string cmdFilePath, string virtualFileClusterName, string folderPath, string quotaLimit, int mode, string wmiUserName, string wmiPassword); } } diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj b/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj index 3fed47eb..137151d2 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj @@ -92,6 +92,11 @@ + + True + True + Settings.settings + @@ -312,6 +317,10 @@ + + SettingsSingleFileGenerator + Settings.Designer.cs + diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.OS.Windows2003/Windows2003.cs b/WebsitePanel/Sources/WebsitePanel.Providers.OS.Windows2003/Windows2003.cs index f251bd66..0965df57 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.OS.Windows2003/Windows2003.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.OS.Windows2003/Windows2003.cs @@ -209,6 +209,17 @@ namespace WebsitePanel.Providers.OS SecurityUtils.GrantGroupNtfsPermissions(path, users, resetChildPermissions, ServerSettings, usersOU, null); } + + public virtual void SetQuotaLimitOnFolder(string cmdFilePath, string virtualFileClusterName, string folderPath, string quotaLimit, int mode, string wmiUserName, string wmiPassword) + { + FileUtils.SetQuotaLimitOnFolder(cmdFilePath, virtualFileClusterName, folderPath, quotaLimit, mode, wmiUserName, wmiPassword); + } + + public static void DeleteDirRecursive(DirectoryInfo treeRoot) + { + FileUtils.DeleteDirectoryRecursive(treeRoot); + } + #endregion #region ODBC DSNs diff --git a/WebsitePanel/Sources/WebsitePanel.Server.Client/OperatingSystemProxy.cs b/WebsitePanel/Sources/WebsitePanel.Server.Client/OperatingSystemProxy.cs index f40b6d59..d641b6f1 100644 --- a/WebsitePanel/Sources/WebsitePanel.Server.Client/OperatingSystemProxy.cs +++ b/WebsitePanel/Sources/WebsitePanel.Server.Client/OperatingSystemProxy.cs @@ -61,6 +61,8 @@ namespace WebsitePanel.Providers.OS { private System.Threading.SendOrPostCallback CreatePackageFolderOperationCompleted; private System.Threading.SendOrPostCallback FileExistsOperationCompleted; + + private System.Threading.SendOrPostCallback SetQuotaLimitOnFolderOperationCompleted; private System.Threading.SendOrPostCallback DirectoryExistsOperationCompleted; @@ -131,7 +133,8 @@ namespace WebsitePanel.Providers.OS { private System.Threading.SendOrPostCallback UpdateDSNOperationCompleted; private System.Threading.SendOrPostCallback DeleteDSNOperationCompleted; - + + /// public OperatingSystem() { this.Url = "http://localhost/Server/OperatingSystem.asmx"; @@ -142,6 +145,8 @@ namespace WebsitePanel.Providers.OS { /// public event FileExistsCompletedEventHandler FileExistsCompleted; + + public event SetQuotaLimitOnFolderCompletedEventHandler SetQuotaLimitOnFolderCompleted; /// public event DirectoryExistsCompletedEventHandler DirectoryExistsCompleted; @@ -331,6 +336,56 @@ namespace WebsitePanel.Providers.OS { this.FileExistsCompleted(this, new FileExistsCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); } } + + /// + [System.Web.Services.Protocols.SoapHeaderAttribute("ServiceProviderSettingsSoapHeaderValue")] + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://smbsaas/websitepanel/server/SetQuotaLimitOnFolder", RequestNamespace = "http://smbsaas/websitepanel/server/", ResponseNamespace = "http://smbsaas/websitepanel/server/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + public bool SetQuotaLimitOnFolder(string cmdFilePath, string virtualFileClusterName, string folderPath, string quotaLimit, int mode, string wmiUserName, string wmiPassword) + { + object[] results = this.Invoke("SetQuotaLimitOnFolder", new object[] { + cmdFilePath, virtualFileClusterName, folderPath, quotaLimit, mode, wmiUserName, wmiPassword}); + return ((bool)(results[0])); + } + + /// + public System.IAsyncResult BeginSetQuotaLimitOnFolder(string cmdFilePath, string virtualFileClusterName, string folderPath, string quotaLimit, int mode, string wmiUserName, string wmiPassword, System.AsyncCallback callback, object asyncState) + { + return this.BeginInvoke("SetQuotaLimitOnFolder", new object[] { + cmdFilePath, virtualFileClusterName, folderPath, quotaLimit, mode, wmiUserName, wmiPassword}, callback, asyncState); + } + + /// + public bool EndSetQuotaLimitOnFolder(System.IAsyncResult asyncResult) + { + object[] results = this.EndInvoke(asyncResult); + return ((bool)(results[0])); + } + + /// + public void SetQuotaLimitOnFolderAsync(string cmdFilePath, string virtualFileClusterName, string folderPath, string quotaLimit, int mode, string wmiUserName, string wmiPassword) + { + this.SetQuotaLimitOnFolderAsync(cmdFilePath, virtualFileClusterName, folderPath, quotaLimit, mode, wmiUserName, wmiPassword, null); + } + + /// + public void SetQuotaLimitOnFolderAsync(string cmdFilePath, string virtualFileClusterName, string folderPath, string quotaLimit, int mode, string wmiUserName, string wmiPassword, object userState) + { + if ((this.FileExistsOperationCompleted == null)) + { + this.FileExistsOperationCompleted = new System.Threading.SendOrPostCallback(this.OnFileExistsOperationCompleted); + } + this.InvokeAsync("SetQuotaLimitOnFolder", new object[] { + cmdFilePath, virtualFileClusterName, folderPath, quotaLimit, mode, wmiUserName, wmiPassword}, this.SetQuotaLimitOnFolderOperationCompleted, userState); + } + + private void OnSetQuotaLimitOnFolderOperationCompleted(object arg) + { + if ((this.SetQuotaLimitOnFolderCompleted != null)) + { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.SetQuotaLimitOnFolderCompleted(this, new SetQuotaLimitOnFolderCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } /// [System.Web.Services.Protocols.SoapHeaderAttribute("ServiceProviderSettingsSoapHeaderValue")] @@ -1899,6 +1954,36 @@ namespace WebsitePanel.Providers.OS { } } } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")] + public delegate void SetQuotaLimitOnFolderCompletedEventHandler(object sender, SetQuotaLimitOnFolderCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class SetQuotaLimitOnFolderCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs + { + + private object[] results; + + internal SetQuotaLimitOnFolderCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : + base(exception, cancelled, userState) + { + this.results = results; + } + + /// + public bool Result + { + get + { + this.RaiseExceptionIfNecessary(); + return ((bool)(this.results[0])); + } + } + } /// [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")] diff --git a/WebsitePanel/Sources/WebsitePanel.Server.Utils/FileUtils.cs b/WebsitePanel/Sources/WebsitePanel.Server.Utils/FileUtils.cs index f30354a5..77d6d45e 100644 --- a/WebsitePanel/Sources/WebsitePanel.Server.Utils/FileUtils.cs +++ b/WebsitePanel/Sources/WebsitePanel.Server.Utils/FileUtils.cs @@ -37,6 +37,7 @@ using System.Collections.Generic; using System.Reflection; using Ionic.Zip; using WebsitePanel.Providers.OS; +using System.Management; namespace WebsitePanel.Providers.Utils { @@ -844,6 +845,121 @@ namespace WebsitePanel.Providers.Utils conn, null); cat = null; } + + public static void DeleteDirectoryRecursive(DirectoryInfo treeRoot) + { + if (treeRoot.Exists) + { + + DirectoryInfo[] dirs = treeRoot.GetDirectories(); + while (dirs.Length > 0) + { + foreach (DirectoryInfo dir in dirs) + DeleteDirectoryRecursive(dir); + + dirs = treeRoot.GetDirectories(); + } + + // DELETE THE FILES UNDER THE CURRENT ROOT + string[] files = Directory.GetFiles(treeRoot.FullName); + foreach (string file in files) + { + File.SetAttributes(file, FileAttributes.Normal); + File.Delete(file); + } + + Directory.Delete(treeRoot.FullName, true); + } + + } + + public static void SetQuotaLimitOnFolder(string cmdFilePath, string virtualFileClusterName, string folderPath, string quotaLimit, int mode, string wmiUserName, string wmiPassword) + { + try + { + string[] splits = folderPath.Split('\\'); + if (splits.Length > 0) + { + // Creating the BAT file + FileStream fs = File.Create(cmdFilePath); + if (fs != null) + { + fs.Close(); + fs.Dispose(); + } + + StreamWriter swr = new StreamWriter(cmdFilePath); + + if (swr != null) + { + swr.WriteLine(@"cd c:\windows\system32"); + + string[] shareDrive = { }; + string sharePath = String.Empty; + + if (splits.Length > 4) + { + // Check the share name if it's not an empty string + if (splits[3].Length > 0) + shareDrive = splits[3].Split('_'); + + // Form the share physicalPath + if (shareDrive.Length == 2) + sharePath = shareDrive[1] + @":\" + splits[3]; + + if (splits.Length == 7 && !quotaLimit.Equals(String.Empty)) + { + splits[6] = "wwwroot"; + + switch (mode) + { + // Set + case 0: swr.WriteLine(@"dirquota quota add /path:" + sharePath + @"\" + splits[4] + @"\" + splits[5] + @"\" + splits[6] + @" /limit:" + quotaLimit + @" /remote:" + splits[2]); + break; + + // Modify + case 1: swr.WriteLine(@"dirquota quota modify /path:" + sharePath + @"\" + splits[4] + @"\" + splits[5] + @"\" + splits[6] + @" /limit:" + quotaLimit + @" /remote:" + splits[2]); + break; + } + } + + + } + swr.Flush(); + swr.Close(); + swr.Dispose(); + } + + ConnectionOptions connOptions = new ConnectionOptions(); + + if (wmiUserName.Length > 0) + { + connOptions.Username = wmiUserName; + connOptions.Password = wmiPassword; + } + + connOptions.Impersonation = ImpersonationLevel.Impersonate; + + connOptions.EnablePrivileges = true; + + ManagementScope manScope = + new ManagementScope(String.Format(@"\\{0}\ROOT\CIMV2", virtualFileClusterName), connOptions); + manScope.Connect(); + + ObjectGetOptions objectGetOptions = new ObjectGetOptions(); + ManagementPath managementPath = new ManagementPath("Win32_Process"); + ManagementClass processClass = new ManagementClass(manScope, managementPath, objectGetOptions); + + ManagementBaseObject inParams = processClass.GetMethodParameters("Create"); + inParams["CommandLine"] = cmdFilePath; + ManagementBaseObject outParams = processClass.InvokeMethod("Create", inParams, null); + + } + } + catch + { } + } + #region Advanced Delete /// /// Deletes the specified file. diff --git a/WebsitePanel/Sources/WebsitePanel.Server/OperatingSystem.asmx.cs b/WebsitePanel/Sources/WebsitePanel.Server/OperatingSystem.asmx.cs index e258900a..3e24a15e 100644 --- a/WebsitePanel/Sources/WebsitePanel.Server/OperatingSystem.asmx.cs +++ b/WebsitePanel/Sources/WebsitePanel.Server/OperatingSystem.asmx.cs @@ -533,6 +533,23 @@ namespace WebsitePanel.Server throw; } } + + + [WebMethod, SoapHeader("settings")] + public void SetQuotaLimitOnFolder(string cmdFilePath, string virtualFileClusterName, string folderPath, string quotaLimit, int mode, string wmiUserName, string wmiPassword) + { + try + { + Log.WriteStart("'{0}' SetQuotaLimitOnFolder", ProviderSettings.ProviderName); + OsProvider.SetQuotaLimitOnFolder(cmdFilePath, virtualFileClusterName, folderPath, quotaLimit, mode, wmiUserName, wmiPassword); + Log.WriteEnd("'{0}' SetQuotaLimitOnFolder", ProviderSettings.ProviderName); + } + catch (Exception ex) + { + Log.WriteError(String.Format("'{0}' SetQuotaLimitOnFolder", ProviderSettings.ProviderName), ex); + throw; + } + } #endregion #region Synchronizing diff --git a/WebsitePanel/Sources/WebsitePanel.Server/Web.config b/WebsitePanel/Sources/WebsitePanel.Server/Web.config index 48568b3a..f4c59fb4 100644 --- a/WebsitePanel/Sources/WebsitePanel.Server/Web.config +++ b/WebsitePanel/Sources/WebsitePanel.Server/Web.config @@ -44,7 +44,7 @@ - + diff --git a/WebsitePanel/Sources/WebsitePanel.Server/WebsitePanel.Server.csproj b/WebsitePanel/Sources/WebsitePanel.Server/WebsitePanel.Server.csproj index 890ebc21..5c4731db 100644 --- a/WebsitePanel/Sources/WebsitePanel.Server/WebsitePanel.Server.csproj +++ b/WebsitePanel/Sources/WebsitePanel.Server/WebsitePanel.Server.csproj @@ -20,6 +20,10 @@ v3.5 false + + + + true @@ -231,6 +235,7 @@ + diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/WebsitePanel.WebPortal.csproj b/WebsitePanel/Sources/WebsitePanel.WebPortal/WebsitePanel.WebPortal.csproj index c93b1a73..e852620d 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/WebsitePanel.WebPortal.csproj +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/WebsitePanel.WebPortal.csproj @@ -241,6 +241,7 @@ + From e45eff5297342f8286210210d1889f6f4abb93db Mon Sep 17 00:00:00 2001 From: Haya Nmeir Date: Tue, 18 Sep 2012 09:14:06 +0300 Subject: [PATCH 04/13] Update the delete website function to delete the website directory tree and the remote management access accounts. --- .../Code/Files/FilesController.cs | 37 ++++++++ .../Code/WebServers/WebServerController.cs | 8 ++ .../OS/IOperatingSystem.cs | 3 + .../Windows2003.cs | 4 +- .../OperatingSystemProxy.cs | 92 ++++++++++++++++++- .../WebsitePanel.Server.Utils/FileUtils.cs | 45 +++++---- .../OperatingSystem.asmx.cs | 16 ++++ 7 files changed, 181 insertions(+), 24 deletions(-) diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Files/FilesController.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Files/FilesController.cs index 4314bcd0..3e58f78a 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Files/FilesController.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Files/FilesController.cs @@ -983,5 +983,42 @@ namespace WebsitePanel.EnterpriseServer } + public static int DeleteDirectoryRecursive(int packageId, string rootPath) + { + + // check account + int accountCheck = SecurityContext.CheckAccount(DemandAccount.NotDemo | DemandAccount.IsActive); + if (accountCheck < 0) return accountCheck; + + // check package + int packageCheck = SecurityContext.CheckPackage(packageId, DemandPackage.IsActive); + if (packageCheck < 0) return packageCheck; + + // place log record + TaskManager.StartTask("FILES", "DELETE_DIRECTORY_RECURSIVE", rootPath); + TaskManager.ItemId = packageId; + + try + { + + OS.OperatingSystem os = GetOS(packageId); + os.DeleteDirectoryRecursive(rootPath); + + return 0; + } + catch (Exception ex) + { + //Log and return a generic error rather than throwing an exception + TaskManager.WriteError(ex); + return BusinessErrorCodes.ERROR_FILE_GENERIC_LOGGED; + } + finally + { + TaskManager.CompleteTask(); + } + + + } + } } diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/WebServers/WebServerController.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/WebServers/WebServerController.cs index a703fa4f..8966ac3a 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/WebServers/WebServerController.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/WebServers/WebServerController.cs @@ -599,6 +599,14 @@ namespace WebsitePanel.EnterpriseServer // web.DeleteSite(siteItem.SiteId); + // Delete WebManagementAccess Account + WebServerController.RevokeWebManagementAccess(siteItemId); + + // Delete website directory from file server + // This will remove the hard quota as well + FilesController.DeleteDirectoryRecursive(siteItem.PackageId, new DirectoryInfo(siteItem.DataPath).Parent.FullName); + + // delete service item PackageController.DeletePackageItem(siteItemId); diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/OS/IOperatingSystem.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/OS/IOperatingSystem.cs index 73088563..add15c94 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/OS/IOperatingSystem.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/OS/IOperatingSystem.cs @@ -28,6 +28,7 @@ using System; using System.Collections; +using System.IO; namespace WebsitePanel.Providers.OS { @@ -82,5 +83,7 @@ namespace WebsitePanel.Providers.OS FolderGraph GetFolderGraph(string path); void ExecuteSyncActions(FileSyncAction[] actions); void SetQuotaLimitOnFolder(string cmdFilePath, string virtualFileClusterName, string folderPath, string quotaLimit, int mode, string wmiUserName, string wmiPassword); + void DeleteDirectoryRecursive(string rootPath); + } } diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.OS.Windows2003/Windows2003.cs b/WebsitePanel/Sources/WebsitePanel.Providers.OS.Windows2003/Windows2003.cs index 0965df57..1d37b8b3 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.OS.Windows2003/Windows2003.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.OS.Windows2003/Windows2003.cs @@ -215,9 +215,9 @@ namespace WebsitePanel.Providers.OS FileUtils.SetQuotaLimitOnFolder(cmdFilePath, virtualFileClusterName, folderPath, quotaLimit, mode, wmiUserName, wmiPassword); } - public static void DeleteDirRecursive(DirectoryInfo treeRoot) + public virtual void DeleteDirectoryRecursive(string rootPath) { - FileUtils.DeleteDirectoryRecursive(treeRoot); + FileUtils.DeleteDirectoryRecursive(rootPath); } #endregion diff --git a/WebsitePanel/Sources/WebsitePanel.Server.Client/OperatingSystemProxy.cs b/WebsitePanel/Sources/WebsitePanel.Server.Client/OperatingSystemProxy.cs index d641b6f1..34be86c2 100644 --- a/WebsitePanel/Sources/WebsitePanel.Server.Client/OperatingSystemProxy.cs +++ b/WebsitePanel/Sources/WebsitePanel.Server.Client/OperatingSystemProxy.cs @@ -63,6 +63,8 @@ namespace WebsitePanel.Providers.OS { private System.Threading.SendOrPostCallback FileExistsOperationCompleted; private System.Threading.SendOrPostCallback SetQuotaLimitOnFolderOperationCompleted; + + private System.Threading.SendOrPostCallback DeleteDirectoryRecursiveOperationCompleted; private System.Threading.SendOrPostCallback DirectoryExistsOperationCompleted; @@ -146,7 +148,11 @@ namespace WebsitePanel.Providers.OS { /// public event FileExistsCompletedEventHandler FileExistsCompleted; + /// public event SetQuotaLimitOnFolderCompletedEventHandler SetQuotaLimitOnFolderCompleted; + + /// + public event DeleteDirectoryRecursiveCompletedEventHandler DeleteDirectoryRecursiveCompleted; /// public event DirectoryExistsCompletedEventHandler DirectoryExistsCompleted; @@ -370,9 +376,9 @@ namespace WebsitePanel.Providers.OS { /// public void SetQuotaLimitOnFolderAsync(string cmdFilePath, string virtualFileClusterName, string folderPath, string quotaLimit, int mode, string wmiUserName, string wmiPassword, object userState) { - if ((this.FileExistsOperationCompleted == null)) + if ((this.SetQuotaLimitOnFolderOperationCompleted == null)) { - this.FileExistsOperationCompleted = new System.Threading.SendOrPostCallback(this.OnFileExistsOperationCompleted); + this.SetQuotaLimitOnFolderOperationCompleted = new System.Threading.SendOrPostCallback(this.OnSetQuotaLimitOnFolderOperationCompleted); } this.InvokeAsync("SetQuotaLimitOnFolder", new object[] { cmdFilePath, virtualFileClusterName, folderPath, quotaLimit, mode, wmiUserName, wmiPassword}, this.SetQuotaLimitOnFolderOperationCompleted, userState); @@ -386,6 +392,57 @@ namespace WebsitePanel.Providers.OS { this.SetQuotaLimitOnFolderCompleted(this, new SetQuotaLimitOnFolderCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); } } + + /// + [System.Web.Services.Protocols.SoapHeaderAttribute("ServiceProviderSettingsSoapHeaderValue")] + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://smbsaas/websitepanel/server/DeleteDirectoryRecursive", RequestNamespace = "http://smbsaas/websitepanel/server/", ResponseNamespace = "http://smbsaas/websitepanel/server/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + public bool DeleteDirectoryRecursive(string rootPath) + { + object[] results = this.Invoke("DeleteDirectoryRecursive", new object[] { + rootPath }); + return ((bool)(results[0])); + } + + /// + public System.IAsyncResult BeginDeleteDirectoryRecursive(string rootPath, System.AsyncCallback callback, object asyncState) + { + return this.BeginInvoke("DeleteDirectoryRecursive", new object[] { + rootPath}, callback, asyncState); + } + + /// + public bool EndDeleteDirectoryRecursive(System.IAsyncResult asyncResult) + { + object[] results = this.EndInvoke(asyncResult); + return ((bool)(results[0])); + } + + /// + public void DeleteDirectoryRecursiveAsync(string rootPath) + { + this.DeleteDirectoryRecursiveAsync(rootPath, null); + } + + /// + public void DeleteDirectoryRecursiveAsync(string rootPath, object userState) + { + if ((this.DeleteDirectoryRecursiveOperationCompleted == null)) + { + this.DeleteDirectoryRecursiveOperationCompleted = new System.Threading.SendOrPostCallback(this.OnDeleteDirectoryRecursiveOperationCompleted); + } + this.InvokeAsync("DeleteDirectoryRecursive", new object[] { + rootPath}, this.DeleteDirectoryRecursiveOperationCompleted, userState); + } + + private void OnDeleteDirectoryRecursiveOperationCompleted(object arg) + { + if ((this.DeleteDirectoryRecursiveCompleted != null)) + { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.DeleteDirectoryRecursiveCompleted(this, new DeleteDirectoryRecursiveCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + /// [System.Web.Services.Protocols.SoapHeaderAttribute("ServiceProviderSettingsSoapHeaderValue")] @@ -1984,6 +2041,37 @@ namespace WebsitePanel.Providers.OS { } } } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")] + public delegate void DeleteDirectoryRecursiveCompletedEventHandler(object sender, DeleteDirectoryRecursiveCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class DeleteDirectoryRecursiveCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs + { + + private object[] results; + + internal DeleteDirectoryRecursiveCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : + base(exception, cancelled, userState) + { + this.results = results; + } + + /// + public bool Result + { + get + { + this.RaiseExceptionIfNecessary(); + return ((bool)(this.results[0])); + } + } + } + /// [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")] diff --git a/WebsitePanel/Sources/WebsitePanel.Server.Utils/FileUtils.cs b/WebsitePanel/Sources/WebsitePanel.Server.Utils/FileUtils.cs index 77d6d45e..06433897 100644 --- a/WebsitePanel/Sources/WebsitePanel.Server.Utils/FileUtils.cs +++ b/WebsitePanel/Sources/WebsitePanel.Server.Utils/FileUtils.cs @@ -846,30 +846,35 @@ namespace WebsitePanel.Providers.Utils cat = null; } - public static void DeleteDirectoryRecursive(DirectoryInfo treeRoot) + public static void DeleteDirectoryRecursive(string rootPath) { - if (treeRoot.Exists) - { - - DirectoryInfo[] dirs = treeRoot.GetDirectories(); - while (dirs.Length > 0) + // This code is done this way to force folder deletion + // even if the folder was opened + + DirectoryInfo treeRoot = new DirectoryInfo(rootPath); + if (treeRoot.Exists) { - foreach (DirectoryInfo dir in dirs) - DeleteDirectoryRecursive(dir); - dirs = treeRoot.GetDirectories(); + DirectoryInfo[] dirs = treeRoot.GetDirectories(); + while (dirs.Length > 0) + { + foreach (DirectoryInfo dir in dirs) + DeleteDirectoryRecursive(dir.FullName); + + dirs = treeRoot.GetDirectories(); + } + + // DELETE THE FILES UNDER THE CURRENT ROOT + string[] files = Directory.GetFiles(treeRoot.FullName); + foreach (string file in files) + { + File.SetAttributes(file, FileAttributes.Normal); + File.Delete(file); + } + + Directory.Delete(treeRoot.FullName, true); } - - // DELETE THE FILES UNDER THE CURRENT ROOT - string[] files = Directory.GetFiles(treeRoot.FullName); - foreach (string file in files) - { - File.SetAttributes(file, FileAttributes.Normal); - File.Delete(file); - } - - Directory.Delete(treeRoot.FullName, true); - } + } diff --git a/WebsitePanel/Sources/WebsitePanel.Server/OperatingSystem.asmx.cs b/WebsitePanel/Sources/WebsitePanel.Server/OperatingSystem.asmx.cs index 3e24a15e..d226536f 100644 --- a/WebsitePanel/Sources/WebsitePanel.Server/OperatingSystem.asmx.cs +++ b/WebsitePanel/Sources/WebsitePanel.Server/OperatingSystem.asmx.cs @@ -550,6 +550,22 @@ namespace WebsitePanel.Server throw; } } + + [WebMethod, SoapHeader("settings")] + public void DeleteDirectoryRecursive(string rootPath) + { + try + { + Log.WriteStart("'{0}' DeleteDirectoryRecursive", ProviderSettings.ProviderName); + OsProvider.DeleteDirectoryRecursive(rootPath); + Log.WriteEnd("'{0}' DeleteDirectoryRecursive", ProviderSettings.ProviderName); + } + catch (Exception ex) + { + Log.WriteError(String.Format("'{0}' DeleteDirectoryRecursive", ProviderSettings.ProviderName), ex); + throw; + } + } #endregion #region Synchronizing From e2b94badfddcfa16285b45f7726ba9950694362f Mon Sep 17 00:00:00 2001 From: rdolezel Date: Tue, 18 Sep 2012 21:08:40 +0200 Subject: [PATCH 05/13] Merged with the latest changeset --- WebsitePanel/Database/update_db.sql | 60 +++++++++++++++++++ .../Code/Data/DataProvider.cs | 12 ++++ .../Exchange2007.cs | 41 +++++++++++++ 3 files changed, 113 insertions(+) diff --git a/WebsitePanel/Database/update_db.sql b/WebsitePanel/Database/update_db.sql index 4443fe81..08746cc4 100644 --- a/WebsitePanel/Database/update_db.sql +++ b/WebsitePanel/Database/update_db.sql @@ -5211,6 +5211,66 @@ GO +IF NOT EXISTS(select 1 from sys.columns COLS INNER JOIN sys.objects OBJS ON OBJS.object_id=COLS.object_id and OBJS.type='U' AND OBJS.name='ExchangeOrganizationDomains' AND COLS.name='DomainTypeID') +BEGIN +ALTER TABLE [dbo].[ExchangeOrganizationDomains] ADD + [DomainTypeID] [int] NOT NULL CONSTRAINT DF_ExchangeOrganizationDomains_DomainTypeID DEFAULT 0 +END +GO + + + + +ALTER PROCEDURE [dbo].[GetExchangeOrganizationDomains] +( + @ItemID int +) +AS +SELECT + ED.DomainID, + D.DomainName, + ED.IsHost, + ED.DomainTypeID +FROM + ExchangeOrganizationDomains AS ED +INNER JOIN Domains AS D ON ED.DomainID = D.DomainID +WHERE ED.ItemID = @ItemID +RETURN + +GO + + + + + + + +IF NOT EXISTS (SELECT * FROM sys.objects WHERE type_desc = N'SQL_STORED_PROCEDURE' AND name = N'ChangeExchangeAcceptedDomainType') +BEGIN +EXEC sp_executesql N' +CREATE PROCEDURE [dbo].ChangeExchangeAcceptedDomainType +( + @ItemID int, + @DomainID int, + @DomainTypeID int +) +AS +UPDATE ExchangeOrganizationDomains +SET DomainTypeID=@DomainTypeID +WHERE ItemID=ItemID AND DomainID=@DomainID +RETURN' +END +GO + + + + + + + + + + ALTER PROCEDURE [dbo].[GetPackages] ( @ActorID int, diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Data/DataProvider.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Data/DataProvider.cs index b102fb37..3fdd6f11 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Data/DataProvider.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Data/DataProvider.cs @@ -2153,6 +2153,18 @@ namespace WebsitePanel.EnterpriseServer ); } + public static void ChangeExchangeAcceptedDomainType(int itemId, int domainId, int domainTypeId) + { + SqlHelper.ExecuteNonQuery( + ConnectionString, + CommandType.StoredProcedure, + "ChangeExchangeAcceptedDomainType", + new SqlParameter("@ItemID", itemId), + new SqlParameter("@DomainID", domainId), + new SqlParameter("@DomainTypeID", domainTypeId) + ); + } + public static IDataReader GetExchangeOrganizationStatistics(int itemId) { return SqlHelper.ExecuteReader( diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/Exchange2007.cs b/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/Exchange2007.cs index ba51c9ce..119233ae 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/Exchange2007.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/Exchange2007.cs @@ -230,6 +230,11 @@ namespace WebsitePanel.Providers.HostedSolution { DeleteAuthoritativeDomainInternal(domain); } + + public void ChangeAcceptedDomainType(string domainName, ExchangeAcceptedDomainType domainType) + { + ChangeAcceptedDomainTypeInternal(domainName, domainType); + } #endregion #region Mailboxes @@ -5954,6 +5959,31 @@ namespace WebsitePanel.Providers.HostedSolution ExchangeLog.LogEnd("CreateAuthoritativeDomainInternal"); } + private void ChangeAcceptedDomainTypeInternal(string domainName, ExchangeAcceptedDomainType domainType) + { + ExchangeLog.LogStart("ChangeAcceptedDomainType"); + + Runspace runSpace = null; + try + { + runSpace = OpenRunspace(); + + SetAcceptedDomainType(runSpace, domainName,domainType); + } + catch (Exception ex) + { + ExchangeLog.LogError("ChangeAcceptedDomainType", ex); + throw; + } + finally + { + + CloseRunspace(runSpace); + } + + ExchangeLog.LogEnd("ChangeAcceptedDomainType"); + } + private void DeleteAcceptedDomain(string domainName) { ExchangeLog.LogStart("DeleteAcceptedDomain"); @@ -6018,6 +6048,17 @@ namespace WebsitePanel.Providers.HostedSolution ExchangeLog.LogEnd("RemoveAcceptedDomain"); } + private void SetAcceptedDomainType(Runspace runSpace, string id, ExchangeAcceptedDomainType domainType) + { + ExchangeLog.LogStart("SetAcceptedDomainType"); + Command cmd = new Command("Set-AcceptedDomain"); + cmd.Parameters.Add("Identity", id); + cmd.Parameters.Add("DomainType", domainType.ToString()); + cmd.Parameters.Add("Confirm", false); + ExecuteShellCommand(runSpace, cmd); + ExchangeLog.LogEnd("SetAcceptedDomainType"); + } + #endregion #region ActiveSync From 867aee9835ef46dc7a255980ea03e57fc905533c Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Tue, 18 Sep 2012 17:48:14 -0400 Subject: [PATCH 06/13] Merge --- .../WebsitePanel.Installer/Updater.exe | Bin 199168 -> 198144 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/WebsitePanel.Installer/Sources/WebsitePanel.Installer/Updater.exe b/WebsitePanel.Installer/Sources/WebsitePanel.Installer/Updater.exe index 3876760880c4d368fe9b30a0f25615bd1c256998..29802bd2b9a5e9d8d83ffd9c8dbb78e5bbe7c297 100644 GIT binary patch delta 29104 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

NGkq!Te#nb#ltQzB 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 delta 30110 zcma)_2|!d;`~S~5_c9C&BEvQd0}T5NJK_R@0s=0n34)4=iMg-1<&xS!7+Gm*R~xg{{;78n5kD6QBRZ-j0+a}vK|_@% zXq?wykk$&Ozm=D00wa>rKx3&^`Hsd1XSgUCJ&FGLE2n3{RNGQZYLP&3%?134iVCj`n zl^O^WO{FJ4#B-k_eHetnBc!(&Cu@m=7x5o+@C>m~3n&*o@XED>%n;2h2Q~Kg&HyHw z=E|scs06q3T0dfsCrq;GRA*soqvHco9U8*B9cl}iyfdQE;nUFdH1KaJ_-_gghb9n% zPeuYyR_Vjt5>4RW6pcw=vC0+@)xv8MblQYUUkLkPt+esH0nG({!~$nS*)p?16QJtB zHa~u3Hj|kb&Wtv_$`B28i6={mGEs`m=UvA;A&6Tc9FiJC&Ou2~C#dgCC|VA#492W8 zp=^0lPhJay>dVLvMEOD*>>yq?6HtIguW6sj+vqhJ3ib~0)XV=EpbA6}F?x^5FiX5E zEj&M)2|i@KXC(|YglsT=-T_)qoE!mOOsm(b)vyI%L$FHWLm#QrDH!GEN9z*1jYxO z%jb-P2s58e8t70%bAMyUl5?q$D8Ps4eQeOBn&zxfJUIuw3-LJ00WFvfI#q*10MRfY zBoBIt|HQ)Y92l8*;g@@Z5uzcfp5!2ewGKX9BzUy9+M7~kI(X4}29L&R8T+auUAHmF7x)#gbyA4 zgy#TTobsIq)B$4A&)+gM5c2cpWvHjM=ijoAHfbI?2Ln$6WCGJdbc9HE4$dd?H_RD0 z*}^ia&`Cp6H% zP?S33c|F~&So=sT9JrADe>H=gegC{j_C7eM3 zFyiWE!1Bgn#{9(a3bo7l&SVC^ueP&E4q-!t7ief%w>URT%A-u1ISiJ z6pdGha2TgtZeuf{IJq(p!s-HC*@;IhgS>(r!Wixo?ln0dVk-;&$uX&pL6;T&6Jgy6 zV;o*Kxie4L<)3(SW!HZoxU!oH&=fh`FWmNsUmiK>1Gis?S|Mv4cWijXF;8izeC!`z zhRW^_gD4WZgqLD`q!b=G=?ix$3@?|~WxNo-M+(vLl)-BCmGRz&-q0U#4Us2ZcqlWE z2=D%H)#H&N&F#i4jXaBbHAWwXN;pHIn~!-Lpqt^swKEr_C~tBvh_=CU1S4ax730x* z3hHKE3=;sWXX}lzwmdkf6;g+ci5MJD97JZam0;RnTd6qq!Q&(*!AYYIUa-Rk^9+mY zry9**6m?~PYhcc6CYOQ5)*sC{UxF*2KnS+s5qCJFi4D#!Z`jemLgP&)L%TJ$fjk&b z9^G5Y1d1lmyL$4hAMt~EY$O(1xH zOO5Q_-=RH{uqqx4CmZZcbp)mcltT2(_7txUVUt$!_CtrmhKt!Ectzp-nqQ;PsS2h*$ z2P&WY*bTVfXyKJ~634FD7NpP?|IHSxboj3}gEHg4+KkGU|7tTScUss({=F_TiGq5X zdE1m!U$aApi>IgB=kbIE@=J^cI)lIMfSJzU%J5AvbTeNP)nVidIgIY#nq){jc?|T> zY;K3a50}Y=;Q6q)Q#FfZ8!P%&?b?<&W){^a%!U%~6eb2-AK)F!6j<`9j?Dyv%seZ{ zK~~So@u-!k6F?_-fI=%_S=Xq0L)Ec{z;ev5n$WIWzO5YYY0b@TVaQ~UKz=FXO~baq z`9$EV!rKNT{U6%a%H1|@hqm>EwwbVPu&I>Z^fbux;37lc^fY>ifa=OuwvC1BFrQHm zH#%G`3})wlY%`Dl?`?)lgr+k0f3z8PLBxuFCyjvG8L)QVnqWz3YU!8h?gMpVCqpj; z+S*_r@X>{ZoWS|XdjJOX;T}*@{eocWe8{KTVl^Q&4_o(e;)Utm0$e1HF(7o=y2*@xzv&PcRz4CKH?_^{EUXRM>yhU zaKzwb{68GQ$@+++*hebFt-&kaf>YKs(p~=eg0fW3!cuu(1PgGV1#d!s!GTu`p zRS69Yp=nBHU?pv(tP5;M)0K;$trb&HJK9Dm4vL~}m8U`5Da(U;(G1s(pe~eVDrts( zw7v48A&O=x8w|T?wldK;nRZaF7)Q{KN>5V*&2f2{4V308p&>amPZ=1}i*`~rgtVji z%9W5cw7~VErGe5yB`>Umc2<^zrO+TbZPV#sWkcI(^eIe_Tw6Loj?pfCP86kMls35~bgc4XZUY^s@qnO%OS(_Hqh zIxU^)yl+*HS{@G(BKi2*0^RrwT99;O2p9j=<}{GhlWsEtK1m&F@3@H*6?c@ zI#-!Lt`~h#IXCV#`jRqZd4rQu>O^K1rf`2OTkK%;HCLu{2&F5PRm&dGRjyUbQy6{S_2p|&^EZ?>tIpFpCFu1M zx>_0a`ZW5ca`E*ebd9po2mqXuHOsgNzcOW)W$$B%0)q=J$^NqGKso|Uwe)+nYwN00@9kDZG7pkG{k9dNnfUxhAl0r(~pKa zds=Be4Qp6rr6r7pH(ZINH@&H~;aC#Asi6_hPg>IlG_v87HZ;eRMmhh=rf<;bhE*NF zBaLxh=}1#(Y(r2E?IqJV=dgS_liC_C=0ma6-jG&EcT*bg%|%(k3+o^`Ow$8QL3id-bLvRBpw2b_umO z3rgr(n%;1ugbty!bwkfSw3kHNI9HWH$!(oK@CS%fp8D>HMkw$xIBdp6=hd2^j}y0YisTyRR=*yB#m$5@Q>$YadgS=^0H z=Ao86?lC8OjK!;l=XsK;kFnOylHM$?!J|8yZ}OS%ZI!66{<-=3=N36%AIc1LiSxsu ztc%wwUx;0;f9@@(W*D=^uhUp5^{-mxVP(|Ehl9RqH6EVZpdL1QX zlxjYw9xgg3k7VZ^vM2LpvM2S|OP+ATd&>TyjQIw7`l>(7zu4E;f1v+h|4?5qPY-Wz z7V6<28tCci?O$~^$bTHP;1K*{-u|Ipo|;f!tuOQS1y7JzV*XW|;GYLLuiD}To}>AT z@lYav@lb((YyN_QS*XRo>KlzGgKX!to>Hg{!Altk z>Pwy(v1gz^Sv=xj5WjoG7{|aca$>{}Bm9Xpvf@d95vZa;K+8W`gy5P+#)n$S8=p2Wh+s9kmM77uAZIf|`r^IO>z2xf(KI z6ffX8P+y{qsu`>ybr`d8)Cnkl->Bjt8uAtDcbMkRs67K)G7T&u8WJ?RA#o~u*28fk zsHAE?;d%n~8fp`&H|6m`pv6_upp+!jQ=o0=InWODB4}571+hq{;Q1_so zMr}e3l6l@N)H2j5s0%V4Z+E1$7!|vvsCNJFr%xz5v=BKi?x8;vLKJ z@ILA`)GtxL0hP!F)Egdg?(k3GLL!YGc~Hf>9-Tq|g6gU%DZF#%RkvumyVKh=tsvZ5 zQv~supc2Ui)sya;KA^oFc<85j0?g%_L7;;)yg$Z)N@Tib2I$^3!Soxw`5^A_<^y^d^(tzUH&hhvPU*Niz3xPiM2tG# z$>9(~Nh)er)B&LCl%Zt2t`At}fkK;fPSCe>d^om3UWt5;;qO5u@(cQ8KD<8ye7Mgj zpBjkgGeaU-J}W^T`920X^zz}EhxzacI0f}NpVbhq!)za-9z;Fmvku~aMEx6MG%Yqk z<@7ChFIrlhfK@NC1wSwHS|o!GZ}A~$ZHtdVH@5iHJ)m)HB@E~>M+<&9i+TyP`Rt5i zn;`xsxb9o^GwL6x_d%P}*gZZ3tA{UFZ&W|fwj{!r_fVSeZqUbkdApzTy7eNiX2Zpo>Lvx~deJq&MQ9Gb^2W__Y)hB?p9Ca{gan*1=zcf!ltwntmbroto>K4?U zs9&O`g5m#sAkky)Kt{=sQIYfQA<$=qmBlJGsr*HkVfYCw*j3G zF=^yA)HR^6p897RB(fR9A3OZ{iMJc!21aKEE0(h=K3|j;8 zAbkvKJjSG=wnr^MeH^tvC?&%J3L*VijF}Mt`yYwSL0F8s3UwW-3-!|gAINYt;43Kd zG8Xd_Y7;66dmf@M%o{Pdp_zG5x*3=F^)`&l5ob zxL5@cIjB#tqqs^R#K$`rH3Zd)8i$&MnvR-@nuD5;+7&d7^a$!@NGJV4B~k$~u#%#V zMxB5<6|J*S9jMO*4L3**G8fJ2q?nK4S5cjqNFC`_7_%DnZPfKa-$Ea34&v+lM?quY zT=)#)i>vmd9zy*Z^(5*A)GMerP=7*o`~nBH1uVrQauUFFlG?yP}I>5JWN2HiaHDRIn)v;q4ML3$O@Kus zA@nDAF=?SopqLEQ9MG;-xHm(pjrF08P)sS3Lf#K;0-7UeN9bP$Mm7sN3?w_qWq}tU zsfOGZbTd>odJ;eQSR0=wGSEn$ofauS z_!DEaYU>sjXM`sx;B#M|vM*2&X@n1NIaP$E7>%SnPNnf-ZH;CU?Xao%d{~w-gk-p> z(O@A%k@k=UVYx;NSubo(C@_>vN#OYwk@vz1jiF>AQVq5+l&nNjv>U^^fvr){p0Hj( zfr&hyqCFbc2gsTT&o>aFc1;+Wg~nR#*|2hB7+ERkGE^;$Gzz*ER$&Y$f$(q%*6j6QBo2!c!=mJ_d>* z^(v8X!>1Z!$yq@^g*O^v$#pl)0$VoR2In2@ZJlL|Ba4x0NgHdm(MB!^>STS+1MvY9{lLu$#>)@8=lfF6D%?B9ALf3AhoUV7U4z7ZaN;p70kXx(DWQ4#1z>u1J% zk_%6*z&%eG(F4W;QifEk{lhxd*j1$DgI4b*?(}QpV{R`Ot*4DW+{Aqrk+~1~EGBhG z4({}tvCkt;n~6KUW$fp6bJ6;%vA>(R(}CpZLr$M0*WDE*CjP0!Kdo;j?o&4L8@<>U z4rsm3G@==y^+wZJL23)fxoxMd;igJAU9`rSCc25|dz!!~!jF0$OeIz~rJ1IZ45V5u zi^wodC%J+g0TJ1NJp@KaKsvFe1?n^R2-2DG)GW*#N(!!WS*eW z5hXy&1Wk`9H_jq;g62kK0j(Fb%n?CMv&m+G8zTAx?G*GG*q$Z(1)Txgv*b9E+Cm38 zi^Lb*G?Rl|M^Z>*#FM6K;?tVeQ<666)>c-r&=sS+3n#+S)T zB(;cnWG#|f#5}T5qzsF!GQC1h3ZjuOnHG^oL4iQ862CUhL$T1LkX$!48kUi+Zc1~Q zmXT6Kg?L52W?Dh!38Im2n_egNf&ziwAbXH%wf4viQyn>k#4EZUNQQ^i)Ui)9y-obw z)M%(DaL&SyLfS`eHPw?MK|O&S?~%Cz2LirNb_%MD{LHk8TozOf!vK@UJ~f0%cgzAili2JfF!zYjfR7ywVSex2TATjDG!kzZd;?_Fe!CYmhmvD za6FXs2pQ`(HX4qRDQ?O#9wSw5x@`K2%zG%`aXu>Wv)l7R2eM^?PQ#Kk- zk~*ZlJYCoMJ7m!ppXGke7 z^s1LLWIGb~Ld|E%6kPUIFXzZvB-P7z2X|90!{M`jtnBlEI(@v77FWG9m9^gKC) z#GS4&ULY2{dZk{(E^)9*@2MTG2j$$ivlN@qWmhmRJrIPjuXwxmC&Bv753DBlnqyT9Vsf~&? z|46puMNci_Cvp<0n(*QMi8LYAlBH2e=AVh&lY4P+Y-hert|RiKznOj^+Q+d7@@7;g z^RHyAn~Kbhq-!s3Q_t<+NfDAlHbxCH|4!-!eHt~~{0G_Wrt#*xq_pUteD_H?lHwqr zM@=)|C!19yUjzL`e2RI}rQ`QbP0yPttrHX&{j!`CV!E+K=W-!Xg9DJ5#sanbLab+k!PEszhL zRjS(Fh;A^qpymBk+8DjV>`SjBEhW36KR36emNITzM2MhpEFWOG;MTKqr(7SI~~Alx|F;b;}sH1dkA_j zMjv9Mf#uv*tNkeEnlXW<3i<*m1F2g3bxejSfffkcO{7vm+Sn|}w_Z(2f?^vDiPUeP z>N7s}n$eL+69u*dOr%{^B6+b_%!%|Y62HWTge1}1ZnA}>(da?kO*QEqd(+&SR#m7p z3aA}jJ6NTv*k8@rulTgN;qoy z^sJy>FiiRMf*?L<`Sg~^#|JH+-WN7LX!%qgh9zkEpyg8^L445isUuKD!bh!uS_JV? z>rA7O)HA&cEkasK{uSFgqzkPQv^6#>q$_PboEK58-5FaL@))f^swIbGy8&GmbPlKo z9f^D0T5<~p=5bo*K&&Qz#1_L7ueOog4WH|MLyBluB(>X0XuTjlpZiklD4udJ_Dp}8 zD2Vq=f0`hqP8D@=@GuNJ%DQ zfn-0>5bC3n_8X}7a2f~%?XT6|kIMy&7RD%B1w56UD5#4q7bsiM7~4xBBWZ!48McK$ zJp|3QEd?4X$O&FX(XoQw2QQ=OVx$`F=eBa=Xu6V<1B&N6ztME9NcycU3n*g})?0ho zwkl){%@x#WyJ8+gM+%bd6~?i2f}lwIn;~QAbU{h>dY~#nIref$Iag43dlt|#BzXVV z&%Qon9IX?^QAqWIW`mn?bfch`khTh{vu^=g>SVQ|AKHm&Jk1bv04Z0{clM7$#?v}M zzuGe(WxYxc?Vr$!@pPjw>f$-=6ciS}12XOxloY=ksA!5>AYa)k>3TugkZ%IrDySqr z7wD*<(eVdDCeo9Fo{K*WbXkyNMf~xQN%WS$4e_Uengs0xr<1Atv|8Y~_=_QvsgIz0 z@mGP2f(!|_LZ(owpoD}wK#78K5-N;O(_BIQ6LNuu3YzRl_#8g!e2ns1#JP_ zG+KqEko^g=Wg5LL=tP3IWd^QwPfey46humRIQ^H}$YMme7*|D-%mBPTJ(A{y_3GycN~tnZ*8gY~kyq`GSvYK|q8%=-1|e;ogG8#58V&DKNAB|~Du@dOy_1v$8MA9un=9!V%X_r!1(iO7 zl<(8Pxtw5kmsDeUpWc6klS0lW&9`i%*$Y(LZ%Jc9KA=626xfz6vAF1UK~nM?mMzri zSg0lqOn%GqAzh4AL(-Gi!?!(dFXFapQkcBSvXxq1RcT!ER?A0pnWEBMpdEDOVwK(i z`iy2QQRx$)y|iknN+*H7pyf_ZHRSi?E9S#=q*HXTKIMw}2tB@1P1-tTm*pr;U9D1n z${!)eXuY7alxxOgbm1D+HZi3FXx>^*u$fMgfmR|_lSN?riXIhIpOS6*ir#ul&G$vh zKFini(7Sm3t0pH>GECplqW4te_bH8rZ|HTT8uDvO7qBf`ui8lJ6*D|S`JqZJQx99d zr8cA**y&y|pQN+4s`zqVB%tr8 zaR;YGxCy^Ni;!x`OR4897ihVgE?X|rWrAJ>+a6}lwms+wS^_Jx-J?W+< z%Qc#~6HIXZBlW2)^g7Mp2($_41}zX&pXw9(11)lsA@mlt?rKiy6Z$i)67&fae}~R< z(`Cyqbf=*GU~8m@+;rLU8$F2x@BdDwW*PsWmxb|UYP_Y1T0c{ZxRe?ddXFXw`VHtW znjuI^O9~~dtDD+}N^Gv1qC!2{$labZA1OoPPZ{CG>|n3 zicgCQH86RP>PAZI6l!MKg2I48*%YK|l9krQWMxgl)-&y#C4$MHtND7SUA9CrKS57` zEt-`hRTIa!v>u@`Y`Va4Y5hWNEN~xY)Yhg|7!#RAkdl@QWD~@8!ngq>jl?yg`zuJfV>feqT1@WtYJC-fzomR6Qp&6_| z;Eq-`Kt+Q1wk(rr52$YVwk(tR37QN$gG^==#CHvuELzYvtzHUk&k_aQX|)h2LlEDT zX0cpBd{gSkVm$=5NG~^Lvr<9U^emt%L432-fo&ATH&h+jRzZA2)sgKH#P?G{) zTB=P?cZTM(9!NE$b2_{mWMwL8`=_r8$!FVzZ6w+p%MN0J@Rlpfn9r<-nrT&N0o&-N zMnh*7_+_*0uaM5H%1v*Dc46AX&9)7p-Pkgf$av_(9_%DiHJOqAR%lOFa0F9oUr65? z+KZJs1TIYfG_;7#aU0KBdb6X))T9g3_l1_QTY{FS9|`TlQomAd>(fsHrFQ|E=62@5gR`h1b8UbOC&**pHE~xzjyBxyF8M4pO!DTj;hj zmUx`os&l&h%$ffUNLFre*6(q5auHK~|tA*m_LKKY;itbO4L~2ECBn z)_;UP$?Col*S{XEOH6~A-wD-N*1FN~6dNmOIMRL~Uc}VaBZ zKqFZ;5Z{Ufv82>lOYFFt%EIQc!0(&$4GLSpx~k-W zHwYubUS)d_m%=7-eAr@k+)Yo1En%14R1@Z8jc%GBww%eAxKp0*^{|!9&rS7VuQQ9A zwuP-`HaG1JTgx^Ia%9Au4y$K7-Nx_3*0G~*x)b&uyWpn#VH?{vA$$u9bW>*dR#xw($HTX?t zK)cyaLG9X34d27g3MvBI=WOeBHRUj%y)5?!m1Y9%V_k2mv=nGR)80~PU0cVj@B^$X zVh!2aw!i5ht58Y1uPrehVpEWolGANv;~`e%ra9qXvfFNYDf|fA`6G8)3!j<6hc|5K zZBEtX2GV{(O-QA8np492zhi8_8?TtZV%lHSjQ;Jen7?MmUsXzLmti{2W(n%pZc+Gg zcCt~mJqh$J+xUm-^qF>9#?x%4n?fyT*ikpdTh6hwZYm3NoM+eFxIFxO*660X@GDGi zQk}lst}grr3q-0WZ?vlq|B-dQtJ>a-+7$i^8|kJ`!hdCR1#N5hMfh)QqnpNCerG2I z9f68AIau~R)ykCj)W8GDAHAWwcW{ZS-OpMkv6vb z9;ivAjL6_b?sG4T;3KWA7n3EQqz*!VF^akfH^ZWn=)QszgR+OtE-K*@7l! z{1mQ{E(og5_&r=J-9oA%uVma0_mJ z{{_XjlJt2tG|@(CO>PSRF1@N)Ecb@X`yP<@*7QNsZP-6 z85KseR4?f3j9j42f8+H}y~P?LwSK@0RBuIxN#!cxE!GHWtRQ}iHA0#th~Hw3kmiYe z{1$73v{KmkE!GHWryzdwIYK%rh~Ht2kWN0p>)&3y`5Y--5N`M_)@bQE(nWePqtOr} z-4-@}Upz+gBNQsCc4>@cK~g`kkCC<`Rg?Reua5GR)kL4k^QAIQH6#XU50HanyG*M! zMyimwQ6Zf&hZM~YZ z81i+O0^!L(Uf@8W9@1H(N~78jvG$bag&;Y!)7n=UAD0%ZsC^ZRe_X0l2{w=;t-Yl6 zZkl8*mbSZTwzX6`8N#-v>j=$ z*Rl5JtmC9Zg3hdf7Z%>LI8N*q)UZBh_m8ds>IIQV@Sn>yWk!;-4l|NqYqG zPZO%7>2|e$J7;B>s--HGa6lc^(mXeQWUY~wxoNMpR$A+(qt+LtJxJ<^&XwwosZUh!5IAsYwtYw1pB$#1e4O7Diq^9so)MI}CjuSw;C_ztGpYd&#w0(I#PPxXdQX*0fG!UMd zlIHb=@Bi@ylCMzPr1io$K0P*Ko0Qm3E&h|NcdZ{wW8t$yo{}$D+a;etDw*^drcb1T z3YA7?B}aTBl_II_-673EswSUjwTajv9UrQuJet)b;($~%OkDpiWetcpEX^9ujS9J& zH6h|#sSc@{w8+jjos|}k;5M~Q=cJWLY7yt8?2&3db9QyaIcX?T4T;FEjrdNgAFURc z2y|Z3j#E>%%bp)`L7KzK0R`q|FO9e)ZAYV8#1&}|l3K(SY5jPfvDvoSOEn-n-fbu%^l(}>?BBmYy*qH1>~E0UV>u9TtLw9jS}(_Ja|k(6aBIiQIB z5qG8iDw3D7GfelSlWsZ^aZkGLrXkiprTcC=9&ul4JsFE9e3twzl?hr2ULHt`1-*l` zRgep5k06ID`*g$u>A2f?F@ngK-E;%)qTYAYod{VDoWcu)36*^$!c(4rR7?1EQ!6hP zbODO+l8*|yncZmck{bmzWv{S$$(E>!!WdKzX{Gj#>@!G9-1e4w35x@x?ksKBT6E#oCc!vdCuz z^2@J9?lGMgsIJzba)ltiT8GM0kkrLGR6eBIaIp@P8wK&jI!ta7#24!@**XJ#;$j^p z7pSC##oA#ClY0o{t96*XRuEsU!{qfMBY&nRTs|&{FV>OrSwXm8mM;t9i*=0b^9(Og zU7l@nxgfqg+vW9w`10(Cmm3B0^*KS#p2;)9(`>MmCdy?<{H(YaktiQUdR}YoP+?4y z&mvW8TXpb`Oq0uJ@qE?Vj1JepR)wU#lSq>bo<$pZ42HM0+@o5hRY5=wc^;zr#7k@W zvLOCeqP5&8h_|=3d|wc6Z(G^tIn_;ZhjL>(d9I+*9WqSqdzrkTCgqpW_OhQKJ}~WNqaZ#o?PV(x?_j^kEP14$pe#dV2YIca z=&bO_9J%XU?sF+=lNA@4Cm%(+NS}v3%$MgnUgXA$Uaxe>Gv&(*RifWON9D`Q1o3x3 z`SMwj@?MA3$b9)S5+9gs$k&KeO=3DW8VY1^=zi$FnfPPpPgpw(8-M1$bz~QybbJaO z9y`yAd`$LxiC2cdjeIP!yPS)(l%#j;6Imn|A>qo_&~FEm%nmrKN&Ak|%<#qZjI~kuO3_y|EbdxyWMt7D_ktIf}g7G1~#pcyI2QWvnKjK&!pz z9;n1}NSb9_2O4i#O}^?lH*ypCzT<*OFLJBn=jLq?-)PuI_?~bZxes}Ffzu_CyNGwr z%E&a2pqx5TbIzK`1L)xxvE{6b^dYG^??+xFe86tNcTpM*qeym6w#hMybcI7VQkvs} z+6~L8fSOLsX*3j*X`o(oR?gN)_#<&SpGJDor8#S$mE+;jG%vb3XAi`@hcT;j4nTNw zPIPcJ`6#E{sHeMgjzH`A9q7SW-BG9$QD>l5ll|bo+Cfg_oR2ioOF35}BWQhSjv<+cDFksBD*jm*gX1u8T*Hw3~fA$>Qp9@ViO4~KIjql(c*H+c5d9#u_lLwtYw zS8gGwU*5FH{K;`M+Gtor`FCy>QT~0JMU;Qz zW)bDzv{_Dv<&{LOrsMJkMJ=bZAzTd;d2G~+wBEsMP3PoIiP}aN<~gEv(Up1UO}psZ zc@@T8baP%Rj6MHKiWmJXZ%!0^5)3or6g`}mVLC;>&Eu2qLf%V|t3Ff#y`Be^!0yd- zYZgq>`q0ZJt~X73#w)64tkY{z$6(sRlOraG$^zx9MFfWJ>_%i;V;b@5^k!5V2}5lK zYG;L=)`1Q{9gR90^|L%4Z_Zg4#b=CcNn8D+ut zMWb5C)lTOj{wAbPgqUnoB7yl7l}LW=^dqEv(CK}cp3`!EkGf0wBfZg>-a_R3_ahy4 zrp?|H-bFYSQzLm*#+$ty&_#Ws z*Rd7(13=g05019udm208%e5WvDcRYE{83Q35A!QQcjQ+X4?usUS?%oW{HG!2d(`^S z>S*4J^C0FYXoj8L%g->`87tuGgBpZtMNI(R#2l>)hFHD$^oc$NPM3pb7E~CkA$%Fm z^1YqvqKiq_f_I`Xvd0V7Llr9uK8W4~)<%OJ+kHcX`6Ib@!Y@a5!mmPh+$GovpH+6k zFLs;Q*n(}*cOm_!(NtQIzc1QLg89EKS}$>T5z^FxY`C2^2X$e=m(dZ@@`B@_Zxx)0 z=EcBz0NJiUH*P7o8Euk2Drf>dTtH*eFr0?rO!Srq3NuDJSKtHI8wJ;l-7vnt^h-fN zOg0(YF*L@D49j!K7U-hF%4jdrqL9zny`7?B(uk=rA!d{mSGWq!g0#YPh$%qr530u) z`12DO<}qnx9EQ2BW6u_5#n`163iCi06m|u*<@AcNGiPC6&^HSQ#*8H&6uuuhh4-Js zz}qx5W(rOpJKJ6e-38-1I_3b|SNKuL6v96ZoI+kmpBlr@g;`L*$-)d%8o5&VT#Ox8 z@}cC1!V2S1bZRI3!afvSpN|@g%A2tW3a$@b7Q?Ry{EJIh+r1UD9o4ZJFAVG0A5iPn z*hT9=--p(Bh{-aJlK2*e$8Upqezjdg%pOd?2QMUEbaeJEsFu`uFQ_?ZPE;vYcLw$E zd^lzXjq7|oW|x%G`84!UR_6;brJ@;UI$e!f4^^o*mO4m5=UZS@EvF|OgFrOt(KN|zGgg*oqQa- z^f-1kcbX6j?~h{k!l10~oECc-tc`}tIFy&k^3EBt$8g%NX76?$VqML)f>N3H?p^6K zC|)na{O=fRf~dmS2v8^zH4QZrH4n7W&<(@IsQpm~gTgfs!xKSsjWaM@jrt<$BG5*| za!}YwV0azsCQ#TtfOdl~8e!A{)MIG40oo(>4#wQY80x_@EW*}!K{(r_2W>RGD5)zN z+^TGN`665H;W+G(OeX8DgU;0b23n&FguhGvvMw1^(RBrVP4_tH8eKoo_jCh6UAiHl zAM56W?$*_7x{>a>6Pioppzb{A*SgD~XLK>161}902mM-?0(w(d3i_+=NzW*VS?`$- zF~=NmxTHG+`nB$Y=MYd2Z4J)`3fVv*n|2L^pVaP#_!`igy1AfV>t5AHNiJQ3HXrn& zwnF+-r}G*DVLz`L(Dq(yK!ArmX{!=7BtFd9;i#V6g0qRXUlxg_jCt91ALBvx^yR7=6ktx z%x^bnBItX%zMug<<$gE35`2dF4e>sxd)05Xce;<$Zw-WB_uB>GHGUUC-}9pmUAoT) zei5J_`Q?G`@~gHS)E)3!4SLvb7wFf17eP<@(ddJ^bAAz^-}~i(Uh^9addsgG^p4+Z z(BJ)bf&S@t5tQg@%t4)perHUAkGDQI{-CbAz5=vJUj^DnUkCbx{zAOtpl%R+#r&Xd zsNM=XN}mflUSE}z;4@iIk`sJ3=&L|~((eS#@~_B9@LAwr1^Sgg$xQGG3aA2oJfN=q zLEYqlouJbLtXT(jvjcKLp9`n}eIcL++YJb8$$UY2Sw{2tXlR#(K z9rl;)3*fcXzS91deFLPgjoV@W0&FMj=j=D_jyrbG_!ja0@waWYafWy+98=@7;&b9V z$M=QsZQB#^PsNXnpBi5qw=8~b{QCIq@q6NL$IA)62|)>Q39S+`6FMjKg5TP>K|tL7 zNYL>Kvl5<5Sds8i!p?-#?$`N*Uog#|3C%CczYfD+p*GLNe_kyT`70pNlsF3<{qxFB zEP&TziTx9^;%6lcNt~Woop{?eKXGwled6ha9f@BhUQGNk@qS{>a}r6u6Bn4AlyoiWR$Oc{cUqQ|ncO{j5QIl1PXG&#O+U zrzY1VFHFAeYkMvE&E$8Iw%O-ZjR2oJnAeHOhTgpOA-#E#aj0#3 ze+FT-C-N|+wD&%U8QJ>~=roL3*!wF8uj~CS=r)XT9O-=);1=qi7{yAsYfA|)G6}=k zCA`*;mGE{9LY-B@3s(E%c}%keW4<zptToV~bK=yxP8pTc)=A;g(rS??K9hQeNq{r6i84CumlwFX&^X2GHK6 zypd(44xVTzx}ILjTl_NW3eXecC@R~mC?ms&EkAA%R@aj&@<_-JL9tQnitx=1QL`U9_^Z(y1wGTfD z-7WZ!1$XSj*NN&r$qhf>VJ~Vr1V~w=hesdMhlF{SfLc9^K_fkbq&_6tlgGz;&ZZ|j zQ}R`^kwn0M*U^e(l3daS{!7YloLib$xZ`y4334v^a`H9!{TY7mCf^5@Q!Xd_z;7V@ zT2i7x?oH2!0s0G)f{GhhZ2P?16|B~>f!ITu{oei*-=m@y9Bz7U3!<2 zyU%ks>?HyBWqxl_7#zp*eOj$LM2Oo)ZUcAc!a=N7a zYs9~sx}=PSLHoDlDKjemXIz>y{T`bbM93ldzfzljzUSdkX;DNFJ8p3vzQ^KxL-U)B d Date: Wed, 19 Sep 2012 00:34:10 +0200 Subject: [PATCH 07/13] Removed character causing error --- .../App_LocalResources/ExchangeDomainNames.ascx.resx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/App_LocalResources/ExchangeDomainNames.ascx.resx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/App_LocalResources/ExchangeDomainNames.ascx.resx index 77fff6cd..8775c057 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/App_LocalResources/ExchangeDomainNames.ascx.resx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/App_LocalResources/ExchangeDomainNames.ascx.resx @@ -160,7 +160,7 @@ Change Type - ¨ + Change From 8eb4865510899a5fe84ad02a545956d0ad489ae1 Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Tue, 18 Sep 2012 18:35:48 -0400 Subject: [PATCH 08/13] Merge --- .../WebsitePanel.Installer/Updater.exe | Bin 198144 -> 198144 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/WebsitePanel.Installer/Sources/WebsitePanel.Installer/Updater.exe b/WebsitePanel.Installer/Sources/WebsitePanel.Installer/Updater.exe index 29802bd2b9a5e9d8d83ffd9c8dbb78e5bbe7c297..24807a2081e275d4247b2a6afb24675a28bad0d6 100644 GIT binary patch delta 45 zcmZqZ;c4jMnb5(^xgw&myS1BfYd6!u0)e9sK5;xNviDwna-M%9FOTi^m_nu{QvkOQ B6Kntg delta 45 zcmZqZ;c4jMnb5&(aX+B3yS1BfYd6!u0)ac-AAO5E&Hd+fDFDTO B6ukfd From f85d468b7ce84864d4da59b84125ece8be9cdc6e Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Tue, 18 Sep 2012 18:53:28 -0400 Subject: [PATCH 09/13] Added tag build-2.0.0.38 for changeset 47deeeaba0d7 From 39d94f06e263f61697dc644df64dda3f60430835 Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Tue, 18 Sep 2012 20:21:27 -0400 Subject: [PATCH 10/13] Update Copyright --- .../WebsitePanel.Installer/Updater.exe | Bin 198144 -> 198144 bytes .../MsFTP80.cs | 30 +++++++++++++++++- .../Properties/AssemblyInfo.cs | 30 +++++++++++++++++- .../Properties/AssemblyInfo.cs | 30 +++++++++++++++++- .../WebsitePanel.Providers.Web.IIs80/IIs80.cs | 30 +++++++++++++++++- .../Properties/AssemblyInfo.cs | 30 +++++++++++++++++- .../ExchangeDomainNames.ascx.designer.cs | 28 ++++++++++++++++ .../GlobalDnsRecordsControl.ascx.designer.cs | 28 ++++++++++++++++ .../WebSitesAddPointer.ascx.designer.cs | 28 ++++++++++++++++ .../WebSitesAddSite.ascx.designer.cs | 28 ++++++++++++++++ 10 files changed, 257 insertions(+), 5 deletions(-) diff --git a/WebsitePanel.Installer/Sources/WebsitePanel.Installer/Updater.exe b/WebsitePanel.Installer/Sources/WebsitePanel.Installer/Updater.exe index 24807a2081e275d4247b2a6afb24675a28bad0d6..08fe7cdcf3f29b3b4dc99f7ca361c466c00e0ae7 100644 GIT binary patch delta 44 zcmZqZ;c4jMnb5&hzOk{ZwTp3U7t^5vfr&qTS-B6$c}@$JV>JK9HD!BDA=8p60Fs6g AvH$=8 delta 44 zcmZqZ;c4jMnb5(+xuUVFwTp3U7t^5vfuj#TaXc%s_g;N+o_`}RkL~uDLZ&5C0H*#E A5dZ)H diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.FTP.IIs80/MsFTP80.cs b/WebsitePanel/Sources/WebsitePanel.Providers.FTP.IIs80/MsFTP80.cs index 1fbffbd8..910f18c1 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.FTP.IIs80/MsFTP80.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.FTP.IIs80/MsFTP80.cs @@ -1,4 +1,32 @@ -using Microsoft.Win32; +// Copyright (c) 2012, 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 Microsoft.Win32; using System; using System.Collections.Generic; using System.Linq; diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.FTP.IIs80/Properties/AssemblyInfo.cs b/WebsitePanel/Sources/WebsitePanel.Providers.FTP.IIs80/Properties/AssemblyInfo.cs index 8ae894a1..5bb54eef 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.FTP.IIs80/Properties/AssemblyInfo.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.FTP.IIs80/Properties/AssemblyInfo.cs @@ -1,4 +1,32 @@ -using System.Reflection; +// Copyright (c) 2012, 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.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Web.IIS70/Properties/AssemblyInfo.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Web.IIS70/Properties/AssemblyInfo.cs index ed50c061..23c091a1 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Web.IIS70/Properties/AssemblyInfo.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Web.IIS70/Properties/AssemblyInfo.cs @@ -1,4 +1,32 @@ -using System.Reflection; +// Copyright (c) 2012, 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.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Web.IIs80/IIs80.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Web.IIs80/IIs80.cs index 960487b0..db31084d 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Web.IIs80/IIs80.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Web.IIs80/IIs80.cs @@ -1,4 +1,32 @@ -using Microsoft.Win32; +// Copyright (c) 2012, 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 Microsoft.Win32; using System; using System.Collections.Generic; using System.Linq; diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Web.IIs80/Properties/AssemblyInfo.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Web.IIs80/Properties/AssemblyInfo.cs index 3e0804f1..f6b854c5 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Web.IIs80/Properties/AssemblyInfo.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Web.IIs80/Properties/AssemblyInfo.cs @@ -1,4 +1,32 @@ -using System.Reflection; +// Copyright (c) 2012, 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.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/ExchangeDomainNames.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/ExchangeDomainNames.ascx.designer.cs index a3ea96d8..7bad4113 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/ExchangeDomainNames.ascx.designer.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/ExchangeDomainNames.ascx.designer.cs @@ -1,3 +1,31 @@ +// Copyright (c) 2012, 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. + //------------------------------------------------------------------------------ // // This code was generated by a tool. diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/GlobalDnsRecordsControl.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/GlobalDnsRecordsControl.ascx.designer.cs index c0ce1e91..c3308c73 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/GlobalDnsRecordsControl.ascx.designer.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/GlobalDnsRecordsControl.ascx.designer.cs @@ -1,3 +1,31 @@ +// Copyright (c) 2012, 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. + //------------------------------------------------------------------------------ // // This code was generated by a tool. diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebSitesAddPointer.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebSitesAddPointer.ascx.designer.cs index 5ea5bdeb..555da404 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebSitesAddPointer.ascx.designer.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebSitesAddPointer.ascx.designer.cs @@ -1,3 +1,31 @@ +// Copyright (c) 2012, 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. + //------------------------------------------------------------------------------ // // This code was generated by a tool. diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebSitesAddSite.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebSitesAddSite.ascx.designer.cs index fd2055fe..2b9b45f0 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebSitesAddSite.ascx.designer.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebSitesAddSite.ascx.designer.cs @@ -1,3 +1,31 @@ +// Copyright (c) 2012, 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. + //------------------------------------------------------------------------------ // // This code was generated by a tool. From 2094e5362eea1141214926276616982f50ad78ce Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Tue, 18 Sep 2012 20:36:51 -0400 Subject: [PATCH 11/13] Added tag build-2.0.0.39 for changeset 44cd0d1ba68d From d91b32e1564fc2fdb6371db4284521191bc23b3a Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Tue, 18 Sep 2012 22:15:08 -0400 Subject: [PATCH 12/13] Backed out merge changeset: c3a217f258da Backed out merge revision to its second parent (d44635d5d6c5) --- .../Code/Files/FilesController.cs | 108 ---- .../Code/WebServers/WebServerController.cs | 492 ++++++++++++------ .../WebsitePanel.EnterpriseServer/Web.config | 40 +- .../WebsitePanel.EnterpriseServer.csproj | 6 - .../OS/IOperatingSystem.cs | 4 - .../WebsitePanel.Providers.Base.csproj | 10 +- .../Windows2003.cs | 11 - .../OperatingSystemProxy.cs | 175 +------ .../WebsitePanel.Server.Utils/FileUtils.cs | 121 ----- .../OperatingSystem.asmx.cs | 33 -- .../Sources/WebsitePanel.Server/Web.config | 2 +- .../WebsitePanel.Server.csproj | 5 - .../WebsitePanel.WebPortal.csproj | 1 - 13 files changed, 350 insertions(+), 658 deletions(-) diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Files/FilesController.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Files/FilesController.cs index 3e58f78a..7784cad8 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Files/FilesController.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/Files/FilesController.cs @@ -912,113 +912,5 @@ namespace WebsitePanel.EnterpriseServer return users.ToArray(); } - - public static int SetFolderQuota(int packageId, string path) - { - - // check account - int accountCheck = SecurityContext.CheckAccount(DemandAccount.NotDemo | DemandAccount.IsActive); - if (accountCheck < 0) return accountCheck; - - // check package - int packageCheck = SecurityContext.CheckPackage(packageId, DemandPackage.IsActive); - if (packageCheck < 0) return packageCheck; - - // place log record - TaskManager.StartTask("FILES", "SET_QUOTA_ON_FOLDER", path); - TaskManager.ItemId = packageId; - - try - { - - // file server cluster name - string fileServerClusterName = String.Empty; - - // Share Name where home folders are created - string shareName = String.Empty; - - string[] splits = GetHomeFolder(packageId).Split('\\'); - - if (splits.Length > 4) - { - fileServerClusterName = splits[2]; - shareName = splits[3]; - } - - // disk space quota - QuotaValueInfo diskSpaceQuota = PackageController.GetPackageQuota(packageId, Quotas.OS_DISKSPACE); - - // bat file pat - string cmdFilePath = @"\\" + fileServerClusterName + @"\" + shareName + @"\" + "Process.bat"; - - #region figure Quota Unit - - // Quota Unit - string unit = String.Empty; - if (diskSpaceQuota.QuotaDescription.ToLower().Contains("gb")) - unit = "GB"; - else if (diskSpaceQuota.QuotaDescription.ToLower().Contains("mb")) - unit = "MB"; - else - unit = "KB"; - - #endregion - - OS.OperatingSystem os = GetOS(packageId); - os.SetQuotaLimitOnFolder(cmdFilePath, fileServerClusterName, path, diskSpaceQuota.QuotaAllocatedValue.ToString() + unit, 0, String.Empty, String.Empty); - - return 0; - } - catch (Exception ex) - { - //Log and return a generic error rather than throwing an exception - TaskManager.WriteError(ex); - return BusinessErrorCodes.ERROR_FILE_GENERIC_LOGGED; - } - finally - { - TaskManager.CompleteTask(); - } - - - } - - public static int DeleteDirectoryRecursive(int packageId, string rootPath) - { - - // check account - int accountCheck = SecurityContext.CheckAccount(DemandAccount.NotDemo | DemandAccount.IsActive); - if (accountCheck < 0) return accountCheck; - - // check package - int packageCheck = SecurityContext.CheckPackage(packageId, DemandPackage.IsActive); - if (packageCheck < 0) return packageCheck; - - // place log record - TaskManager.StartTask("FILES", "DELETE_DIRECTORY_RECURSIVE", rootPath); - TaskManager.ItemId = packageId; - - try - { - - OS.OperatingSystem os = GetOS(packageId); - os.DeleteDirectoryRecursive(rootPath); - - return 0; - } - catch (Exception ex) - { - //Log and return a generic error rather than throwing an exception - TaskManager.WriteError(ex); - return BusinessErrorCodes.ERROR_FILE_GENERIC_LOGGED; - } - finally - { - TaskManager.CompleteTask(); - } - - - } - } } diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/WebServers/WebServerController.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/WebServers/WebServerController.cs index 8966ac3a..5ea4e114 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/WebServers/WebServerController.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Code/WebServers/WebServerController.cs @@ -157,11 +157,11 @@ namespace WebsitePanel.EnterpriseServer public static int AddWebSite(int packageId, string hostName, int domainId, int ipAddressId) { - return AddWebSite(packageId, hostName, domainId, ipAddressId, false); + return AddWebSite(packageId, hostName, domainId, ipAddressId, false, true); } public static int AddWebSite(int packageId, string hostName, int domainId, int packageAddressId, - bool addInstantAlias) + bool addInstantAlias, bool ignoreGlobalDNSRecords) { // check account int accountCheck = SecurityContext.CheckAccount(DemandAccount.NotDemo | DemandAccount.IsActive); @@ -180,12 +180,15 @@ namespace WebsitePanel.EnterpriseServer DomainInfo domain = ServerController.GetDomain(domainId); string domainName = domain.DomainName; - // check if the web site already exists - if (PackageController.GetPackageItemByName(packageId, domainName, typeof(WebSite)) != null) + string siteName = string.IsNullOrEmpty(hostName) ? domainName : hostName + "." + domainName; + + // check if the web site already exists (legacy) + if (PackageController.GetPackageItemByName(packageId, siteName, typeof(WebSite)) != null) return BusinessErrorCodes.ERROR_WEB_SITE_ALREADY_EXISTS; + if (DataProvider.CheckDomain(domain.PackageId, siteName, true) != 0) + return BusinessErrorCodes.ERROR_WEB_SITE_ALREADY_EXISTS; - string siteName = string.IsNullOrEmpty(hostName) ? domainName : hostName + "." + domainName; ; // place log record TaskManager.StartTask("WEB_SITE", "ADD", siteName); @@ -198,7 +201,7 @@ namespace WebsitePanel.EnterpriseServer if (serviceId == 0) return BusinessErrorCodes.ERROR_WEB_SITE_SERVICE_UNAVAILABLE; - #region Fix for bug #587 + // Initialize IIS provider webservice proxy WebServer web = new WebServer(); ServiceProviderProxy.Init(web, serviceId); @@ -216,7 +219,6 @@ namespace WebsitePanel.EnterpriseServer // Return generic operation failed error return BusinessErrorCodes.FAILED_EXECUTE_SERVICE_OPERATION; } - #endregion // load web settings StringDictionary webSettings = ServerController.GetServiceSettings(serviceId); @@ -240,13 +242,6 @@ namespace WebsitePanel.EnterpriseServer if (ip != null) ipAddr = !String.IsNullOrEmpty(ip.InternalIP) ? ip.InternalIP : ip.ExternalIP; - // load domain instant alias - /* - string instantAlias = ServerController.GetDomainAlias(packageId, domainName); - DomainInfo instantDomain = ServerController.GetDomain(instantAlias); - if (instantDomain == null || instantDomain.WebSiteId > 0) - instantAlias = ""; - */ // load web DNS records List dnsRecords = ServerController.GetDnsRecordsByService(serviceId); @@ -254,26 +249,15 @@ namespace WebsitePanel.EnterpriseServer // prepare site bindings List bindings = new List(); - if (!dedicatedIp) - { - // SHARED IP - // fill main domain bindings - /* - FillWebServerBindings(bindings, dnsRecords, ipAddr, domain.DomainName); + // SHARED IP + // fill main domain bindings + FillWebServerBindings(bindings, dnsRecords, ipAddr, hostName, domain.DomainName, ignoreGlobalDNSRecords); - // fill alias bindings if required - if (addInstantAlias && !String.IsNullOrEmpty(instantAlias)) - { - // fill bindings from DNS "A" records - FillWebServerBindings(bindings, dnsRecords, ipAddr, instantAlias); - } - */ - bindings.Add(new ServerBinding(ipAddr, "80", siteName)); - } - else + //double check all bindings + foreach (ServerBinding b in bindings) { - // DEDICATED IP - bindings.Add(new ServerBinding(ipAddr, "80", "")); + if (DataProvider.CheckDomain(domain.PackageId, b.Host, true) != 0) + return BusinessErrorCodes.ERROR_WEB_SITE_ALREADY_EXISTS; } UserInfo user = PackageController.GetPackageOwner(packageId); @@ -327,12 +311,10 @@ namespace WebsitePanel.EnterpriseServer site.EnableParentPaths = Utils.ParseBool(webPolicy["EnableParentPaths"], false); site.DedicatedApplicationPool = Utils.ParseBool(webPolicy["EnableDedicatedPool"], false); - #region Fix for bug: #1556 + // Ensure the website meets hosting plan quotas QuotaValueInfo quotaInfo = PackageController.GetPackageQuota(packageId, Quotas.WEB_APPPOOLS); site.DedicatedApplicationPool = site.DedicatedApplicationPool && (quotaInfo.QuotaAllocatedValue > 0); - - #endregion site.EnableAnonymousAccess = Utils.ParseBool(webPolicy["EnableAnonymousAccess"], false); site.EnableWindowsAuthentication = Utils.ParseBool(webPolicy["EnableWindowsAuthentication"], false); @@ -377,9 +359,6 @@ namespace WebsitePanel.EnterpriseServer // CREATE WEB SITE siteId = web.CreateSite(site); - // Set hard quota on the website content folder - FilesController.SetFolderQuota(packageId, site.DataPath); - // register item site.ServiceId = serviceId; site.PackageId = packageId; @@ -395,14 +374,9 @@ namespace WebsitePanel.EnterpriseServer // update domain // add main pointer - AddWebSitePointer(siteItemId, hostName, domain.DomainId, false); - - // add instant pointer - /* - if (addInstantAlias && !String.IsNullOrEmpty(instantAlias)) - AddWebSitePointer(siteItemId, instantDomain.DomainId, false); - */ + AddWebSitePointer(siteItemId, hostName, domain.DomainId, false, ignoreGlobalDNSRecords, false); + // add parking page // load package if (webPolicy["AddParkingPage"] != null) @@ -577,36 +551,26 @@ namespace WebsitePanel.EnterpriseServer // remove all web site pointers List pointers = GetWebSitePointers(siteItemId); foreach (DomainInfo pointer in pointers) - DeleteWebSitePointer(siteItemId, pointer.DomainId, false); + DeleteWebSitePointer(siteItemId, pointer.DomainId, false, true, true); // remove web site main pointer DomainInfo domain = ServerController.GetDomain(siteItem.Name); if(domain != null) - DeleteWebSitePointer(siteItemId, domain.DomainId, false); + DeleteWebSitePointer(siteItemId, domain.DomainId, false, true, true); // delete web site WebServer web = new WebServer(); ServiceProviderProxy.Init(web, siteItem.ServiceId); - #region Fix for bug #710 // if (web.IsFrontPageSystemInstalled() && web.IsFrontPageInstalled(siteItem.SiteId)) { web.UninstallFrontPage(siteItem.SiteId, siteItem.FrontPageAccount); } - #endregion // web.DeleteSite(siteItem.SiteId); - // Delete WebManagementAccess Account - WebServerController.RevokeWebManagementAccess(siteItemId); - - // Delete website directory from file server - // This will remove the hard quota as well - FilesController.DeleteDirectoryRecursive(siteItem.PackageId, new DirectoryInfo(siteItem.DataPath).Parent.FullName); - - // delete service item PackageController.DeletePackageItem(siteItemId); @@ -622,8 +586,119 @@ namespace WebsitePanel.EnterpriseServer } } + public static int SwitchWebSiteToDedicatedIP(int siteItemId, int ipAddressId) + { + // check account + int accountCheck = SecurityContext.CheckAccount(DemandAccount.NotDemo | DemandAccount.IsActive); + if (accountCheck < 0) return accountCheck; + + // load web site item + WebSite siteItem = (WebSite)PackageController.GetPackageItem(siteItemId); + if (siteItem == null) + return BusinessErrorCodes.ERROR_WEB_SITE_PACKAGE_ITEM_NOT_FOUND; + + // load assigned IP address + //IPAddressInfo ip = ServerController.GetIPAddress(ipAddressId); + //if (ip == null) + //return BusinessErrorCodes.ERROR_WEB_SITE_IP_ADDRESS_NOT_SPECIFIED; + + //string ipAddr = !String.IsNullOrEmpty(ip.InternalIP) ? ip.InternalIP : ip.ExternalIP; + int addressId = 0; + PackageIPAddress packageIp = ServerController.GetPackageIPAddress(ipAddressId); + if (packageIp != null) + { + addressId = packageIp.AddressID; + } + + + // place log record + TaskManager.StartTask("WEB_SITE", "SWITCH_TO_DEDICATED_IP", siteItem.Name); + TaskManager.ItemId = siteItemId; +/* + try + { + // remove all web site pointers + List pointers = GetWebSitePointers(siteItemId); + foreach (DomainInfo pointer in pointers) + DeleteWebSitePointer(siteItemId, pointer.DomainId, true, true, false); + + // remove web site main pointer + DomainInfo domain = ServerController.GetDomain(siteItem.Name); + if (domain != null) + DeleteWebSitePointer(siteItemId, domain.DomainId, true, true, false); + + // update site item + siteItem.SiteIPAddressId = addressId; + PackageController.UpdatePackageItem(siteItem); + + // associate IP with web site + if (addressId != 0) + ServerController.AddItemIPAddress(siteItemId, addressId); + + AddWebSitePointer(siteItemId, "", domain.DomainId, true, true, true); + + foreach (DomainInfo pointer in pointers) + AddWebSitePointer(siteItemId, "", pointer.DomainId, true, true, true); + + return 0; + } + catch (Exception ex) + { + throw TaskManager.WriteError(ex); + } + finally + { + TaskManager.CompleteTask(); + } + */ + + return 0; + } + + public static int SwitchWebSiteToSharedIP(int siteItemId) + { + // check account + int accountCheck = SecurityContext.CheckAccount(DemandAccount.NotDemo | DemandAccount.IsActive); + if (accountCheck < 0) return accountCheck; + + // load web site item + WebSite siteItem = (WebSite)PackageController.GetPackageItem(siteItemId); + if (siteItem == null) + return BusinessErrorCodes.ERROR_WEB_SITE_PACKAGE_ITEM_NOT_FOUND; + + // place log record + TaskManager.StartTask("WEB_SITE", "SWITCH_TO_SHARED_IP", siteItem.Name); + TaskManager.ItemId = siteItemId; +/* + try + { + // get web site pointers + var sitePointers = GetWebSitePointers(siteItemId); + + // get existing web site bindings + WebServer web = new WebServer(); + ServiceProviderProxy.Init(web, siteItem.ServiceId); + var bindings = web.GetSiteBindings(siteItem.SiteId); + + // TODO - what would be correct logic here? + + return 0; + } + catch (Exception ex) + { + throw TaskManager.WriteError(ex); + } + finally + { + TaskManager.CompleteTask(); + } + */ + return 0; + + } + private static void FillWebServerBindings(List bindings, List dnsRecords, - string ipAddr, string hostName, string domainName) + string ipAddr, string hostName, string domainName, bool ignoreGlobalDNSRecords) // TODO test if IPv6 works { int bindingsCount = bindings.Count; @@ -632,36 +707,46 @@ namespace WebsitePanel.EnterpriseServer if ((dnsRecord.RecordType == "A" || dnsRecord.RecordType == "AAAA" || dnsRecord.RecordType == "CNAME") && dnsRecord.RecordName != "*") { - /* - string recordData = dnsRecord.RecordName + - ((dnsRecord.RecordName != "") ? "." : "") + domainName; + string recordData = Utils.ReplaceStringVariable(dnsRecord.RecordName, "host_name", hostName, true); - bindings.Add(new ServerBinding(ipAddr, "80", recordData)); - */ - - string tmpName = string.Empty; - if (!String.IsNullOrEmpty(hostName)) - tmpName = Utils.ReplaceStringVariable(dnsRecord.RecordName, "host_name", hostName); - - string recordData = string.Empty; - if (tmpName.Contains(".")) - recordData = hostName; + if (!string.IsNullOrEmpty(domainName)) + recordData = recordData + ((string.IsNullOrEmpty(recordData)) ? "" : ".") + domainName; + //otherwise full recordData is supplied by hostName + + if (ignoreGlobalDNSRecords) + { + //only look for the host_nanme record, ignore all others + if (dnsRecord.RecordName == "[host_name]") + { + AddBinding(bindings, new ServerBinding(ipAddr, "80", recordData)); + break; + } + } else - recordData = tmpName + ((tmpName != "") ? "." : "") + domainName; - - bindings.Add(new ServerBinding(ipAddr, "80", recordData)); + { + AddBinding(bindings, new ServerBinding(ipAddr, "80", recordData)); + } } } - - /* - if(bindings.Count == bindingsCount) + + if ((bindings.Count == bindingsCount) | (bindings.Count == 0)) { - bindings.Add(new ServerBinding(ipAddr, "80", domainName)); - bindings.Add(new ServerBinding(ipAddr, "80", "www." + domainName)); + AddBinding(bindings, new ServerBinding(ipAddr, "80", string.IsNullOrEmpty(hostName) ? domainName : hostName + "." + domainName)); } - */ } + private static void AddBinding(List bindings, ServerBinding binding) + { + foreach (ServerBinding b in bindings) + { + if (string.Compare(b.Host, binding.Host, true) == 0) + return; + } + + bindings.Add(binding); + } + + private static string GetWebSiteUsername(UserSettings webPolicy, string domainName) { UsernamePolicy policy = new UsernamePolicy(webPolicy["AnonymousAccountPolicy"]); @@ -747,10 +832,15 @@ namespace WebsitePanel.EnterpriseServer public static int AddWebSitePointer(int siteItemId, string hostName, int domainId) { - return AddWebSitePointer(siteItemId, hostName, domainId, true); + return AddWebSitePointer(siteItemId, hostName, domainId, true, true, false); } internal static int AddWebSitePointer(int siteItemId, string hostName, int domainId, bool updateWebSite) + { + return AddWebSitePointer(siteItemId, hostName, domainId, updateWebSite, false, false); + } + + internal static int AddWebSitePointer(int siteItemId, string hostName, int domainId, bool updateWebSite, bool ignoreGlobalDNSRecords, bool rebuild) { // check account int accountCheck = SecurityContext.CheckAccount(DemandAccount.NotDemo | DemandAccount.IsActive); @@ -766,6 +856,13 @@ namespace WebsitePanel.EnterpriseServer if (domain == null) return BusinessErrorCodes.ERROR_DOMAIN_PACKAGE_ITEM_NOT_FOUND; + // check if the web site already exists + if (!rebuild) + { + if (DataProvider.CheckDomain(domain.PackageId, string.IsNullOrEmpty(hostName) ? domain.DomainName : hostName + "." + domain.DomainName, true) != 0) + return BusinessErrorCodes.ERROR_WEB_SITE_ALREADY_EXISTS; + } + // get zone records for the service List dnsRecords = ServerController.GetDnsRecordsByService(siteItem.ServiceId); @@ -781,16 +878,62 @@ namespace WebsitePanel.EnterpriseServer try { + + // load appropriate zone DnsZone zone = (DnsZone)PackageController.GetPackageItem(domain.ZoneItemId); + if (zone != null) { // change DNS zone + List tmpDnsRecords = new List(); + string serviceIp = (ip != null) ? ip.ExternalIP : null; - List resourceRecords = DnsServerController.BuildDnsResourceRecords( - dnsRecords, hostName, domain.DomainName, serviceIp); + if (string.IsNullOrEmpty(serviceIp)) + { + StringDictionary settings = ServerController.GetServiceSettings(siteItem.ServiceId); + if (settings["PublicSharedIP"] != null) + serviceIp = settings["PublicSharedIP"].ToString(); + } + + //filter initiat GlobaDNSRecords list + if (ignoreGlobalDNSRecords) + { + //ignore all other except the host_name record + foreach (GlobalDnsRecord r in dnsRecords) + { + if (rebuild) + { + if ((r.RecordName + (string.IsNullOrEmpty(r.RecordName) ? domain.ZoneName : "." + domain.ZoneName)) == domain.DomainName) tmpDnsRecords.Add(r); + } + else + { + if (r.RecordName == "[host_name]") tmpDnsRecords.Add(r); + } + + } + } + else + tmpDnsRecords = dnsRecords; + + + List resourceRecords = rebuild ? DnsServerController.BuildDnsResourceRecords(tmpDnsRecords, "", domain.DomainName, serviceIp): + DnsServerController.BuildDnsResourceRecords(tmpDnsRecords, hostName, domain.DomainName, serviceIp); + + if (!rebuild) + { + foreach (DnsRecord r in resourceRecords) + { + if (r.RecordName != "*") + { + // check if the web site already exists + if (DataProvider.CheckDomain(domain.PackageId, string.IsNullOrEmpty(r.RecordName) ? domain.DomainName : r.RecordName + "." + domain.DomainName, true) != 0) + return BusinessErrorCodes.ERROR_WEB_SITE_ALREADY_EXISTS; + } + } + } try { @@ -807,59 +950,60 @@ namespace WebsitePanel.EnterpriseServer } // update host headers - if (updateWebSite) + List bindings = new List(); + + // get existing web site bindings + WebServer web = new WebServer(); + ServiceProviderProxy.Init(web, siteItem.ServiceId); + + bindings.AddRange(web.GetSiteBindings(siteItem.SiteId)); + + // check if web site has dedicated IP assigned + bool dedicatedIp = bindings.Exists(binding => { return String.IsNullOrEmpty(binding.Host) && binding.IP != "*"; }); + + // update binding only for "shared" ip addresses + // add new host headers + string ipAddr = "*"; + if (ip != null) + ipAddr = !String.IsNullOrEmpty(ip.InternalIP) ? ip.InternalIP : ip.ExternalIP; + + // fill bindings + if (rebuild) + FillWebServerBindings(bindings, dnsRecords, "", domain.DomainName, "", ignoreGlobalDNSRecords); + else + FillWebServerBindings(bindings, dnsRecords, ipAddr, hostName, domain.DomainName, ignoreGlobalDNSRecords); + + //for logging purposes + foreach (ServerBinding b in bindings) { - // get existing web site bindings - WebServer web = new WebServer(); - ServiceProviderProxy.Init(web, siteItem.ServiceId); - - List bindings = new List(); - bindings.AddRange(web.GetSiteBindings(siteItem.SiteId)); - - // check if web site has dedicated IP assigned - bool dedicatedIp = bindings.Exists(binding => { return String.IsNullOrEmpty(binding.Host) && binding.IP != "*"; }); - - // update binding only for "shared" ip addresses - if (!dedicatedIp) - { - // add new host headers - string ipAddr = "*"; - if (ip != null) - ipAddr = !String.IsNullOrEmpty(ip.InternalIP) ? ip.InternalIP : ip.ExternalIP; - - // fill bindings - FillWebServerBindings(bindings, dnsRecords, ipAddr, hostName, domain.DomainName); - - foreach (ServerBinding b in bindings) - { - string header = string.Format("{0} {1} {2}", b.Host, b.IP, b.Port); - TaskManager.WriteParameter("Add Binding", b.Host); - } - - // update bindings - web.UpdateSiteBindings(siteItem.SiteId, bindings.ToArray()); - } + string header = string.Format("{0} {1} {2}", b.Host, b.IP, b.Port); + TaskManager.WriteParameter("Add Binding", header); } + // update bindings + if (updateWebSite) + web.UpdateSiteBindings(siteItem.SiteId, bindings.ToArray(), false); + // update domain - domain.WebSiteId = siteItemId; - //ServerController.UpdateDomain(domain); - if (!String.IsNullOrEmpty(hostName)) - domain.DomainName = hostName + "." + domain.DomainName; - else - domain.DomainName = domain.DomainName; - domain.IsDomainPointer = true; - int domainID = ServerController.AddDomain(domain); - - DomainInfo domainTmp = ServerController.GetDomain(domainID); - if (domainTmp != null) + if (!rebuild) { - domainTmp.WebSiteId = siteItemId; - domainTmp.ZoneItemId = domain.ZoneItemId; - ServerController.UpdateDomain(domainTmp); + domain.WebSiteId = siteItemId; + domain.IsDomainPointer = true; + foreach (ServerBinding b in bindings) + { + //add new domain record + domain.DomainName = b.Host; + int domainID = ServerController.AddDomain(domain); + DomainInfo domainTmp = ServerController.GetDomain(domainID); + if (domainTmp != null) + { + domainTmp.WebSiteId = siteItemId; + domainTmp.ZoneItemId = domain.ZoneItemId; + ServerController.UpdateDomain(domainTmp); + } + } } - return 0; } catch (Exception ex) @@ -874,10 +1018,10 @@ namespace WebsitePanel.EnterpriseServer public static int DeleteWebSitePointer(int siteItemId, int domainId) { - return DeleteWebSitePointer(siteItemId, domainId, true); + return DeleteWebSitePointer(siteItemId, domainId, true, true, true); } - public static int DeleteWebSitePointer(int siteItemId, int domainId, bool updateWebSite) + public static int DeleteWebSitePointer(int siteItemId, int domainId, bool updateWebSite, bool ignoreGlobalDNSRecords, bool deleteDomainsRecord) { // check account int accountCheck = SecurityContext.CheckAccount(DemandAccount.NotDemo | DemandAccount.IsActive); @@ -906,16 +1050,36 @@ namespace WebsitePanel.EnterpriseServer TaskManager.StartTask("WEB_SITE", "DELETE_POINTER", siteItem.Name); TaskManager.ItemId = siteItemId; TaskManager.WriteParameter("Domain pointer", domain.DomainName); + TaskManager.WriteParameter("updateWebSite", updateWebSite.ToString()); try { if (zone != null) { // change DNS zone + List tmpDnsRecords = new List(); + string serviceIp = (ip != null) ? ip.ExternalIP : null; + if (string.IsNullOrEmpty(serviceIp)) + { + StringDictionary settings = ServerController.GetServiceSettings(siteItem.ServiceId); + if (settings["PublicSharedIP"] != null) + serviceIp = settings["PublicSharedIP"].ToString(); + } + + if (ignoreGlobalDNSRecords) + { + foreach (GlobalDnsRecord r in dnsRecords) + { + if ((r.RecordName == "[host_name]") | ((r.RecordName + (string.IsNullOrEmpty(r.RecordName) ? domain.ZoneName : "." + domain.ZoneName)) == domain.DomainName)) + tmpDnsRecords.Add(r); + } + } + else tmpDnsRecords = dnsRecords; + List resourceRecords = DnsServerController.BuildDnsResourceRecords( - dnsRecords, domain.DomainName, "", serviceIp); + tmpDnsRecords, domain.DomainName, "", serviceIp); try { @@ -929,43 +1093,41 @@ namespace WebsitePanel.EnterpriseServer } } + // get existing web site bindings + WebServer web = new WebServer(); + ServiceProviderProxy.Init(web, siteItem.ServiceId); + + List bindings = new List(); + bindings.AddRange(web.GetSiteBindings(siteItem.SiteId)); + + // check if web site has dedicated IP assigned + bool dedicatedIp = bindings.Exists(binding => { return String.IsNullOrEmpty(binding.Host) && binding.IP != "*"; }); + + // update binding only for "shared" ip addresses + + // remove host headers + List domainBindings = new List(); + FillWebServerBindings(domainBindings, dnsRecords, "", domain.DomainName, "", ignoreGlobalDNSRecords); + + // fill to remove list + List headersToRemove = new List(); + foreach (ServerBinding domainBinding in domainBindings) + headersToRemove.Add(domainBinding.Host); + + // remove bndings + bindings.RemoveAll(b => { return headersToRemove.Contains(b.Host) && b.Port == "80"; } ); + + // update bindings if (updateWebSite) - { - // get existing web site bindings - WebServer web = new WebServer(); - ServiceProviderProxy.Init(web, siteItem.ServiceId); - - List bindings = new List(); - bindings.AddRange(web.GetSiteBindings(siteItem.SiteId)); - - // check if web site has dedicated IP assigned - bool dedicatedIp = bindings.Exists(binding => { return String.IsNullOrEmpty(binding.Host) && binding.IP != "*"; }); - - // update binding only for "shared" ip addresses - if (!dedicatedIp) - { - // remove host headers - List domainBindings = new List(); - FillWebServerBindings(domainBindings, dnsRecords, "", domain.DomainName, ""); - - // fill to remove list - List headersToRemove = new List(); - foreach (ServerBinding domainBinding in domainBindings) - headersToRemove.Add(domainBinding.Host); - - // remove bndings - bindings.RemoveAll(b => { return headersToRemove.Contains(b.Host) && b.Port == "80"; } ); - - // update bindings - web.UpdateSiteBindings(siteItem.SiteId, bindings.ToArray()); - } - } + web.UpdateSiteBindings(siteItem.SiteId, bindings.ToArray(), true); // update domain domain.WebSiteId = 0; - ServerController.UpdateDomain(domain); - ServerController.DeleteDomain(domain.DomainId); - + if (deleteDomainsRecord) + { + ServerController.UpdateDomain(domain); + ServerController.DeleteDomain(domain.DomainId); + } return 0; } catch (Exception ex) diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Web.config b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Web.config index 56350e5d..a99cd490 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Web.config +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/Web.config @@ -1,56 +1,56 @@ - + -

+
- + - + - + - + - + - + - + - + - - - + + + - + - + - + - - + + - + - + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/WebsitePanel.EnterpriseServer.csproj b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/WebsitePanel.EnterpriseServer.csproj index ac8ea558..52285130 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/WebsitePanel.EnterpriseServer.csproj +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/WebsitePanel.EnterpriseServer.csproj @@ -19,11 +19,6 @@ v4.0 - false - - - - true @@ -415,7 +410,6 @@ - diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/OS/IOperatingSystem.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/OS/IOperatingSystem.cs index add15c94..fc9f3076 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/OS/IOperatingSystem.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/OS/IOperatingSystem.cs @@ -28,7 +28,6 @@ using System; using System.Collections; -using System.IO; namespace WebsitePanel.Providers.OS { @@ -82,8 +81,5 @@ namespace WebsitePanel.Providers.OS // Synchronizing FolderGraph GetFolderGraph(string path); void ExecuteSyncActions(FileSyncAction[] actions); - void SetQuotaLimitOnFolder(string cmdFilePath, string virtualFileClusterName, string folderPath, string quotaLimit, int mode, string wmiUserName, string wmiPassword); - void DeleteDirectoryRecursive(string rootPath); - } } diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj b/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj index 137151d2..b8623bcf 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj @@ -80,6 +80,7 @@ + @@ -92,11 +93,6 @@ - - True - True - Settings.settings - @@ -317,10 +313,6 @@ - - SettingsSingleFileGenerator - Settings.Designer.cs - diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.OS.Windows2003/Windows2003.cs b/WebsitePanel/Sources/WebsitePanel.Providers.OS.Windows2003/Windows2003.cs index 1d37b8b3..f251bd66 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.OS.Windows2003/Windows2003.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.OS.Windows2003/Windows2003.cs @@ -209,17 +209,6 @@ namespace WebsitePanel.Providers.OS SecurityUtils.GrantGroupNtfsPermissions(path, users, resetChildPermissions, ServerSettings, usersOU, null); } - - public virtual void SetQuotaLimitOnFolder(string cmdFilePath, string virtualFileClusterName, string folderPath, string quotaLimit, int mode, string wmiUserName, string wmiPassword) - { - FileUtils.SetQuotaLimitOnFolder(cmdFilePath, virtualFileClusterName, folderPath, quotaLimit, mode, wmiUserName, wmiPassword); - } - - public virtual void DeleteDirectoryRecursive(string rootPath) - { - FileUtils.DeleteDirectoryRecursive(rootPath); - } - #endregion #region ODBC DSNs diff --git a/WebsitePanel/Sources/WebsitePanel.Server.Client/OperatingSystemProxy.cs b/WebsitePanel/Sources/WebsitePanel.Server.Client/OperatingSystemProxy.cs index 34be86c2..f40b6d59 100644 --- a/WebsitePanel/Sources/WebsitePanel.Server.Client/OperatingSystemProxy.cs +++ b/WebsitePanel/Sources/WebsitePanel.Server.Client/OperatingSystemProxy.cs @@ -61,10 +61,6 @@ namespace WebsitePanel.Providers.OS { private System.Threading.SendOrPostCallback CreatePackageFolderOperationCompleted; private System.Threading.SendOrPostCallback FileExistsOperationCompleted; - - private System.Threading.SendOrPostCallback SetQuotaLimitOnFolderOperationCompleted; - - private System.Threading.SendOrPostCallback DeleteDirectoryRecursiveOperationCompleted; private System.Threading.SendOrPostCallback DirectoryExistsOperationCompleted; @@ -135,8 +131,7 @@ namespace WebsitePanel.Providers.OS { private System.Threading.SendOrPostCallback UpdateDSNOperationCompleted; private System.Threading.SendOrPostCallback DeleteDSNOperationCompleted; - - + /// public OperatingSystem() { this.Url = "http://localhost/Server/OperatingSystem.asmx"; @@ -147,12 +142,6 @@ namespace WebsitePanel.Providers.OS { /// public event FileExistsCompletedEventHandler FileExistsCompleted; - - /// - public event SetQuotaLimitOnFolderCompletedEventHandler SetQuotaLimitOnFolderCompleted; - - /// - public event DeleteDirectoryRecursiveCompletedEventHandler DeleteDirectoryRecursiveCompleted; /// public event DirectoryExistsCompletedEventHandler DirectoryExistsCompleted; @@ -342,107 +331,6 @@ namespace WebsitePanel.Providers.OS { this.FileExistsCompleted(this, new FileExistsCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); } } - - /// - [System.Web.Services.Protocols.SoapHeaderAttribute("ServiceProviderSettingsSoapHeaderValue")] - [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://smbsaas/websitepanel/server/SetQuotaLimitOnFolder", RequestNamespace = "http://smbsaas/websitepanel/server/", ResponseNamespace = "http://smbsaas/websitepanel/server/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] - public bool SetQuotaLimitOnFolder(string cmdFilePath, string virtualFileClusterName, string folderPath, string quotaLimit, int mode, string wmiUserName, string wmiPassword) - { - object[] results = this.Invoke("SetQuotaLimitOnFolder", new object[] { - cmdFilePath, virtualFileClusterName, folderPath, quotaLimit, mode, wmiUserName, wmiPassword}); - return ((bool)(results[0])); - } - - /// - public System.IAsyncResult BeginSetQuotaLimitOnFolder(string cmdFilePath, string virtualFileClusterName, string folderPath, string quotaLimit, int mode, string wmiUserName, string wmiPassword, System.AsyncCallback callback, object asyncState) - { - return this.BeginInvoke("SetQuotaLimitOnFolder", new object[] { - cmdFilePath, virtualFileClusterName, folderPath, quotaLimit, mode, wmiUserName, wmiPassword}, callback, asyncState); - } - - /// - public bool EndSetQuotaLimitOnFolder(System.IAsyncResult asyncResult) - { - object[] results = this.EndInvoke(asyncResult); - return ((bool)(results[0])); - } - - /// - public void SetQuotaLimitOnFolderAsync(string cmdFilePath, string virtualFileClusterName, string folderPath, string quotaLimit, int mode, string wmiUserName, string wmiPassword) - { - this.SetQuotaLimitOnFolderAsync(cmdFilePath, virtualFileClusterName, folderPath, quotaLimit, mode, wmiUserName, wmiPassword, null); - } - - /// - public void SetQuotaLimitOnFolderAsync(string cmdFilePath, string virtualFileClusterName, string folderPath, string quotaLimit, int mode, string wmiUserName, string wmiPassword, object userState) - { - if ((this.SetQuotaLimitOnFolderOperationCompleted == null)) - { - this.SetQuotaLimitOnFolderOperationCompleted = new System.Threading.SendOrPostCallback(this.OnSetQuotaLimitOnFolderOperationCompleted); - } - this.InvokeAsync("SetQuotaLimitOnFolder", new object[] { - cmdFilePath, virtualFileClusterName, folderPath, quotaLimit, mode, wmiUserName, wmiPassword}, this.SetQuotaLimitOnFolderOperationCompleted, userState); - } - - private void OnSetQuotaLimitOnFolderOperationCompleted(object arg) - { - if ((this.SetQuotaLimitOnFolderCompleted != null)) - { - System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); - this.SetQuotaLimitOnFolderCompleted(this, new SetQuotaLimitOnFolderCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); - } - } - - /// - [System.Web.Services.Protocols.SoapHeaderAttribute("ServiceProviderSettingsSoapHeaderValue")] - [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://smbsaas/websitepanel/server/DeleteDirectoryRecursive", RequestNamespace = "http://smbsaas/websitepanel/server/", ResponseNamespace = "http://smbsaas/websitepanel/server/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] - public bool DeleteDirectoryRecursive(string rootPath) - { - object[] results = this.Invoke("DeleteDirectoryRecursive", new object[] { - rootPath }); - return ((bool)(results[0])); - } - - /// - public System.IAsyncResult BeginDeleteDirectoryRecursive(string rootPath, System.AsyncCallback callback, object asyncState) - { - return this.BeginInvoke("DeleteDirectoryRecursive", new object[] { - rootPath}, callback, asyncState); - } - - /// - public bool EndDeleteDirectoryRecursive(System.IAsyncResult asyncResult) - { - object[] results = this.EndInvoke(asyncResult); - return ((bool)(results[0])); - } - - /// - public void DeleteDirectoryRecursiveAsync(string rootPath) - { - this.DeleteDirectoryRecursiveAsync(rootPath, null); - } - - /// - public void DeleteDirectoryRecursiveAsync(string rootPath, object userState) - { - if ((this.DeleteDirectoryRecursiveOperationCompleted == null)) - { - this.DeleteDirectoryRecursiveOperationCompleted = new System.Threading.SendOrPostCallback(this.OnDeleteDirectoryRecursiveOperationCompleted); - } - this.InvokeAsync("DeleteDirectoryRecursive", new object[] { - rootPath}, this.DeleteDirectoryRecursiveOperationCompleted, userState); - } - - private void OnDeleteDirectoryRecursiveOperationCompleted(object arg) - { - if ((this.DeleteDirectoryRecursiveCompleted != null)) - { - System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); - this.DeleteDirectoryRecursiveCompleted(this, new DeleteDirectoryRecursiveCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); - } - } - /// [System.Web.Services.Protocols.SoapHeaderAttribute("ServiceProviderSettingsSoapHeaderValue")] @@ -2011,67 +1899,6 @@ namespace WebsitePanel.Providers.OS { } } } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")] - public delegate void SetQuotaLimitOnFolderCompletedEventHandler(object sender, SetQuotaLimitOnFolderCompletedEventArgs e); - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - public partial class SetQuotaLimitOnFolderCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs - { - - private object[] results; - - internal SetQuotaLimitOnFolderCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : - base(exception, cancelled, userState) - { - this.results = results; - } - - /// - public bool Result - { - get - { - this.RaiseExceptionIfNecessary(); - return ((bool)(this.results[0])); - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")] - public delegate void DeleteDirectoryRecursiveCompletedEventHandler(object sender, DeleteDirectoryRecursiveCompletedEventArgs e); - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - public partial class DeleteDirectoryRecursiveCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs - { - - private object[] results; - - internal DeleteDirectoryRecursiveCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : - base(exception, cancelled, userState) - { - this.results = results; - } - - /// - public bool Result - { - get - { - this.RaiseExceptionIfNecessary(); - return ((bool)(this.results[0])); - } - } - } - /// [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")] diff --git a/WebsitePanel/Sources/WebsitePanel.Server.Utils/FileUtils.cs b/WebsitePanel/Sources/WebsitePanel.Server.Utils/FileUtils.cs index 06433897..f30354a5 100644 --- a/WebsitePanel/Sources/WebsitePanel.Server.Utils/FileUtils.cs +++ b/WebsitePanel/Sources/WebsitePanel.Server.Utils/FileUtils.cs @@ -37,7 +37,6 @@ using System.Collections.Generic; using System.Reflection; using Ionic.Zip; using WebsitePanel.Providers.OS; -using System.Management; namespace WebsitePanel.Providers.Utils { @@ -845,126 +844,6 @@ namespace WebsitePanel.Providers.Utils conn, null); cat = null; } - - public static void DeleteDirectoryRecursive(string rootPath) - { - // This code is done this way to force folder deletion - // even if the folder was opened - - DirectoryInfo treeRoot = new DirectoryInfo(rootPath); - if (treeRoot.Exists) - { - - DirectoryInfo[] dirs = treeRoot.GetDirectories(); - while (dirs.Length > 0) - { - foreach (DirectoryInfo dir in dirs) - DeleteDirectoryRecursive(dir.FullName); - - dirs = treeRoot.GetDirectories(); - } - - // DELETE THE FILES UNDER THE CURRENT ROOT - string[] files = Directory.GetFiles(treeRoot.FullName); - foreach (string file in files) - { - File.SetAttributes(file, FileAttributes.Normal); - File.Delete(file); - } - - Directory.Delete(treeRoot.FullName, true); - } - - - } - - public static void SetQuotaLimitOnFolder(string cmdFilePath, string virtualFileClusterName, string folderPath, string quotaLimit, int mode, string wmiUserName, string wmiPassword) - { - try - { - string[] splits = folderPath.Split('\\'); - if (splits.Length > 0) - { - // Creating the BAT file - FileStream fs = File.Create(cmdFilePath); - if (fs != null) - { - fs.Close(); - fs.Dispose(); - } - - StreamWriter swr = new StreamWriter(cmdFilePath); - - if (swr != null) - { - swr.WriteLine(@"cd c:\windows\system32"); - - string[] shareDrive = { }; - string sharePath = String.Empty; - - if (splits.Length > 4) - { - // Check the share name if it's not an empty string - if (splits[3].Length > 0) - shareDrive = splits[3].Split('_'); - - // Form the share physicalPath - if (shareDrive.Length == 2) - sharePath = shareDrive[1] + @":\" + splits[3]; - - if (splits.Length == 7 && !quotaLimit.Equals(String.Empty)) - { - splits[6] = "wwwroot"; - - switch (mode) - { - // Set - case 0: swr.WriteLine(@"dirquota quota add /path:" + sharePath + @"\" + splits[4] + @"\" + splits[5] + @"\" + splits[6] + @" /limit:" + quotaLimit + @" /remote:" + splits[2]); - break; - - // Modify - case 1: swr.WriteLine(@"dirquota quota modify /path:" + sharePath + @"\" + splits[4] + @"\" + splits[5] + @"\" + splits[6] + @" /limit:" + quotaLimit + @" /remote:" + splits[2]); - break; - } - } - - - } - swr.Flush(); - swr.Close(); - swr.Dispose(); - } - - ConnectionOptions connOptions = new ConnectionOptions(); - - if (wmiUserName.Length > 0) - { - connOptions.Username = wmiUserName; - connOptions.Password = wmiPassword; - } - - connOptions.Impersonation = ImpersonationLevel.Impersonate; - - connOptions.EnablePrivileges = true; - - ManagementScope manScope = - new ManagementScope(String.Format(@"\\{0}\ROOT\CIMV2", virtualFileClusterName), connOptions); - manScope.Connect(); - - ObjectGetOptions objectGetOptions = new ObjectGetOptions(); - ManagementPath managementPath = new ManagementPath("Win32_Process"); - ManagementClass processClass = new ManagementClass(manScope, managementPath, objectGetOptions); - - ManagementBaseObject inParams = processClass.GetMethodParameters("Create"); - inParams["CommandLine"] = cmdFilePath; - ManagementBaseObject outParams = processClass.InvokeMethod("Create", inParams, null); - - } - } - catch - { } - } - #region Advanced Delete /// /// Deletes the specified file. diff --git a/WebsitePanel/Sources/WebsitePanel.Server/OperatingSystem.asmx.cs b/WebsitePanel/Sources/WebsitePanel.Server/OperatingSystem.asmx.cs index d226536f..e258900a 100644 --- a/WebsitePanel/Sources/WebsitePanel.Server/OperatingSystem.asmx.cs +++ b/WebsitePanel/Sources/WebsitePanel.Server/OperatingSystem.asmx.cs @@ -533,39 +533,6 @@ namespace WebsitePanel.Server throw; } } - - - [WebMethod, SoapHeader("settings")] - public void SetQuotaLimitOnFolder(string cmdFilePath, string virtualFileClusterName, string folderPath, string quotaLimit, int mode, string wmiUserName, string wmiPassword) - { - try - { - Log.WriteStart("'{0}' SetQuotaLimitOnFolder", ProviderSettings.ProviderName); - OsProvider.SetQuotaLimitOnFolder(cmdFilePath, virtualFileClusterName, folderPath, quotaLimit, mode, wmiUserName, wmiPassword); - Log.WriteEnd("'{0}' SetQuotaLimitOnFolder", ProviderSettings.ProviderName); - } - catch (Exception ex) - { - Log.WriteError(String.Format("'{0}' SetQuotaLimitOnFolder", ProviderSettings.ProviderName), ex); - throw; - } - } - - [WebMethod, SoapHeader("settings")] - public void DeleteDirectoryRecursive(string rootPath) - { - try - { - Log.WriteStart("'{0}' DeleteDirectoryRecursive", ProviderSettings.ProviderName); - OsProvider.DeleteDirectoryRecursive(rootPath); - Log.WriteEnd("'{0}' DeleteDirectoryRecursive", ProviderSettings.ProviderName); - } - catch (Exception ex) - { - Log.WriteError(String.Format("'{0}' DeleteDirectoryRecursive", ProviderSettings.ProviderName), ex); - throw; - } - } #endregion #region Synchronizing diff --git a/WebsitePanel/Sources/WebsitePanel.Server/Web.config b/WebsitePanel/Sources/WebsitePanel.Server/Web.config index f4c59fb4..48568b3a 100644 --- a/WebsitePanel/Sources/WebsitePanel.Server/Web.config +++ b/WebsitePanel/Sources/WebsitePanel.Server/Web.config @@ -44,7 +44,7 @@ - + diff --git a/WebsitePanel/Sources/WebsitePanel.Server/WebsitePanel.Server.csproj b/WebsitePanel/Sources/WebsitePanel.Server/WebsitePanel.Server.csproj index 5c4731db..890ebc21 100644 --- a/WebsitePanel/Sources/WebsitePanel.Server/WebsitePanel.Server.csproj +++ b/WebsitePanel/Sources/WebsitePanel.Server/WebsitePanel.Server.csproj @@ -20,10 +20,6 @@ v3.5 false - - - - true @@ -235,7 +231,6 @@ - diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/WebsitePanel.WebPortal.csproj b/WebsitePanel/Sources/WebsitePanel.WebPortal/WebsitePanel.WebPortal.csproj index e852620d..c93b1a73 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/WebsitePanel.WebPortal.csproj +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/WebsitePanel.WebPortal.csproj @@ -241,7 +241,6 @@ - From af1a156b18247aff8c090303ce3e566dbaa07aa7 Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Tue, 18 Sep 2012 22:35:21 -0400 Subject: [PATCH 13/13] Added tag build-2.0.0.41 for changeset 93d247d79145