Initial project's source code check-in.

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

View file

@ -0,0 +1,684 @@
// Copyright (c) 2011, Outercurve Foundation.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// - Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// - Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// - Neither the name of the Outercurve Foundation nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using System;
using System.IO;
using System.Collections;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.Text;
using WebsitePanel.Providers.Utils;
using WebsitePanel.Server.Utils;
using WebsitePanel.Providers.Utils.LogParser;
using Microsoft.Win32;
namespace WebsitePanel.Providers.FTP
{
public class Gene6 : HostingServiceProviderBase, IFtpServer
{
#region Properties
protected string SiteId
{
get { return ProviderSettings["SiteId"]; }
}
protected string InstallFolder
{
get { return FileUtils.EvaluateSystemVariables(ProviderSettings["InstallFolder"]); }
}
#endregion
#region Sites
public virtual bool SiteExists(string siteId)
{
return Directory.Exists(GetDomainPath(siteId));
}
public virtual FtpSite[] GetSites()
{
List<FtpSite> sites = new List<FtpSite>();
// get all domain directories
string[] domainNames = Directory.GetDirectories(GetAccountsPath());
foreach (string domainName in domainNames)
{
sites.Add(GetSite(Path.GetFileName(domainName)));
}
return sites.ToArray();
}
public virtual FtpSite GetSite(string siteId)
{
// load domain
ServerState state = ServerState.Started;
return LoadDomain(siteId, out state);
}
public virtual string CreateSite(FtpSite site)
{
// create site
SaveDomain(site, ServerState.Started);
// create "users" directory
Directory.CreateDirectory(GetDomainPath(site.Name) + "\\users");
// create "groups" directory
Directory.CreateDirectory(GetDomainPath(site.Name) + "\\groups");
return site.Name;
}
public virtual void UpdateSite(FtpSite site)
{
// get original site state
ServerState state = ServerState.Started;
LoadDomain(site.Name, out state);
// create site
SaveDomain(site, state);
}
public virtual void DeleteSite(string siteId)
{
// delete domain directory
Directory.Delete(GetDomainPath(siteId), true);
}
public virtual void ChangeSiteState(string siteId, ServerState state)
{
// get original site state
ServerState origState = ServerState.Started;
FtpSite site = LoadDomain(siteId, out origState);
// create site
SaveDomain(site, state);
}
public virtual ServerState GetSiteState(string siteId)
{
// load domain
ServerState state = ServerState.Started;
LoadDomain(siteId, out state);
return state;
}
#endregion
#region Accounts
public virtual bool AccountExists(string accountName)
{
string accountPath = GetUserSettingsPath(SiteId, accountName);
return File.Exists(accountPath);
}
public virtual FtpAccount[] GetAccounts()
{
List<FtpAccount> accounts = new List<FtpAccount>();
// get all settings files in directory
string usersPath = Path.Combine(GetDomainPath(SiteId), "users");
string[] files = Directory.GetFiles(usersPath, "*.ini");
foreach (string file in files)
{
accounts.Add(GetAccount(Path.GetFileNameWithoutExtension(Path.GetFileName(file))));
}
return accounts.ToArray();
}
public virtual FtpAccount GetAccount(string accountName)
{
string accountPath = GetUserSettingsPath(SiteId, accountName);
if (!File.Exists(accountPath))
return null;
// load account settings
NameValueCollection dict = ReadSettingsFile(accountPath);
if (dict == null)
return null;
FtpAccount account = new FtpAccount();
account.Name = accountName;
// acccess rights
string acr = dict["AccessList0"];
if (acr != null)
{
string[] acrParts = acr.Split(',');
account.Folder = acrParts[1];
account.CanRead = (acrParts[2][0] == 'R' && acrParts[3][0] == 'F');
account.CanWrite = (acrParts[2][1] == 'W');
}
account.Enabled = (dict["Enabled"] == "-1");
return account;
}
public virtual void CreateAccount(FtpAccount account)
{
// get default account settings
DateTime created = DateTime.Now;
NameValueCollection dict = GetAccountDefaultSettings();
dict["AccessList0"] = BildAccountAccessList(account);
dict["CreationDate"] = created.ToString("yyyy/MM/dd HH:mm:ss");
dict["ExpirationDate"] = created.ToString("yyyy/MM/dd");
dict["Password"] = "MD5:" + MD5(account.Password);
dict["Enabled"] = account.Enabled ? "-1" : "0";
// save account settings
SaveSettingsFile(GetUserSettingsPath(SiteId, account.Name), "Account", dict);
// fluch cache
FlushCache();
}
public virtual void UpdateAccount(FtpAccount account)
{
// load account settings
NameValueCollection dict = ReadSettingsFile(GetUserSettingsPath(SiteId, account.Name));
if (dict == null)
return;
// update account properties
dict["AccessList0"] = BildAccountAccessList(account);
// change password if required
if (!String.IsNullOrEmpty(account.Password))
dict["Password"] = "MD5:" + MD5(account.Password);
dict["Enabled"] = account.Enabled ? "-1" : "0";
// save account settings
SaveSettingsFile(GetUserSettingsPath(SiteId, account.Name), "Account", dict);
// fluch cache
FlushCache();
}
public virtual void DeleteAccount(string accountName)
{
// delete account file
string accountPath = GetUserSettingsPath(SiteId, accountName);
if (File.Exists(accountPath))
File.Delete(accountPath);
// fluch cache
FlushCache();
}
#endregion
#region HostingServiceProvier methods
public override string[] Install()
{
List<string> messages = new List<string>();
// check Gene6 folder exists
try
{
if (!Directory.Exists(InstallFolder))
messages.Add(String.Format("Specified '{0}' installation folder does not exist", InstallFolder));
}
catch (Exception ex)
{
messages.Add(String.Format("Could not check existance of the installation folder: {0}", ex.Message));
return messages.ToArray();
}
// check if siteId is selected
if (String.IsNullOrEmpty(SiteId))
messages.Add("FTP Site should be selected");
return messages.ToArray();
}
public override void ChangeServiceItemsState(ServiceProviderItem[] items, bool enabled)
{
foreach (ServiceProviderItem item in items)
{
if (item is FtpAccount)
{
try
{
// make FTP account read-only
FtpAccount account = GetAccount(item.Name);
account.Enabled = enabled;
UpdateAccount(account);
}
catch (Exception ex)
{
Log.WriteError(String.Format("Error switching '{0}' {1}", item.Name, item.GetType().Name), ex);
}
}
}
}
public override void DeleteServiceItems(ServiceProviderItem[] items)
{
foreach (ServiceProviderItem item in items)
{
if (item is FtpAccount)
{
try
{
// delete FTP account from default FTP site
DeleteAccount(item.Name);
}
catch (Exception ex)
{
Log.WriteError(String.Format("Error deleting '{0}' {1}", item.Name, item.GetType().Name), ex);
}
}
}
}
public override ServiceProviderItemBandwidth[] GetServiceItemsBandwidth(ServiceProviderItem[] items, DateTime since)
{
ServiceProviderItemBandwidth[] itemsBandwidth = new ServiceProviderItemBandwidth[items.Length];
// create parser object
// and update statistics
LogParser parser = new LogParser("Gene6Ftp", SiteId, GetLogsPath(), "cs-username");
parser.ParseLogs();
// update items with diskspace
for (int i = 0; i < items.Length; i++)
{
ServiceProviderItem item = items[i];
// create new bandwidth object
itemsBandwidth[i] = new ServiceProviderItemBandwidth();
itemsBandwidth[i].ItemId = item.Id;
itemsBandwidth[i].Days = new DailyStatistics[0];
if (item is FtpAccount)
{
try
{
// get daily statistics
itemsBandwidth[i].Days = parser.GetDailyStatistics(since, new string[] { item.Name });
}
catch (Exception ex)
{
Log.WriteError(ex);
}
}
}
return itemsBandwidth;
}
#endregion
#region Private helper methods
private string BildAccountAccessList(FtpAccount account)
{
StringBuilder sb = new StringBuilder();
sb.Append("/,")
.Append(account.Folder).Append(",");
// file permissions
sb.Append(account.CanRead ? "R" : "-")
.Append(account.CanWrite ? "W" : "-")
.Append(account.CanWrite ? "D" : "-")
.Append(account.CanWrite ? "A" : "-")
.Append(",");
// folder permissions
sb.Append(account.CanRead ? "F" : "-")
.Append(account.CanRead ? "D" : "-")
.Append(account.CanWrite ? "M" : "-")
.Append(account.CanWrite ? "R" : "-")
.Append(account.CanRead ? "I" : "-")
.Append("---,");
return sb.ToString();
}
private void SaveDomain(FtpSite site, ServerState state)
{
StringBuilder sb = new StringBuilder();
// append header
sb.Append("[Domain]\n");
// build IP bindings
if (site.Bindings != null)
{
for (int i = 0; i < site.Bindings.Length; i++)
{
ServerBinding binding = site.Bindings[i];
sb.Append("IP").Append(i).Append("=")
.Append((binding.IP == "" || binding.IP == "*") ? "*" : binding.IP).Append(",")
.Append(binding.Port).Append(",\n");
}
}
// site state
string domainStatus = "0"; // online "1" - closed, "2" - offline
switch (state)
{
case ServerState.Continuing: domainStatus = "0"; break; // online
case ServerState.Paused: domainStatus = "1"; break; // closed
case ServerState.Started: domainStatus = "0"; break; // online
case ServerState.Stopped: domainStatus = "2"; break; // offline
default: domainStatus = "0"; break; // online
}
sb.Append("Status=").Append(domainStatus).Append("\n");
// footer (default settings)
sb.Append(@"LogList0=Default,W3C,""-1,$DOM_NAME-$year-$mm-$dd.log,0""
LogList1=Transfers,W3C,""-1,$DOM_NAME-$year-$mm-$dd.log,0""
LogList2=Bandwidth,W3C,""-1,$DOM_NAME-$year-$mm-$dd.log,0""
MaxClients=0
MaxConnectionsPerIP=0
Running=1392
StatsCurrentlyLogged=0
CanDeleteReadOnly=-1
ChangeDataIPDependingOnClientIP=-1
DontLimitSpeedForLAN=-1
DontLimitTransferForLAN=-1
HammerResetOnLogin=-1
LogCacheEnabled=-1
LogEnabled=-1
NoCompressionForLAN=-1
ResolveIP=-1
TransferLimitType=never");
// save domain file
WriteTextFile(GetDomainSettingsPath(site.Name), sb.ToString());
// flush cache
FlushCache();
}
private FtpSite LoadDomain(string domainName, out ServerState siteState)
{
siteState = ServerState.Started;
NameValueCollection dict = ReadSettingsFile(GetDomainSettingsPath(domainName));
if (dict == null)
return null;
// process domain settings
FtpSite site = new FtpSite();
site.Name = domainName;
site.SiteId = domainName;
ArrayList bindings = new ArrayList();
foreach (string key in dict.Keys)
{
string val = dict[key];
// check for binding
if (key.ToUpper().StartsWith("IP"))
{
bool numbers = true;
for (int i = 2; i < key.Length; i++)
{
if (!Char.IsNumber(key[i]))
{
numbers = false;
break;
}
}
if (numbers)
{
// process binding
string[] bindParts = val.Split(',');
bindings.Add(new ServerBinding(((bindParts[0] == "*") ? "" : bindParts[0]),
bindParts[1], ""));
}
}
}
// set bindings
site.Bindings = (ServerBinding[])bindings.ToArray(typeof(ServerBinding));
// status
string domainStatus = dict["Status"];
switch (domainStatus)
{
case "0": siteState = ServerState.Started; break;
case "1": siteState = ServerState.Paused; break;
case "2": siteState = ServerState.Stopped; break;
default: siteState = ServerState.Started; break;
}
return site;
}
private NameValueCollection GetAccountDefaultSettings()
{
NameValueCollection dict = new NameValueCollection();
dict.Add("AccessList0", "/,C:\\2,RWDA,FDMRI---");
dict.Add("CreationDate", "2005/10/14 11:00:30");
dict.Add("Enabled", "-1");
dict.Add("Password", "MD5:827CCB0EEA8A706C4C34A16891F84E7B");
dict.Add("PasswordEnabled", "-1");
dict.Add("ExpirationDate", "2005/10/14");
dict.Add("IncomingFXPAllowed", "-1");
dict.Add("LogEnabled", "-1");
dict.Add("OutgoingFXPAllowed", "-1");
dict.Add("QuotaCheckOnLogin", "-1");
dict.Add("TimeOutEnabled", "-1");
dict.Add("TransferLimitType", "never");
return dict;
}
private void FlushCache()
{
// just create an ampty file
WriteTextFile(GetReloadCachePath(), "");
}
private string GetInstallFolder()
{
string folder = InstallFolder.Replace("/", "\\");
if (folder[folder.Length - 1] != '\\')
folder += "\\";
return folder;
}
private NameValueCollection ReadSettingsFile(string path)
{
NameValueCollection dict = new NameValueCollection();
if (!File.Exists(path))
return null;
StreamReader reader = null;
try
{
reader = new StreamReader(path);
string line = null;
while ((line = reader.ReadLine()) != null)
{
if (line.StartsWith("[") || line.StartsWith(";"))
continue; // skip header and comments
// parse line
string[] parts = line.Trim().Split('=');
dict.Add(parts[0], parts[1]);
}
}
finally
{
reader.Close();
}
return dict;
}
private void SaveSettingsFile(string path, string settingsName, NameValueCollection dict)
{
string fullPath = Path.GetDirectoryName(path);
if (!Directory.Exists(fullPath))
Directory.CreateDirectory(fullPath);
StreamWriter writer = new StreamWriter(path);
try
{
// write header
writer.WriteLine("[" + settingsName + "]");
foreach (string key in dict.Keys)
writer.WriteLine(key + "=" + dict[key]);
}
finally
{
writer.Close();
}
}
private string GetAccountsPath()
{
return GetInstallFolder() + "Accounts";
}
private string GetServerSettingsPath()
{
return GetInstallFolder() + "Accounts\\settings.ini";
}
private string GetDomainPath(string domainName)
{
return GetInstallFolder() + "Accounts\\" + domainName;
}
private string GetDomainSettingsPath(string domainName)
{
return GetInstallFolder() + "Accounts\\" + domainName + "\\settings.ini";
}
private string GetUserSettingsPath(string domainName, string userName)
{
return GetInstallFolder() + "Accounts\\" + domainName + "\\users\\" + userName + ".ini";
}
private string GetReloadCachePath()
{
return GetInstallFolder() + "reload";
}
private string GetLogsPath()
{
return GetInstallFolder() + "Log";
}
private void WriteTextFile(string path, string content)
{
string fullPath = Path.GetDirectoryName(path);
if (!Directory.Exists(fullPath))
Directory.CreateDirectory(fullPath);
StreamWriter writer = new StreamWriter(path);
try
{
writer.Write(content);
}
finally
{
writer.Close();
}
}
private string ReadTextFile(string path)
{
if (!File.Exists(path))
return null;
string content = null;
StreamReader reader = null;
try
{
reader = new StreamReader(path);
content = reader.ReadToEnd();
}
finally
{
reader.Close();
}
return content;
}
private string MD5(string str)
{
System.Text.UTF8Encoding ue = new System.Text.UTF8Encoding();
byte[] bytes = ue.GetBytes(str);
// encrypt bytes
System.Security.Cryptography.MD5CryptoServiceProvider md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] hashBytes = md5.ComputeHash(bytes);
// Convert the encrypted bytes back to a string (base 16)
string hashString = "";
for (int i = 0; i < hashBytes.Length; i++)
{
hashString += Convert.ToString(hashBytes[i], 16).PadLeft(2, '0');
}
return hashString.PadLeft(32, '0').ToUpper();
}
#endregion
public override bool IsInstalled()
{
string versionNumber = null;
RegistryKey HKLM = Registry.LocalMachine;
RegistryKey key = HKLM.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Gene6 FTP Server_is1");
if (key != null)
{
versionNumber = (string)key.GetValue("DisplayVersion");
}
else
{
key = HKLM.OpenSubKey(@"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Gene6 FTP Server_is1");
if (key != null)
{
versionNumber = (string)key.GetValue("DisplayVersion");
}
else
{
return false;
}
}
string[] split = versionNumber.Split(new char[] { '.' });
return split[0].Equals("3");
}
}
}

