How to programatically log into the WoW site menu

Shout-Out

User Tag List

Results 1 to 11 of 11
  1. #1
    Apoc's Avatar Angry Penguin
    Reputation
    1387
    Join Date
    Jan 2008
    Posts
    2,750
    Thanks G/R
    0/12
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    How to programatically log into the WoW site

    After quite a few requests for my login code for the WoW Account Management site, I might as well hand it over. (Or at least a small version of it )

    Keep in mind, I'm only deal with EU and US WoW. Not Asia. For two reasons. 1) I can't read a damned thing on the Asia site. 2) I don't really care about Asian accounts.

    First of all, we need a way to send and receive HTTP requests and responses. We can either use a long method that we can write each little bit (using HttpWebRequest/Response), or we can use the WebClient class. (Which is what we'll be using)

    The only downside to using the WebClient class, is that it doesn't support cookies by default, whereas a custom written method can support it easily. (But with more work, obviously)

    So first things first, let's make the WebClient class support cookies!

    This is really really hard, so stay with me here.

    Code:
    /// <summary>
        /// WebClientEx is a replacement for the WebClient class. This extended class has support for cookies.
        /// </summary>
        public class WebClientEx : WebClient
        {
            // Our CookieContainer object that we'll be using.
            private CookieContainer cookieJar;
    
    
            /// <summary>
            /// Gets or sets the cookies.
            /// </summary>
            /// <value>The cookies.</value>
            public CookieContainer Cookies
            {
                get
                {
                    // We don't want to be grabbing a null item.
                    // So let's initialize it.
                    if (cookieJar == null)
                    {
                        cookieJar = new CookieContainer();
                    }
                    return cookieJar;
                }
                set { cookieJar = value; }
            }
    
            /// <summary>
            /// Clears the cookies.
            /// </summary>
            public void ClearCookies()
            {
                cookieJar = new CookieContainer();
            }
    
            ///<summary>
            ///Returns a <see cref="T:System.Net.WebRequest" /> object for the specified resource.
            ///</summary>
            ///
            ///<returns>
            ///A new <see cref="T:System.Net.WebRequest" /> object for the specified resource.
            ///</returns>
            ///
            ///<param name="address">A <see cref="T:System.Uri" /> that identifies the resource to request.</param>
            protected override WebRequest GetWebRequest(Uri address)
            {
                // Let our parent method do what it needs to do
                // and grab that request. (It does some initial
                // setup, and checks that we don't need to rewrite)
                WebRequest webRequest = base.GetWebRequest(address);
    
                // Keep ourselves typesafe :)
                if (webRequest is HttpWebRequest)
                {
                    // Set our cookie container property so we can now
                    // store cookies with the WebClient class!
                    (webRequest as HttpWebRequest).CookieContainer = cookieJar;
                }
    
                return webRequest;
            }
        }
    I know, that was really difficult. [/sarcasm]

    Basically, all we've done is override one method, and add a method.

    Now when you use WebClientEx, you can access the current cookies for the class via the 'Cookies' property of the class, and easily clear them by using ClearCookies();.

    We're using a descendant of the WebClient class, because it provides many many ways of HTTP connections, and makes it easier in the end. (Trust me...)

    So, now we have a way to send and get HTTP requests and responses, all we have to do now, is log in. (This is where it gets tricky)

    First of all, we're going to need a few URLs.

    The first two are easy, EU and US login URLs. We'll store these in 'const's since they should never change throughout the program.

    At the time of this post (Oct. 1, 200 these URLs are the following:

    Code:
            public const string EU_LOGIN_URL = @"https://www.wow-europe.com/login/login?service=https%3A%2F%2Fwww.wow-europe.com%2Faccount%2F";
            public const string US_LOGIN_URL = @"https://www.worldofwarcraft.com/login/login?service=https%3A%2F%2Fwww.worldofwarcraft.com%2Faccount%2F";
    These are just the two URLs that show the login page. (Where you enter your account name, and password) There's quite a few things we need to do on this page.

    Next up is the logout pages. (Again, in constants since they'll never change.)

    Code:
            public const string EU_LOGOUT_URL = @"https://www.wow-europe.com/account/logout.html";
            public const string US_LOGOUT_URL = @"https://www.worldofwarcraft.com/account/logout.html";
    Next up is something to save ourselves from doing silly checks, when the site is offline. These are incredibly difficult to understand, so bear with me.

    [/code] public static bool UsLoginOffline { get; set; }
    public static bool EuLoginOffline { get; set; }[/code]

    Phew... that was tough!

    These are both public and static for a reason. If we're running multiple threads (as I usually do), we won't have both threads storing different values for these two variables. Once one thread see's that either site is offline, all other threads will see it as well.

    Next up we have something I use as a little helper to make my life easier while reading code.

    Code:
        public enum LogonType
        {
            EU,
            US,
            Null
        }
    Pretty self-explanatory. Just makes it easier to separate the login types. (Notice the Null, this can happen in some scenarios)

    Next up is just something I use in Scam Tools Suite to do some diagnostic stuff. You can change it, or omit it if you want. (It's a method for a reason, which I won't go into here as it's more-so for my own use, and doesn't pertain to this tutorial)

    Code:
            public string CurrentPage { get; private set; }
    
            private void SetCurrPage(string page)
            {
                Log.WriteLine(OutputType.Diagnostic, page);
                CurrentPage = page;
            }
    The Log class is just a simple class to handle all my output and logging needs. (Wrote it some time ago, I still use it quite often in GUI programming and multi-threaded environments)

    On to the process of logging in!

    So far, we've gotten the basics ready. We have log in/out URLs, a way to store the page we're currently on, and a way to make sure we're not checking a site that is offline.

    I'll explain the login process for the US site (EU is the same, but with slightly different URLs)
    1. Fetch the login page via our US_LOGIN_URL string.
    2. Check if the US login page is offline. (It will display certain text that we'll get to soon) If it's offline, set our UsLoginOffline bool to true.
    3. Next, we need to setup some POST data info (again, will be talked about below) to send to the WoW login page.
    4. In the POST data, we need to feed it what's called an LT Signature. I'll explain this below as well.
    5. We send our POST request to the US_LOGIN_URL to actually log in.
    6. We read the next URL in the process to see if we have successfully logged in.
    7. If we logged in correctly, we're done! And we can move on to checking other information as well. (BC Enabled, Trial, Active, etc etc)


    This looks like a lot, but it really isn't.

    We'll go step by step, adding new pieces to our class as we go.

    First of all, we'll setup our class to have what we need in it. (For the sake of argument, we'll call this class AccountManagement, feel free to rename it to whatever you please)

    Here's the base setup so far:

    Code:
    using System;
    using System.Net;
    
    namespace WoWLogin
    {
        public enum LogonType
        {
            EU,
            US,
            Null
        }
    
        public class AccountManagement
        {
            public const string EU_LOGOUT_URL = @"https://www.wow-europe.com/account/logout.html";
            public const string US_LOGOUT_URL = @"https://www.worldofwarcraft.com/account/logout.html";
            public const string EU_LOGIN_URL = @"https://www.wow-europe.com/login/login?service=https%3A%2F%2Fwww.wow-europe.com%2Faccount%2F";
            public const string US_LOGIN_URL = @"https://www.worldofwarcraft.com/login/login?service=https%3A%2F%2Fwww.worldofwarcraft.com%2Faccount%2F";
            
            /// <summary>
            /// The WebClientEx instance assigned to this AccountManagement instance.
            /// </summary>
            public readonly WebClientEx Web;
            
            /// <summary>
            /// Initializes a new instance of the <see cref="AccountManagement"/> class.
            /// </summary>
            public AccountManagement()
            {
                Web = new WebClientEx();
                Type = LogonType.US;
            }
    
            /// <summary>
            /// Gets or sets a value indicating whether the US Login site is offline (This happens usually on Tuesdays.
            /// </summary>
            /// <value><c>true</c> if US Login site is offline; otherwise, <c>false</c>.</value>
            public static bool UsLoginOffline { get; set; }
            /// <summary>
            /// Gets or sets a value indicating whether EU Login site is offline.
            /// </summary>
            /// <value><c>true</c> if EU Login site is offline; otherwise, <c>false</c>.</value>
            public static bool EuLoginOffline { get; set; }
    
            /// <summary>
            /// Gets or sets the type.
            /// </summary>
            /// <value>The type.</value>
            private LogonType Type { get; set; }
    
            /// <summary>
            /// Gets the current page.
            /// </summary>
            /// <value>The current page.</value>
            public string CurrentPage { get; private set; }
    
            /// <summary>
            /// Sets the current page. And writes the output to our Log class.
            /// </summary>
            /// <param name="page">The page.</param>
            private void SetCurrPage(string page)
            {
                Log.WriteLine(OutputType.Diagnostic, page);
                CurrentPage = page;
            }
    
            public FullAccount Login(Account account)
            {
                if (!UsLoginOffline)
                {
                    try
                    {
                        SetCurrPage(Web.DownloadString(US_LOGIN_URL));
                        if (PageIsOffline(CurrentPage))
                        {
                            UsLoginOffline = true;
                            // Throw an exception to skip to our finally statement.
                            // This exception is just a quick skip.
                            throw new Exception("US login is offline.");
                        }
                    }
                    catch (WebException ex)
                    {
                        Log.WriteException(OutputType.Quiet, ex);
                    }
                    catch (Exception ex)
                    {
                        Log.WriteException(OutputType.Quiet, ex);
                    }
                    finally
                    {
                        Web.ClearCookies();
                    }
                }
                return null;
            }
    
            private bool PageIsOffline(string page)
            {
                return page.ToUpper().Contains("SERVICE TEMPORARILY UNAVAILABLE");
            }
        }
    }
    If you'll notice, our Login method returns a FullAccount, and takes an Account as a parameter. For now, just imagine that Account is just a container for an account name, and password. (2 strings) And FullAccount is the same, but with a bit of extra info (it includes the LogonType). I'll give these to you at the end. Just image they're there for now.

    Keep in mind our use of try/catch/finally. All our main logic will be within the try block, while we're of course, catching the other exceptions, and finally clearing cookies before we head over to the EU page (which I won't be showing in this tutorial, but is available in the classes at the bottom)

    We've also added the PageIsOffline bool statement. We use this to tell if the page is offline, and if it is, set our other bool UsLoginOffline to true.

    Now that we've checked if the site is online, we can move on.

    Code:
    public class AccountManagement
        {
            public const string EU_LOGOUT_URL = @"https://www.wow-europe.com/account/logout.html";
            public const string US_LOGOUT_URL = @"https://www.worldofwarcraft.com/account/logout.html";
            public const string EU_LOGIN_URL = @"https://www.wow-europe.com/login/login?service=https%3A%2F%2Fwww.wow-europe.com%2Faccount%2F";
            public const string US_LOGIN_URL = @"https://www.worldofwarcraft.com/login/login?service=https%3A%2F%2Fwww.worldofwarcraft.com%2Faccount%2F";
    
            /// <summary>
            /// The WebClientEx instance assigned to this AccountManagement instance.
            /// </summary>
            public readonly WebClientEx Web;
    
            /// <summary>
            /// Initializes a new instance of the <see cref="AccountManagement"/> class.
            /// </summary>
            public AccountManagement()
            {
                Web = new WebClientEx();
                Type = LogonType.US;
            }
    
            /// <summary>
            /// Gets or sets a value indicating whether the US Login site is offline (This happens usually on Tuesdays.
            /// </summary>
            /// <value><c>true</c> if US Login site is offline; otherwise, <c>false</c>.</value>
            public static bool UsLoginOffline { get; set; }
            /// <summary>
            /// Gets or sets a value indicating whether EU Login site is offline.
            /// </summary>
            /// <value><c>true</c> if EU Login site is offline; otherwise, <c>false</c>.</value>
            public static bool EuLoginOffline { get; set; }
    
            /// <summary>
            /// Gets or sets the type.
            /// </summary>
            /// <value>The type.</value>
            private LogonType Type { get; set; }
    
            /// <summary>
            /// Gets the current page.
            /// </summary>
            /// <value>The current page.</value>
            public string CurrentPage { get; private set; }
    
            /// <summary>
            /// Sets the current page. And writes the output to our Log class.
            /// </summary>
            /// <param name="page">The page.</param>
            private void SetCurrPage(string page)
            {
                Log.WriteLine(OutputType.Diagnostic, page);
                CurrentPage = page;
            }
    
            public FullAccount Login(Account account)
            {
                if (!UsLoginOffline)
                {
                    try
                    {
                        SetCurrPage(Web.DownloadString(US_LOGIN_URL));
                        if (PageIsOffline(CurrentPage))
                        {
                            UsLoginOffline = true;
                            // Throw an exception to skip to our finally statement.
                            // This exception is just a quick skip.
                            throw new Exception("US login is offline.");
                        }
                        NameValueCollection postData = GetPostData(account.Name, account.Password,
                                                                   GetLtSignature(CurrentPage));
                    }
                    catch (WebException ex)
                    {
                        Log.WriteException(OutputType.Quiet, ex);
                    }
                    catch (Exception ex)
                    {
                        Log.WriteException(OutputType.Quiet, ex);
                    }
                    finally
                    {
                        Web.ClearCookies();
                    }
                }
                return null;
            }
    
            private bool PageIsOffline(string page)
            {
                return page.ToUpper().Contains("SERVICE TEMPORARILY UNAVAILABLE");
            }
    
            private string GetLtSignature(string page)
            {
                return Regex.Match(page, @"(?<=\B<input type=\""hidden\"" name=\""lt\"" value=\"").+\b").Value;
            }
    
    
            private static NameValueCollection GetPostData(string account, string password, string ltSignature)
            {
                return new NameValueCollection
                           {
                               {"username", account},
                               {"password", password},
                               {"lt", ltSignature},
                               {"Login", "Login"}
                           };
            }
        }
    This is our updated class. We're using GetPostData in a separate member just to make maintaining code easier. (We'll only need to change it in one place if Blizzard ever changes it, instead of two)

    It's also a NameValueCollection for a reason. As we'll be using WebClientEx.UploadValues (which is an HTTP POST method).

    You'll also notice another new member. GetLtSignature. This uses a simple Regex check to grab the LT Signature (as explained above) to send to our POST request to log in. Our LT Signature is shown on the log in page, so we're checking from CurrentPage (since we set the current page when we first requested the URL!)

    This is the last update to our class that we need.

    Code:
        public class AccountManagement
        {
            public const string EU_LOGOUT_URL = @"https://www.wow-europe.com/account/logout.html";
            public const string US_LOGOUT_URL = @"https://www.worldofwarcraft.com/account/logout.html";
            public const string EU_LOGIN_URL = @"https://www.wow-europe.com/login/login?service=https%3A%2F%2Fwww.wow-europe.com%2Faccount%2F";
            public const string US_LOGIN_URL = @"https://www.worldofwarcraft.com/login/login?service=https%3A%2F%2Fwww.worldofwarcraft.com%2Faccount%2F";
    
            /// <summary>
            /// The WebClientEx instance assigned to this AccountManagement instance.
            /// </summary>
            public readonly WebClientEx Web;
    
            /// <summary>
            /// Initializes a new instance of the <see cref="AccountManagement"/> class.
            /// </summary>
            public AccountManagement()
            {
                Web = new WebClientEx();
                Type = LogonType.US;
            }
    
            /// <summary>
            /// Gets or sets a value indicating whether the US Login site is offline (This happens usually on Tuesdays.
            /// </summary>
            /// <value><c>true</c> if US Login site is offline; otherwise, <c>false</c>.</value>
            public static bool UsLoginOffline { get; set; }
            /// <summary>
            /// Gets or sets a value indicating whether EU Login site is offline.
            /// </summary>
            /// <value><c>true</c> if EU Login site is offline; otherwise, <c>false</c>.</value>
            public static bool EuLoginOffline { get; set; }
    
            /// <summary>
            /// Gets or sets the type.
            /// </summary>
            /// <value>The type.</value>
            private LogonType Type { get; set; }
    
            /// <summary>
            /// Gets the current page.
            /// </summary>
            /// <value>The current page.</value>
            public string CurrentPage { get; private set; }
    
            /// <summary>
            /// Sets the current page. And writes the output to our Log class.
            /// </summary>
            /// <param name="page">The page.</param>
            private void SetCurrPage(string page)
            {
                Log.WriteLine(OutputType.Diagnostic, page);
                CurrentPage = page;
            }
    
            public FullAccount Login(Account account)
            {
                // Don't do anything if the page is offline.
                if (!UsLoginOffline)
                {
                    try
                    {
                        // Set the current page we'll be using to the US_LOGIN_URL content.
                        SetCurrPage(Web.DownloadString(US_LOGIN_URL));
    
                        // If the page is offline, just skip the rest of the login process.
                        if (PageIsOffline(CurrentPage))
                        {
                            UsLoginOffline = true;
                            // Throw an exception to skip to our finally statement.
                            // This exception is just a quick skip.
                            throw new Exception("US login is offline.");
                        }
                        // Get our post data so we can send it to the WoW page.
                        NameValueCollection postData = GetPostData(account.Name, account.Password,
                                                                   GetLtSignature(CurrentPage));
                        // Send our post data.
                        Web.UploadValues(US_LOGIN_URL, "POST", postData);
    
                        // Grab the next page in the login process to see if we've successfully logged in.
                        // Also set our current page to the content of this page as we'll need it later.
                        SetCurrPage(Web.DownloadString(@"https://www.worldofwarcraft.com/account/index.html?ticket="));
    
                        // Check if we logged in.
                        if (LoginSuccess(CurrentPage))
                        {
                            // We've logged in, so play a sound to say so!
                            System.Media.SystemSounds.Asterisk.Play();
                            return new FullAccount(account, LogonType.US);
                        }
    
                        // We haven't logged in yet. So we can move on to the EU site if we want.
                    }
                    catch (WebException ex)
                    {
                        Log.WriteException(OutputType.Quiet, ex);
                    }
                    catch (Exception ex)
                    {
                        Log.WriteException(OutputType.Quiet, ex);
                    }
                    finally
                    {
                        Web.ClearCookies();
                    }
                }
                return null;
            }
    
            private bool PageIsOffline(string page)
            {
                return page.ToUpper().Contains("SERVICE TEMPORARILY UNAVAILABLE");
            }
    
            private string GetLtSignature(string page)
            {
                return Regex.Match(page, @"(?<=\B<input type=\""hidden\"" name=\""lt\"" value=\"").+\b").Value;
            }
    
            private bool LoginSuccess(string page)
            {
                return page.ToUpper().Contains("LOGIN SUCCESSFUL");
            }
    
            private static NameValueCollection GetPostData(string account, string password, string ltSignature)
            {
                return new NameValueCollection
                           {
                               {"username", account},
                               {"password", password},
                               {"lt", ltSignature},
                               {"Login", "Login"}
                           };
            }
        }
    I've commented this one so I don't need to explain a whole lot. It's fairly self explanatory.

    That's it! That's all you need to login to the WoW Account Management page.

    How to programatically log into the WoW site
  2. #2
    Apoc's Avatar Angry Penguin
    Reputation
    1387
    Join Date
    Jan 2008
    Posts
    2,750
    Thanks G/R
    0/12
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Below is a full set of classes to use. (Including a proper and finished Log class.)

    They include the following:

    WebClientEx
    AccountManagement
    Account
    FullAccount
    Log

    These will make your life easier, as you can just plug and play.

    Note: The AccountManagement class below includes much more 'stuff' to check other things. (It's an older version of my current class, so the regex and content checking is a little... erm... bad)


    Account classes:

    Code:
        public enum AccountStatus
        {
            Frozen,
            Banned,
            Active,
            Trial,
            Unknown
        }
    
        public class Account : IEquatable<Account>
        {
            private static readonly List<char> passChars = new List<char> {'!', '"', '#', '$', ',', '%'};
    
            public Account(string accountName, string password)
            {
                Name = accountName;
                Password = password;
            }
    
            public Account()
            {
                
            }
    
            public string Name { get; set; }
            public string Password { get; set; }
    
    
            public static bool ValidateAccount(string username, string password)
            {
                if (!ValidateUsername(username) || !ValidatePassword(password))
                {
                    return false;
                }
                return username != password;
            }
    
            public static bool ValidatePassword(string password)
            {
                foreach (char c in password)
                {
                    if (!char.IsLetterOrDigit(c) && !passChars.Contains(c))
                    {
                        return false;
                    }
                }
                return password.Length >= 8 && password.Length <= 16;
            }
    
            public static bool ValidateUsername(string username)
            {
                foreach (char c in username)
                {
                    if (!char.IsLetterOrDigit(c))
                    {
                        return false;
                    }
                }
                return username.Length >= 3 && username.Length <= 16;
            }
    
            #region IEquatable<Account> Members
    
            /// <summary>
            /// Indicates whether the current object is equal to another object of the same type.
            /// </summary>
            /// <returns>
            /// true if the current object is equal to the <paramref name="obj" /> parameter; otherwise, false.
            /// </returns>
            /// <param name="obj">An object to compare with this object.</param>
            public bool Equals(Account obj)
            {
                if (ReferenceEquals(null, obj))
                {
                    return false;
                }
                if (ReferenceEquals(this, obj))
                {
                    return true;
                }
                return Equals(obj.Name, Name) && Equals(obj.Password, Password);
            }
    
            #endregion
    
            #region Overrides
    
            /// <summary>
            /// Determines whether the specified <see cref="T:System.Object" /> is equal to the current <see cref="T:System.Object" />.
            /// </summary>
            /// <returns>
            /// true if the specified <see cref="T:System.Object" /> is equal to the current <see cref="T:System.Object" />; otherwise, false.
            /// </returns>
            /// <param name="obj">The <see cref="T:System.Object" /> to compare with the current <see cref="T:System.Object" />. </param>
            /// <exception cref="T:System.NullReferenceException">The <paramref name="obj" /> parameter is null.</exception><filterpriority>2</filterpriority>
            public override bool Equals(object obj)
            {
                if (ReferenceEquals(null, obj))
                {
                    return false;
                }
                if (ReferenceEquals(this, obj))
                {
                    return true;
                }
                return obj.GetType() == typeof (Account) && Equals((Account) obj);
            }
    
            /// <summary>
            /// Serves as a hash function for a particular type. 
            /// </summary>
            /// <returns>
            /// A hash code for the current <see cref="T:System.Object" />.
            /// </returns>
            /// <filterpriority>2</filterpriority>
            public override int GetHashCode()
            {
                unchecked
                {
                    return (Name.GetHashCode() * 397) ^ Password.GetHashCode();
                }
            }
    
            public static bool operator ==(Account left, Account right)
            {
                return Equals(left, right);
            }
    
            public static bool operator !=(Account left, Account right)
            {
                return !Equals(left, right);
            }
    
            /// <summary>
            /// Returns a <see cref="T:System.String" /> that represents the current <see cref="T:System.Object" />.
            /// </summary>
            /// <returns>
            /// A <see cref="T:System.String" /> that represents the current <see cref="T:System.Object" />.
            /// </returns>
            /// <filterpriority>2</filterpriority>
            public override string ToString()
            {
                return string.Format("Name: {0}, Password: {1}", Name, Password);
            }
    
            #endregion
        }
    
        public class FullAccount : Account, IEquatable<FullAccount>
        {
            public FullAccount(Account account, LogonType type) : this(account.Name, account.Password, type) {}
    
            public FullAccount(string account, string password, LogonType type) : base(account, password)
            {
                Type = type;
            }
    
            internal bool Active { get; set; }
            internal bool Banned { get; set; }
            public bool BC { get; set; }
            internal bool Frozen { get; set; }
            internal bool Trial { get; set; }
            public LogonType Type { get; set; }
    
            public AccountStatus Status
            {
                get
                {
                    if (Active)
                    {
                        return AccountStatus.Active;
                    }
                    if (Banned)
                    {
                        return AccountStatus.Banned;
                    }
                    if (Frozen)
                    {
                        return AccountStatus.Frozen;
                    }
                    if (Trial)
                    {
                        return AccountStatus.Trial;
                    }
                    return AccountStatus.Unknown;
                }
            }
    
            #region IEquatable<FullAccount> Members
    
            /// <summary>
            /// Indicates whether the current object is equal to another object of the same type.
            /// </summary>
            /// <returns>
            /// true if the current object is equal to the <paramref name="obj" /> parameter; otherwise, false.
            /// </returns>
            /// <param name="obj">An object to compare with this object.</param>
            public bool Equals(FullAccount obj)
            {
                if (ReferenceEquals(null, obj))
                {
                    return false;
                }
                if (ReferenceEquals(this, obj))
                {
                    return true;
                }
                return base.Equals(obj) && Equals(obj.Type, Type);
            }
    
            #endregion
    
            /// <summary>
            /// Determines whether the specified <see cref="T:System.Object" /> is equal to the current <see cref="T:System.Object" />.
            /// </summary>
            /// <returns>
            /// true if the specified <see cref="T:System.Object" /> is equal to the current <see cref="T:System.Object" />; otherwise, false.
            /// </returns>
            /// <param name="obj">The <see cref="T:System.Object" /> to compare with the current <see cref="T:System.Object" />. </param>
            /// <exception cref="T:System.NullReferenceException">The <paramref name="obj" /> parameter is null.</exception><filterpriority>2</filterpriority>
            public override bool Equals(object obj)
            {
                if (ReferenceEquals(null, obj))
                {
                    return false;
                }
                return ReferenceEquals(this, obj) || Equals(obj as FullAccount);
            }
    
            /// <summary>
            /// Serves as a hash function for a particular type. 
            /// </summary>
            /// <returns>
            /// A hash code for the current <see cref="T:System.Object" />.
            /// </returns>
            /// <filterpriority>2</filterpriority>
            public override int GetHashCode()
            {
                unchecked
                {
                    {
                        return (base.GetHashCode() * 397) ^ Type.GetHashCode();
                    }
                }
            }
    
            public static bool operator ==(FullAccount left, FullAccount right)
            {
                return Equals(left, right);
            }
    
            public static bool operator !=(FullAccount left, FullAccount right)
            {
                return !Equals(left, right);
            }
    
            /// <summary>
            /// Returns a <see cref="T:System.String" /> that represents the current <see cref="T:System.Object" />.
            /// </summary>
            /// <returns>
            /// A <see cref="T:System.String" /> that represents the current <see cref="T:System.Object" />.
            /// </returns>
            /// <filterpriority>2</filterpriority>
            public override string ToString()
            {
                return string.Format("{0}, Status: {1}, BC: {2}, Type: {3}", base.ToString(), Status, BC, Type);
            }
        }
    WebClientEx class:

    Code:
        /// <summary>
        /// WebClientEx is a replacement for the WebClient class. This extended class has support for cookies.
        /// </summary>
        public class WebClientEx : WebClient
        {
            // Our CookieContainer object that we'll be using.
            private CookieContainer cookieJar;
    
    
            /// <summary>
            /// Gets or sets the cookies.
            /// </summary>
            /// <value>The cookies.</value>
            public CookieContainer Cookies
            {
                get
                {
                    // We don't want to be grabbing a null item.
                    // So let's initialize it.
                    if (cookieJar == null)
                    {
                        cookieJar = new CookieContainer();
                    }
                    return cookieJar;
                }
                set { cookieJar = value; }
            }
    
            /// <summary>
            /// Clears the cookies.
            /// </summary>
            public void ClearCookies()
            {
                cookieJar = new CookieContainer();
            }
    
            ///<summary>
            ///Returns a <see cref="T:System.Net.WebRequest" /> object for the specified resource.
            ///</summary>
            ///
            ///<returns>
            ///A new <see cref="T:System.Net.WebRequest" /> object for the specified resource.
            ///</returns>
            ///
            ///<param name="address">A <see cref="T:System.Uri" /> that identifies the resource to request.</param>
            protected override WebRequest GetWebRequest(Uri address)
            {
                // Let our parent method do what it needs to do
                // and grab that request. (It does some initial
                // setup, and checks that we don't need to rewrite)
                WebRequest webRequest = base.GetWebRequest(address);
    
                // Keep ourselves typesafe :)
                if (webRequest is HttpWebRequest)
                {
                    // Set our cookie container property so we can now
                    // store cookies with the WebClient class!
                    (webRequest as HttpWebRequest).CookieContainer = cookieJar;
                }
    
                return webRequest;
            }
        }
    AccountManagement class:

    Code:
        public enum LogonType
        {
            EU,
            US,
            Null
        }
    
        public class AccountManagement
        {
            public const string EU_LOGOUT_URL = @"https://www.wow-europe.com/account/logout.html";
            public const string US_LOGOUT_URL = @"https://www.worldofwarcraft.com/account/logout.html";
            public const string EU_LOGIN_URL = @"https://www.wow-europe.com/login/login?service=https%3A%2F%2Fwww.wow-europe.com%2Faccount%2F";
            public const string US_LOGIN_URL = @"https://www.worldofwarcraft.com/login/login?service=https%3A%2F%2Fwww.worldofwarcraft.com%2Faccount%2F";
    
    
            public readonly WebClientEx Web;
    
            public AccountManagement()
            {
                Web = new WebClientEx();
                Type = LogonType.US;
            }
    
            public static bool UsLoginOffline { get; set; }
            public static bool EuLoginOffline { get; set; }
    
            private LogonType Type { get; set; }
    
            public string CurrentPage { get; private set; }
    
            private void SetCurrPage(string page)
            {
                Log.WriteLine(OutputType.Diagnostic, page);
                CurrentPage = page;
            }
    
            private string GetLtSignature(string page)
            {
                return Regex.Match(page, @"(?<=B<input type=""hidden"" name=""lt"" value="").+b").Value;
            }
    
            private string GetStSignature(string page)
            {
                switch (Type)
                {
                    case LogonType.US:
                        return Regex.Match(page,
                                           @"(?<=https://www.worldofwarcraft.com/account/index.html?ticket=).*(?="";)")
                            .Value;
                    case LogonType.EU:
                        return
                            Regex.Match(page, @"(?<=https://www.wow-europe.com/account/?ticket=).*(?="";)").
                                Value;
                    default:
                        return null;
                }
            }
    
            private static NameValueCollection GetPostData(string account, string password, string ltSignature)
            {
                NameValueCollection postData = new NameValueCollection
                                                   {
                                                       {"username", account},
                                                       {"password", password},
                                                       {"lt", ltSignature},
                                                       {"Login", "Login"}
                                                   };
                return postData;
            }
    
            private void Logout(LogonType type)
            {
                switch (type)
                {
                    case LogonType.US:
                        try
                        {
                            Web.DownloadString(US_LOGOUT_URL);
                        }
                        catch (Exception ex)
                        {
                            Log.WriteLine(OutputType.Normal,
                                          string.Format("Exception while logging out of the US website: {0}", ex.Message), 0);
                            throw;
                        }
                        break;
                    case LogonType.EU:
                        try
                        {
                            Web.DownloadString(EU_LOGOUT_URL);
                        }
                        catch (Exception ex)
                        {
                            Log.WriteLine(OutputType.Normal,
                                          string.Format("Exception while logging out of the EU website: {0}", ex.Message), 0);
                            throw;
                        }
                        break;
                    default:
                        throw new Exception("Type specified was Null.");
                }
                // Make sure we clear our cookies so we don't have some random login left over.
                Web.ClearCookies();
            }
    
            public FullAccount Login(Account account, bool checkAllInfo)
            {
                if (!UsLoginOffline)
                {
                    try
                    {
                        //this.Type = LogonType.US;
                        Log.WriteLine(OutputType.Detailed, "Logging out of the US website.");
                        Logout(LogonType.US);
                        SetCurrPage(Web.DownloadString(US_LOGIN_URL));
                        Log.WriteLine(OutputType.Detailed, "Checking if the US login site is online");
                        if (PageIsOffline(CurrentPage))
                        {
                            UsLoginOffline = true;
                            goto Hell;
                            //throw new LoginPageOfflineException("US Login page is offline.");
                        }
                        Log.WriteLine(OutputType.Detailed, "Setting US POST data string.");
                        NameValueCollection postData = GetPostData(account.Name, account.Password,
                                                                   GetLtSignature(CurrentPage));
                        Log.WriteLine(OutputType.Detailed, "Sending US POST message to log in.");
                        Web.UploadValues(US_LOGIN_URL, "POST", postData);
                        Log.WriteLine(OutputType.Detailed, "Checking if we logged in successfully to US");
                        SetCurrPage(Web.DownloadString(@"https://www.worldofwarcraft.com/account/index.html?ticket="));
                        if (LoginSuccess(CurrentPage))
                        {
                            Log.WriteLine(OutputType.Minimal, "Logged in successfully to US!");
                            if (UserSettings.PlaySounds)
                            {
                                SystemSounds.Asterisk.Play();
                            }
                            if (!checkAllInfo)
                            {
                                return new FullAccount(account.Name, account.Password, LogonType.US);
                            }
                            FullAccount fa = new FullAccount(account.Name, account.Password, LogonType.US);
                            string loginAddress =
                                string.Format(@"https://www.worldofwarcraft.com/account/index.html?ticket={0}",
                                              GetStSignature(
                                                  Web.DownloadString(
                                                      @"https://www.worldofwarcraft.com/account/index.html?ticket=" +
                                                      GetLtSignature(CurrentPage))));
                            SetCurrPage(Web.DownloadString(loginAddress));
                            fa.BC = BurningCrusadeEnabled(CurrentPage, LogonType.US);
                            fa.Active = AccountActive(CurrentPage, LogonType.US);
                            fa.Frozen = AccountFrozen(CurrentPage, LogonType.US);
                            fa.Trial = TrialAccount(CurrentPage, LogonType.US);
                            fa.Banned = AccountBanned(CurrentPage);
                            Log.WriteLine(OutputType.Detailed, fa.ToString());
                            if (fa.Status == AccountStatus.Unknown)
                            {
                                Log.SaveUnknownHtml(CurrentPage, fa.Name, LogonType.US);
                            }
                            return fa;
                        }
                    }
                    catch (WebException ex)
                    {
                        Log.WriteException(OutputType.Quiet, ex);
                        Log.WriteLine(OutputType.Quiet, "{0} ~ Status: {1} ({2}) - {3}", ex.Message,
                                      ((HttpWebResponse)ex.Response).StatusCode,
                                      ((HttpWebResponse)ex.Response).StatusDescription, (int)ex.Status);
                        MessageBox.Show(String.Format("{0} ~ Status: {1} ({2})", ex.Message, ex.Status, (int)ex.Status));
                    }
                    catch (Exception ex)
                    {
                        Log.WriteException(OutputType.Quiet, ex);
                    }
                }
                else if (!EuLoginOffline)
                {
                    try
                    {
                        Log.WriteLine(OutputType.Detailed, "Logging out of the EU website.");
                        Logout(LogonType.EU);
                        SetCurrPage(Web.DownloadString(EU_LOGIN_URL));
                        Log.WriteLine(OutputType.Detailed, "Checking if the EU login site is online");
                        if (PageIsOffline(CurrentPage))
                        {
                            EuLoginOffline = true;
                            goto Hell;
                            //throw new LoginPageOfflineException("US Login page is offline.");
                        }
                        Log.WriteLine(OutputType.Detailed, "Setting EU POST data string.");
                        NameValueCollection postData = GetPostData(account.Name, account.Password,
                                                                   GetLtSignature(CurrentPage));
                        Log.WriteLine(OutputType.Detailed, "Sending EU POST message to log in.");
                        Web.UploadValues(EU_LOGIN_URL, "POST", postData);
                        Log.WriteLine(OutputType.Detailed, "Checking if we logged in successfully to EU");
                        SetCurrPage(Web.DownloadString(@"https://www.wow-europe.com/account/?ticket="));
                        if (LoginSuccess(CurrentPage))
                        {
                            Log.WriteLine(OutputType.Minimal, "Logged in successfully to EU!");
                            if (UserSettings.PlaySounds)
                            {
                                SystemSounds.Asterisk.Play();
                            }
                            if (!checkAllInfo)
                            {
                                return new FullAccount(account.Name, account.Password, LogonType.EU);
                            }
                            FullAccount fa = new FullAccount(account.Name, account.Password, LogonType.EU);
                            string loginAddress = string.Format(@"https://www.wow-europe.com/account/?ticket={0}",
                                                                GetStSignature(
                                                                    Web.DownloadString(
                                                                        @"https://www.wow-europe.com/account/?ticket=" +
                                                                        GetLtSignature(CurrentPage))));
                            SetCurrPage(Web.DownloadString(loginAddress));
                            fa.BC = BurningCrusadeEnabled(CurrentPage, LogonType.EU);
                            fa.Active = AccountActive(CurrentPage, LogonType.EU);
                            fa.Frozen = AccountFrozen(CurrentPage, LogonType.EU);
                            fa.Trial = TrialAccount(CurrentPage, LogonType.EU);
                            fa.Banned = AccountBanned(CurrentPage);
                            if (fa.Status == AccountStatus.Unknown)
                            {
                                Log.SaveUnknownHtml(CurrentPage, fa.Name, LogonType.EU);
                            }
                            return fa;
                        }
                    }
                    catch (WebException ex)
                    {
                        Log.WriteException(OutputType.Quiet, ex);
                        Log.WriteLine(OutputType.Quiet, "{0} ~ Status: {1} ({2}) - {3}", ex.Message,
                                      ((HttpWebResponse)ex.Response).StatusCode,
                                      ((HttpWebResponse)ex.Response).StatusDescription, (int)ex.Status);
                        MessageBox.Show(String.Format("{0} ~ Status: {1} ({2})", ex.Message, ex.Status, (int)ex.Status));
                    }
                    catch (Exception ex)
                    {
                        Log.WriteException(OutputType.Quiet, ex);
                    }
                }
            Hell:
                return null;
            }
    
            #region General Page Status Indicators
    
            private bool LoginSuccess(string page)
            {
                return page.ToUpper().Contains("LOGIN SUCCESSFUL");
            }
    
            private bool PageIsOffline(string page)
            {
                return page.ToUpper().Contains("SERVICE TEMPORARILY UNAVAILABLE");
            }
    
            private bool AccountBanned(string page)
            {
                return
                    page.ToUpper().Contains(
                        "ACCESS TO THIS WORLD OF WARCRAFT ACCOUNT HAS BEEN DISABLED BY BLIZZARD ENTERTAINMENT");
            }
    
            #endregion
    
            #region Account Status Indicators
    
            private bool BurningCrusadeEnabled(string currPage, LogonType type)
            {
                switch (type)
                {
                    case LogonType.US:
                        return currPage.Contains("Burning Crusade [<a href = "/account/download_wow.html">Download</a>]");
                    case LogonType.EU:
                        return currPage.Contains("World of Warcraft + Burning Crusade");
                    default:
                        return false;
                }
            }
    
            private bool AccountActive(string currPage, LogonType type)
            {
                switch (type)
                {
                    case LogonType.US:
                        return currPage.Contains(@"This account is active and can be used for playing.");
                    case LogonType.EU:
                        return currPage.Contains("Active");
                    default:
                        return false;
                }
            }
    
            private bool TrialAccount(string currPage, LogonType type)
            {
                switch (type)
                {
                    case LogonType.US:
                        return
                            currPage.Contains(
                                "This account is a Trial account. A retail Authentication Key will be required to continue playing after the trial time period expires.") ||
                            currPage.Contains("Trial restrictions may remain on the account for up to 72 hours.");
                    default:
                        return false;
                }
            }
    
            private bool AccountFrozen(string currPage, LogonType type)
            {
                switch (type)
                {
                    case LogonType.US:
                        return
                            currPage.Contains(
                                @"This account has been frozen and cannot be used for playing. Please add a payment below to reactivate this account.");
                    default:
                        return false;
                }
            }
    
            #endregion
        }
    Log class:

    Code:
        public delegate void OutputHandler(OutputEventArgs e);
    
        public delegate void LogHandler(LogEventArgs e);
    
        public enum LogType
        {
            Quiet,
            Minimal,
            Normal,
            Detailed,
            Diagnostic
        }
    
        public enum OutputType
        {
            Quiet,
            Minimal,
            Normal,
            Detailed,
            Diagnostic
        }
    
        internal static class Log
        {
            /// <summary>
            /// Gets or sets a value indicating whether output is enabled.
            /// </summary>
            /// <value>
            /// 	<see langword="true"/> if output is enabled; otherwise, <see langword="false"/>.
            /// </value>
            public static bool EnableOutput { get { return Settings.Default.EnableOutput; } set { Settings.Default.EnableOutput = value; } }
    
            /// <summary>
            /// Gets or sets a value indicating whether logging is enabled.
            /// </summary>
            /// <value>
            /// 	<see langword="true"/> if [enable logging]; otherwise, <see langword="false"/>.
            /// </value>
            public static bool EnableLogging { get { return Settings.Default.EnableLogging; } set { Settings.Default.EnableLogging = value; } }
    
            /// <summary>
            /// Gets or sets a value indicating whether logging and output messages should append a short time
            /// string to the prefix of the message. (I.E: [12:51 AM] My Message)
            /// </summary>
            /// <value>
            /// 	<see langword="true"/> if [append short time]; otherwise, <see langword="false"/>.
            /// </value>
            public static bool AppendShortTime { get { return Settings.Default.LogAppendShortTime; } set { Settings.Default.LogAppendShortTime = value; } }
    
            /// <summary>
            /// Gets or sets a value indicating whether to log output messages.
            /// </summary>
            /// <value>
            /// 	<see langword="true"/> if [log when output]; otherwise, <see langword="false"/>.
            /// </value>
            public static bool LogWhenOutput { get { return Settings.Default.LogWhenOutput; } set { Settings.Default.LogWhenOutput = value; } }
    
            private static string _shortTime { get { return string.Format(CultureInfo.InvariantCulture, "[{0}] ", DateTime.Now.ToShortTimeString()); } }
    
            /// <summary>
            /// Gets or sets the log level.
            /// </summary>
            /// <value>The log level.</value>
            public static LogType LogLevel { get { return (LogType)Settings.Default.LoggingLevel; } set { Settings.Default.LoggingLevel = (int)value; } }
    
            /// <summary>
            /// Gets or sets the output level.
            /// </summary>
            /// <value>The output level.</value>
            public static OutputType OutputLevel { get { return (OutputType)Settings.Default.OutputLevel; } set { Settings.Default.OutputLevel = (int)value; } }
    
            /// <summary>
            /// Gets or sets the name of the log file.
            /// </summary>
            /// <value>The name of the log file.</value>
            public static string LogFileName { get { return Settings.Default.LogFileName; } set { Settings.Default.LogFileName = value; } }
    
            /// <summary>
            /// Occurs when a message is sent to the Output system via Write or WriteLine
            /// </summary>
            public static event OutputHandler OnOutput;
    
            /// <summary>
            /// Occurs when a message is sent to the Logging system via LogMessage. Or Write/WriteLine if LogWhenOutput is set to true.
            /// </summary>
            public static event LogHandler OnLog;
    
            private static string _shortDate { get { return DateTime.Now.ToShortDateString().Replace('/', '-'); } }
    
            /// <summary>
            /// Logs the message.
            /// May be used also as a shortcut for String.Format()
            /// </summary>
            /// <param name="level">The level.</param>
            /// <param name="message">The message.</param>
            /// <param name="args">The args.</param>
            public static void LogMessage(LogType level, string message, params object[] args)
            {
                if (level > LogLevel)
                {
                    return;
                }
                if (string.IsNullOrEmpty(LogFileName))
                {
                    throw new LoggingException("LogFileName cannot be null or empty.");
                }
                if (string.IsNullOrEmpty(message))
                {
                    throw new ArgumentNullException("message", "Message cannot be null or empty.");
                }
                message = string.Format(CultureInfo.InvariantCulture, message, args);
                using (TextWriter tw = new StreamWriter(string.Format(Application.StartupPath + "\Logs\{0} {1}.txt", _shortDate, LogFileName), true))
                {
                    if (AppendShortTime)
                    {
                        message = _shortTime + message;
                    }
                    tw.Write(message);
                    InvokeOnLog(new LogEventArgs(message, LogFileName));
                }
            }
    
            private static void _logMessage(LogType level, string message, bool ignoreLevel)
            {
                if (!ignoreLevel && level > LogLevel)
                {
                    return;
                }
                if (string.IsNullOrEmpty(LogFileName))
                {
                    throw new LoggingException("LogFileName cannot be null or empty.");
                }
                if (string.IsNullOrEmpty(message))
                {
                    throw new ArgumentNullException("message", "Message cannot be null or empty.");
                }
                using (TextWriter tw = new StreamWriter(string.Format(Application.StartupPath+"\Logs\{0} {1}.txt", _shortDate, LogFileName), true))
                {
                    tw.Write(message);
                    InvokeOnLog(new LogEventArgs(message, LogFileName));
                }
            }
    
            /// <summary>
            /// Acts as a form of Console.Write where it does not include the NewLine character.
            /// May be used also as a shortcut for String.Format()
            /// </summary>
            /// <param name="level">The level.</param>
            /// <param name="message">The message.</param>
            /// <param name="args">The args.</param>
            public static void Write(OutputType level, string message, params object[] args)
            {
                if (level > OutputLevel)
                {
                    return;
                }
                if (string.IsNullOrEmpty(message))
                {
                    throw new ArgumentNullException("message", "Message cannot be null or empty.");
                }
                message = string.Format(CultureInfo.InvariantCulture, message, args);
                if (AppendShortTime)
                {
                    message = _shortTime + message;
                }
                InvokeOnOutput(new OutputEventArgs(message));
                if (LogWhenOutput)
                {
                    _logMessage((LogType) level, message, true);
                }
            }
    
            /// <summary>
            /// Acts as a form of Console.WriteLine where it includes the NewLine character at the end of the message.
            /// May be used also as a shortcut for String.Format()
            /// </summary>
            /// <param name="level">The level.</param>
            /// <param name="message">The message.</param>
            /// <param name="args">The args.</param>
            public static void WriteLine(OutputType level, string message, params object[] args)
            {
                if (level > OutputLevel)
                {
                    return;
                }
                if (string.IsNullOrEmpty(message))
                {
                    throw new ArgumentNullException("message", "Message cannot be null or empty.");
                }
                message = string.Format(CultureInfo.InvariantCulture, message, args);
                Write(level, message + Environment.NewLine);
            }
    
            /// <summary>
            /// Writes the summary output for an exception thrown during run-time.
            /// </summary>
            /// <param name="level">The level.</param>
            /// <param name="exception">The exception to be summarized and output.</param>
            public static void WriteException(OutputType level,  Exception exception)
            {
                if (exception == null)
                {
                    throw new ArgumentNullException("exception", "Exception cannot be null.");
                }
                string message = string.Format(CultureInfo.InvariantCulture, "Exception thrown: {0}{1}{2}{1}{3}",
                                               exception, Environment.NewLine, exception.Source,
                                               exception.InnerException);
                WriteLine(level, message);
                using (TextWriter tw = new StreamWriter(string.Format(Application.StartupPath + "\Exception Logs\{0} {1}.txt", _shortDate, LogFileName), true))
                {
                    tw.WriteLine(message);
                    InvokeOnLog(new LogEventArgs(message, LogFileName));
                }
            }
    
            //Log.SaveUnknownHtml(CurrentPage, fa.Name, LogonType.US);
            public static void SaveUnknownHtml(string htmlPage, string accountName, LogonType type)
            {
                if (!Directory.Exists("Html Pages"))
                {
                    Directory.CreateDirectory("Html Pages");
                }
                using (TextWriter tw = new StreamWriter(string.Format(Application.StartupPath + @"Html PagesUnknown {0} - {1}.html", accountName, type)))
                {
                    tw.Write(htmlPage);
                }
            }
    
            #region Event Invokers
    
            private static void InvokeOnOutput(OutputEventArgs e)
            {
                OutputHandler Handler = OnOutput;
                if (Handler != null)
                {
                    Handler(e);
                }
            }
    
            private static void InvokeOnLog(LogEventArgs e)
            {
                LogHandler Handler = OnLog;
                if (Handler != null)
                {
                    Handler(e);
                }
            }
    
            #endregion
    
            #region Nested type: LoggingException
    
            [Serializable]
            public class LoggingException : Exception
            {
                //
                // For guidelines regarding the creation of new exception types, see
                //    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp
                // and
                //    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp
                //
    
                public LoggingException() {}
                public LoggingException(string message) : base(message) {}
                public LoggingException(string message, Exception inner) : base(message, inner) {}
    
                protected LoggingException(
                    SerializationInfo info,
                    StreamingContext context)
                    : base(info, context) {}
            }
    
            #endregion
        }
    
        public class OutputEventArgs : EventArgs
        {
            public OutputEventArgs(string message)
            {
                Message = message;
            }
    
            public string Message { get; private set; }
        }
    
        public class LogEventArgs : EventArgs
        {
            public LogEventArgs(string message, string fileName)
            {
                Message = message;
                FileName = fileName;
            }
    
            public string Message { get; private set; }
            public string FileName { get; private set; }
        }

  3. #3
    Hasselhoff's Avatar IN A SPEEDO
    Reputation
    356
    Join Date
    Oct 2007
    Posts
    474
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I have no clue what you said, but I know it's impressive (atleast to me )

    This will really be able to help some people out, so +rep from me




  4. #4
    Clain's Avatar Banned
    Reputation
    179
    Join Date
    Jan 2008
    Posts
    1,396
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thank you! +Rep I actually have a good use for this =D
    Last edited by Clain; 10-01-2008 at 06:56 PM.

  5. #5
    Pale's Avatar Active Member
    Reputation
    63
    Join Date
    Jun 2008
    Posts
    39
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks Apoc, I owe you, + Rep

  6. #6
    bezuca's Avatar Active Member
    Reputation
    16
    Join Date
    Jun 2007
    Posts
    131
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thx for sharing the code.

  7. #7
    Scrubs's Avatar Contributor
    Reputation
    255
    Join Date
    Aug 2006
    Posts
    507
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I don't know this well, but i know it took effort. +rep



  8. #8
    edet123's Avatar Banned
    Reputation
    20
    Join Date
    Mar 2008
    Posts
    308
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    can someone explain what it does?

  9. #9
    Clain's Avatar Banned
    Reputation
    179
    Join Date
    Jan 2008
    Posts
    1,396
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It logs you on to the account management page and has some useful functions for requesting information from the site.

  10. #10
    cloudofmight's Avatar Member
    Reputation
    1
    Join Date
    Nov 2008
    Posts
    1
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hey, I need help. how do i write this program in C#. Like what do i do, some1 tell me plz

  11. #11
    makasante's Avatar Member CoreCoins Purchaser
    Reputation
    14
    Join Date
    Dec 2008
    Posts
    136
    Thanks G/R
    0/0
    Trade Feedback
    2 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    ................. well i read almost all of it, and well... i might aswell of been written in chineese lol
    but i can see a huge amount of knowlege and effort must of gone into this! (i just wish i could understand it)
    i would +rep... but i cant =( i need to go make a post bye :P
    Peace!
    Last edited by makasante; 12-23-2008 at 12:58 PM.

Similar Threads

  1. How can you get into the WoW Cataclysm EU beta?
    By Illidan_000 in forum Community Chat
    Replies: 2
    Last Post: 07-03-2010, 10:32 AM
  2. Wow crashes with MEF after i log into the game?
    By darkprince11 in forum WoW ME Questions and Requests
    Replies: 4
    Last Post: 01-10-2009, 04:34 PM
  3. How do I get into the giveaway forum?
    By Silias in forum WoW Scams Help
    Replies: 6
    Last Post: 08-22-2008, 09:17 PM
  4. How can I get into the trading forum?
    By IamAnoob in forum Community Chat
    Replies: 3
    Last Post: 08-05-2008, 10:05 AM
  5. How to sign up to the WoW forums?
    By giantman in forum World of Warcraft General
    Replies: 0
    Last Post: 03-03-2007, 06:11 AM
All times are GMT -5. The time now is 10:27 AM. Powered by vBulletin® Version 4.2.3
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2024 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search