MMOwned - World of Warcraft Exploits, Hacks, Bots and Guides  
Homepage Register FAQ Members Mark Forums Read Advertise Marketplace FPSowned


Go Back   MMOwned - World of Warcraft Exploits, Hacks, Bots and Guides > Programming > Programming section > C#
Reload this Page How to programatically log into the WoW site
C# Discussions about C#

Reply
 
LinkBack Thread Tools
How to programatically log into the WoW site
(#1)
Old
Apoc's Avatar
Apoc is Offline
c|_| My care cup is empty
Legendary User
Rep Power: 5
Reputation: 688
Apoc is a splendid one to beholdApoc is a splendid one to beholdApoc is a splendid one to beholdApoc is a splendid one to beholdApoc is a splendid one to beholdApoc is a splendid one to behold
 
Posts: 733
Join Date: Jan 2008
How to programatically log into the WoW site - 10-01-2008

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, 2008) 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.


VB skills is an oxymoron. - Cypher
Reply With Quote

Donate to remove ads.
(#2)
Old
Apoc's Avatar
Apoc is Offline
c|_| My care cup is empty
Legendary User
Rep Power: 5
Reputation: 688
Apoc is a splendid one to beholdApoc is a splendid one to beholdApoc is a splendid one to beholdApoc is a splendid one to beholdApoc is a splendid one to beholdApoc is a splendid one to behold
 
Posts: 733
Join Date: Jan 2008
10-01-2008

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; }
    }


VB skills is an oxymoron. - Cypher
Reply With Quote
(#3)
Old
Hasselhoff's Avatar
Hasselhoff is Offline
5-StarGeneral ina 6-Speed
Rep Power: 4
Reputation: 349
Hasselhoff is a jewel in the roughHasselhoff is a jewel in the roughHasselhoff is a jewel in the roughHasselhoff is a jewel in the rough
 
Posts: 394
Join Date: Oct 2007
Location: At the Pool
10-01-2008

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





Reply With Quote
(#4)
Old
Clain's Avatar
Clain is Offline
Contributor
Rep Power: 1
Reputation: 105
Clain will become famous soon enoughClain will become famous soon enough
 
Posts: 986
Join Date: Jan 2008
10-01-2008

Thank you! I actually have a good use for this =D


If you dislike the verbosity of VB, you must really hate typing English sentences.

Last edited by Clain; 10-01-2008 at 08:56 PM..
Reply With Quote
(#5)
Old
Pale's Avatar
Pale is Offline
Sergeant
Rep Power: 1
Reputation: 28
Pale is on a distinguished road
 
Posts: 37
Join Date: Jun 2008
10-03-2008

Thanks Apoc, I owe you, + Rep
Reply With Quote
(#6)
Old
bezuca's Avatar
bezuca is Offline
Master Sergeant
Rep Power: 2
Reputation: 11
bezuca is on a distinguished road
 
Posts: 108
Join Date: Jun 2007
10-04-2008

Thx for sharing the code.
Reply With Quote
(#7)
Old
Scrubs's Avatar
Scrubs is Offline
Contributor
Rep Power: 4
Reputation: 209
Scrubs has a spectacular aura aboutScrubs has a spectacular aura aboutScrubs has a spectacular aura about
 
Posts: 404
Join Date: Aug 2006
Location: New Hampshuh!
10-06-2008

I don't know this well, but i know it took effort. +rep




Reply With Quote
(#8)
Old
edet123 is Offline
Banned
Rep Power: 0
Reputation: 20
edet123 is on a distinguished road
 
Posts: 314
Join Date: Mar 2008
Location: Magtheridon EU
10-12-2008

can someone explain what it does?
Reply With Quote
(#9)
Old
Clain's Avatar
Clain is Offline
Contributor
Rep Power: 1
Reputation: 105
Clain will become famous soon enoughClain will become famous soon enough
 
Posts: 986
Join Date: Jan 2008
10-12-2008

It logs you on to the account management page and has some useful functions for requesting information from the site.


If you dislike the verbosity of VB, you must really hate typing English sentences.
Reply With Quote
(#10)
Old
cloudofmight is Offline
Site n00b.. (A leecher if I've been here for more than a month and can't earn 5 rep)
Rep Power: 0
Reputation: 1
cloudofmight is an unknown quantity at this point
 
Posts: 1
Join Date: Nov 2008
3 Weeks Ago

Hey, I need help. how do i write this program in C#. Like what do i do, some1 tell me plz
Reply With Quote
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are Off
Refbacks are On



Powered by vBulletin® Version 3.7.4
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Optimization by