View file

@ -0,0 +1,21 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("WebsitePanel.Providers.FTP.Gene6")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyProduct("WebsitePanel.Providers.FTP.Gene6")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("073b5f87-2aae-4038-9ee7-4c56696f8627")]

View file

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{3148C2B2-8002-4FBE-9665-C65A83FA5F14}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>WebsitePanel.Providers.FTP</RootNamespace>
<AssemblyName>WebsitePanel.Providers.FTP.Gene6</AssemblyName>
<FileUpgradeFlags>
</FileUpgradeFlags>
<OldToolsVersion>3.5</OldToolsVersion>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\WebsitePanel.Server\bin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<WarningsAsErrors>618</WarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\WebsitePanel.Server\bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<WarningsAsErrors>618</WarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\VersionInfo.cs">
<Link>VersionInfo.cs</Link>
</Compile>
<Compile Include="Gene6FTP.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\WebsitePanel.Providers.Base\WebsitePanel.Providers.Base.csproj">
<Project>{684C932A-6C75-46AC-A327-F3689D89EB42}</Project>
<Name>WebsitePanel.Providers.Base</Name>
</ProjectReference>
<ProjectReference Include="..\WebsitePanel.Server.Utils\WebsitePanel.Server.Utils.csproj">
<Project>{E91E52F3-9555-4D00-B577-2B1DBDD87CA7}</Project>
<Name>WebsitePanel.Server.Utils</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
<Visible>False</Visible>
<ProductName>Windows Installer 3.1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>