using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.IO; using System.Web; using System.Globalization; using System.Data; namespace WmDirectAdminLibrary { /// /// API Wrapper for DirectAdmin /// created by W.L. Middelkoop, 14-aug-2009 @ 10:06hrs /// public class WmDirectAdminApi { protected static string serverApiUrl; protected static string username; protected static string password; protected static CultureInfo usCulture; public static void initDirectAdminApi(string serverIp, string apiUsername, string apiPassword) { serverApiUrl = "http://" + serverIp + ":2222"; username = apiUsername; password = apiPassword; usCulture = new CultureInfo("en-US"); } /// 2 started; 4 stopped (these odd codes come from Windows IIS where multiple states are possible, including starting, stopping, paused etc) public static int getVirtualHostingStatus(string domainName) { string domainsUrl = serverApiUrl + "/CMD_API_ADDITIONAL_DOMAINS?action=view&domain="+domainName; string response = HttpUtility.UrlDecode(getResponseFromServer(domainsUrl, null)).ToLower(); if (response.IndexOf("suspended=yes") != -1) { return 4; } else if (response.IndexOf("suspended=no") != -1) { return 2; } else { return -1; } } public static bool startVirtualHosting(string domainName) { int currentStatus = getVirtualHostingStatus(domainName); if (currentStatus != 2) { // 2 is Windows IIS for started return toggleVirtualHostingStatus(domainName); } return true; // status is already started } public static bool stopVirtualHosting(string domainName) { int currentStatus = getVirtualHostingStatus(domainName); if (currentStatus != 4) { // 4 is Windows IIS for stopped return toggleVirtualHostingStatus(domainName); } return true; // status is already stopped } protected static bool toggleVirtualHostingStatus(string domainName) { string url = serverApiUrl + "/CMD_API_DOMAIN"; List domainVariables = new List(); domainVariables.Add(new PostVariable("action", "select")); domainVariables.Add(new PostVariable("suspend", domainName)); domainVariables.Add(new PostVariable("select0", domainName)); string response = HttpUtility.UrlDecode(getResponseFromServer(url, domainVariables)); if (response.StartsWith("error=0")) { return true; } else { return false; } } /// /// Returns a string[] of existing domains /// public static string[] getVirtualHostingDomainNames() { string url = serverApiUrl + "/CMD_API_SHOW_DOMAINS"; string response = getResponseFromServer(url, null); response = HttpUtility.UrlDecode(response); response = response.Replace("&", ""); response = response.Replace("list[]=", "|"); if (response.StartsWith("|")) { response = response.Substring(1); // remove the first splitting char from the string } string[] domains = response.Split('|'); return domains; } public static bool createVirtualHosting(string domainName) { if (isDomainExistant(domainName)) { // kill it the hard way. throw new Exception("WmDirectAdminApi: Domain "+domainName+" already exists on server."); } // from here I assume that it is safe to continue creating an domain with FTP: string createDomainUrl = serverApiUrl + "/CMD_API_DOMAIN"; List createDomainVariables = new List(); createDomainVariables.Add(new PostVariable("action", "create")); createDomainVariables.Add(new PostVariable("domain", domainName)); createDomainVariables.Add(new PostVariable("ubandwidth", "unlimited")); createDomainVariables.Add(new PostVariable("uquota", "uquota")); createDomainVariables.Add(new PostVariable("cgi", "OFF")); createDomainVariables.Add(new PostVariable("ssl", "OFF")); createDomainVariables.Add(new PostVariable("php", "ON")); string createDomainResponse = getResponseFromServer(createDomainUrl, createDomainVariables); if (createDomainResponse.StartsWith("error=0")) { // error=0 is DirectAdmin's way of telling that it is OKAY return true; } else { return false; } } public static long getVirtualHostingUsage(string domainName) { string domainsUrl = serverApiUrl + "/CMD_API_SHOW_USER_DOMAINS?user=lemmid"; string response = getResponseFromServer(domainsUrl,null); int domainIndex = response.IndexOf(domainName); if (domainIndex > -1) { string data = response.Substring(domainIndex); int nextDomainIndex = data.IndexOf("&"); if (nextDomainIndex == -1) { nextDomainIndex = data.Length; } data = data.Substring(0, nextDomainIndex); string[] dataValues = data.Split(':'); string valueAsString = dataValues[2]; double valueInMb = double.Parse(valueAsString,usCulture); double valueInBytes = valueInMb * 1024 * 1024; long valueAsLong = (long)Math.Round(valueInBytes); return valueAsLong; } else { return -1; } } public static bool removeVirtualHosting(string domainName) { string deleteDomainUrl = serverApiUrl + "/CMD_API_DOMAIN"; List domainVariables = new List(); domainVariables.Add(new PostVariable("action", "delete")); domainVariables.Add(new PostVariable("delete", domainName)); domainVariables.Add(new PostVariable("domain", domainName)); domainVariables.Add(new PostVariable("select0", domainName)); domainVariables.Add(new PostVariable("confirmed", "true")); string domainResponse = getResponseFromServer(deleteDomainUrl, domainVariables); if (domainResponse.StartsWith("error=0")) { // error=0 is DirectAdmin's way of telling that it is OKAY return true; } else { return false; } } public static bool removeFtpAccount(string domainName) { string removeFtpUrl = serverApiUrl + "/CMD_API_FTP"; string ftpPassword = FtpPasswordGenerator.getRandomPassword(); List ftpVariables = new List(); ftpVariables.Add(new PostVariable("action", "delete")); ftpVariables.Add(new PostVariable("domain", domainName)); ftpVariables.Add(new PostVariable("select0", "ftp")); string ftpResponse = HttpUtility.UrlDecode(getResponseFromServer(removeFtpUrl, ftpVariables)); if (ftpResponse.StartsWith("error=0")) { return true; } else { return false; } } public static bool setFtpAccountPassword(string domainName, string newPassword) { string modifyFtpUrl = serverApiUrl + "/CMD_API_FTP"; List ftpVariables = new List(); ftpVariables.Add(new PostVariable("action", "modify")); ftpVariables.Add(new PostVariable("domain", domainName)); ftpVariables.Add(new PostVariable("user", "ftp")); // will end up like ftp@domainname.tld ftpVariables.Add(new PostVariable("type", "custom")); ftpVariables.Add(new PostVariable("custom_val", "/home/lemmid/domains/" + domainName + "/public_html")); ftpVariables.Add(new PostVariable("passwd", newPassword)); ftpVariables.Add(new PostVariable("passwd2", newPassword)); string ftpPasswordResponse = HttpUtility.UrlDecode(getResponseFromServer(modifyFtpUrl, ftpVariables)); if (ftpPasswordResponse.StartsWith("error=0")) { return true; } else { return false; } } public static FtpCredentials createFtpAccount(string domainName) { string createFtpUrl = serverApiUrl + "/CMD_API_FTP"; string ftpPassword = FtpPasswordGenerator.getRandomPassword(); List createFtpVariables = new List(); createFtpVariables.Add(new PostVariable("action", "create")); createFtpVariables.Add(new PostVariable("domain", domainName)); createFtpVariables.Add(new PostVariable("user", "ftp")); // will end up like ftp@domainname.tld createFtpVariables.Add(new PostVariable("type", "custom")); createFtpVariables.Add(new PostVariable("custom_val", "/home/lemmid/domains/" + domainName + "/public_html")); createFtpVariables.Add(new PostVariable("passwd", ftpPassword)); createFtpVariables.Add(new PostVariable("passwd2", ftpPassword)); string createFtpResponse = HttpUtility.UrlDecode(getResponseFromServer(createFtpUrl, createFtpVariables)); if (createFtpResponse.StartsWith("error=0")) { FtpCredentials returnCredentials = new FtpCredentials("ftp@" + domainName, ftpPassword); return returnCredentials; } return null; // in case of error } public static bool isDomainExistant(string domainName) { string[] existingDomains = getVirtualHostingDomainNames(); foreach (string existingDomain in existingDomains) { if (existingDomain.Equals(domainName)) { return true; } } return false; } public static string getResponseFromServer(string url, List postVariables) { WebRequest request = WebRequest.Create(url); string usernamePassword = username + ":" + password; CredentialCache credentialCache = new CredentialCache(); credentialCache.Add(new Uri(serverApiUrl), "Basic", new NetworkCredential(username, password)); request.Credentials = credentialCache; request.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(new ASCIIEncoding().GetBytes(usernamePassword))); if (postVariables != null) { request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; string postString = ""; foreach (PostVariable variable in postVariables) { postString += HttpUtility.UrlEncode(variable.Name) + "=" + HttpUtility.UrlEncode(variable.Value) + "&"; } byte[] postBytes = Encoding.ASCII.GetBytes(postString); request.ContentLength = postBytes.Length; Stream postStream = request.GetRequestStream(); postStream.Write(postBytes, 0, postBytes.Length); postStream.Close(); } else { request.Method = "GET"; } WebResponse response = request.GetResponse(); Stream receiveStream = response.GetResponseStream(); StreamReader reader = new StreamReader(receiveStream, Encoding.UTF8); string content = reader.ReadToEnd(); return content; } } public class PostVariable{ protected string name; protected string value; public PostVariable(string name, string value){ this.name = name; this.value = value; } public string Name{ get { return name;} set { name = value;} } public string Value{ get { return this.value;} set { this.value = value; } } } public class FtpCredentials { protected string ftpUsername; protected string ftpPassword; public FtpCredentials(string ftpUsername, string ftpPassword) { this.ftpUsername = ftpUsername; this.ftpPassword = ftpPassword; } public string FtpUsername { get { return ftpUsername; } set { ftpUsername = value; } } public string FtpPassword { get { return ftpPassword; } set { ftpPassword = value; } } } }