5ubliminal@twitter

PHP cUrl Tutorial | OOP Class eHttpClient : 5ubliminal's TellinYa

<a href="http://www.tellinya.com/art2/39/">PHP cUrl Tutorial | OOP Class eHttpClient : 5ubliminal's TellinYa</a>
Must Reads: Web Scraping | Link Farming | Code Snippets | SEO Freeware » I'm back to work … sorting my shit now :)
Reveal More!
Nogenius warned me about a bug in this PHP cURL which I just crushed. GETs didn't work after POSTs. The fix is commented in the code. Search nogenius. Thanks!
I have updated this to my last functional version of the PHP cURL script. It has a few bugs fixed which I bet you never came accross: handling response headers.
Basic understanding of cUrl and PHP scripting

I expanded the previous sample of Basic cUrl and PHP Usage. I added the headers processing which can be useful to handle cookies. It is now easier to use but basic PHP knowledge is required. This code is also used in the scripts available here for getting MSN Search Results and Google Search Results.

The cUrl based eHttpClient class code

<?
//-----------------------------------------------------------------
//-- Copyright 5ubliminal 2008. (5ubliminal.com)
// http://www.tellinya.com/art2/39/
// You can do anything with it except selling it or claiming it.
// Copyright notice must remain intact and links are appreciated!
//-----------------------------------------------------------------
class eHttpClient{
    //--
    var $httpRecvHeaders    = "";
    var $authUserName    = "";
    var $authPassword    = "";
    var $cookieJar        = "";
    var $selfDestroyCookies    = true;
    var $curl;
    //--
    function eHttpClient(){ $this->__construct(); }
    function __construct() {
        $this->curl = curl_init();
        $this->cookieJar = tempnam('/tmp','cookie');
        //-- If you decide to use persistent cookies UNCOMMENT next line
        //$this->cookieJar = str_replace('\\','/',dirname(__FILE__).'/cookies.curl.txt');
        $this->_initCurl();
    }
    function __destruct() {
        curl_close($this->curl);
        //-- If you decide to use persistent cookies COMMENT next line
        unlink($this->cookieJar);
    }
    function getCookieJar(){ return $this->cookieJar; }
    //-- Add your own setting to internal cURL instance
    function configCurl($option, $value){
        return curl_setopt ($this->curl, $option, $value);
    }
    //-- Enable of disable redirects
    function setRedirects($follow=true){
        return $this->configCurl(CURLOPT_FOLLOWLOCATION, $follow);
    }
    function setTimeout($timeout=30){
        return $this->configCurl(CURLOPT_TIMEOUT, $timeout);
    }
    //-- Explicitly ask cURL you don't need the body
    function getBody($enable=1){
        return $this->configCurl(CURLOPT_NOBODY, !$enable);
    }
    //-- Set the refererURL ... referer spam :)
    function setReferer($referer=false){
        return $this->configCurl(CURLOPT_REFERER, $referer);
    }
    //-- Internal ... DO NOT USE
    function _initCurl(){
        $this->configCurl(CURLINFO_HEADER_OUT, 1);
        $this->configCurl(CURLOPT_SSL_VERIFYPEER, 0);
        $this->configCurl(CURLOPT_SSL_VERIFYHOST, 0);
        $this->configCurl(CURLOPT_RETURNTRANSFER, 1);
        $this->configCurl(CURLOPT_HEADER, 1);
        $this->configCurl(CURLOPT_MUTE, 0);
        $this->configCurl(CURLOPT_AUTOREFERER, 1);
        $this->configCurl(CURLOPT_FORBID_REUSE, 1);
        $this->configCurl(CURLOPT_FRESH_CONNECT, 1);
        $this->configCurl(CURLOPT_COOKIEFILE, $this->cookieJar);
        $this->configCurl(CURLOPT_COOKIEJAR, $this->cookieJar);
        $this->setUserAgent("ie");
        $this->setRedirects();
    }
    //-- Predefined values of your own
    function setUserAgent($ua){
        if($ua=="gg")
            $httpUserAgent = "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)";
        elseif($ua=="ms")
            $httpUserAgent = "msnbot/1.0 (+http://search.msn.com/msnbot.htm)";
        elseif($ua=="yh")
            $httpUserAgent = "Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)";
        elseif($ua=="ie")
            $httpUserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en)";
        elseif($ua=="ff")
            $httpUserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.8.1.8) Gecko/20071008 Firefox/2.0.0.8";
        else
            $httpUserAgent = $ua;
        return $this->configCurl(CURLOPT_USERAGENT, $httpUserAgent);
    }
    //-- Private ... Do Not Use!
    function _prepare($verb,$url,$headers,$sysheaders){
        //--
        if((isset($sysheaders) && !is_array($sysheaders)) || !isset($sysheaders)){
            $sysheaders=array();
        }
        if((isset($headers) && !is_array($headers)) || !isset($headers)){
            $headers=array();
        }
        //--
        if(is_array($headers) && count($headers)){
            foreach($headers as $key => $header){
                if(preg_match("/([^:]+):\s?(.+)?/i",$header,$pcs)){
                    $headers[$pcs[1]]=$pcs[2];
                    unset($headers[$key]);
                }
            }
            unset($headers["Content-Type"]);
            unset($headers["Content-Length"]);
        }
        //--
        $this->configCurl(CURLOPT_CUSTOMREQUEST, $verb);
        $this->configCurl(CURLOPT_URL, $url);
        if(strlen($this->authPassword) && strlen($this->authPassword)){
            $loginInfo = sprintf("%s:%s",$this->authUserName,$this->authPassword);
            $this->configCurl(CURLOPT_HTTPAUTH, CURLAUTH_BASIC); 
            $this->configCurl(CURLOPT_USERPWD, $loginInfo);
        }
        $sendHeaders = $headers;
        if(count($sysheaders)){
            $sendHeaders = array_merge($sendHeaders, $sysheaders);
        }
        $rawHeaders = array("Connection: close");
        if(count($sendHeaders)){
            foreach($sendHeaders as $key => $vals){
                if(!is_array($vals)){
                    array_push($rawHeaders,$key.": ".$vals);
                    continue;
                }
                $vals = array_unique($vals);
                foreach($vals as $val){
                    array_push($rawHeaders,$key.": ".$val);
                }
            }
        }
        $this->configCurl(CURLOPT_HTTPHEADER, $rawHeaders);
        $this->httpRecvHeaders = array();
    }
    //-- Get a URL. $getdata is an associated array that contains query string variables
    //-- used with http_build_query
    function get($url, $getdata, $headers){
        if((isset($getdata) && !is_array($getdata)) || !isset($getdata)){
            $getdata=array();
        }
        if(count($getdata) && ($getdata!=false)){
            $getdata=http_build_query($getdata);
            $url.=(!strchr($url,'?') ? "?" : "&").$getdata;
        }
        //-- nogenius pointed out a bug that was fixed here
        //-- I forgot to clear content-length after using a post and future gets failed
        $this->configCurl(CURLOPT_POSTFIELDS,null);
        $this->configCurl(CURLOPT_POSTFIELDSIZE,0);
        $this->_prepare("GET",$url,$headers);
        return $this->_fetchHtml();
    }
    //-- Get a URL. $getdata is an associated array that contains query string variables
    //-- used with http_build_query. We use HEAD verb here.
    function head($url, $getdata, $headers){
        if((isset($getdata) && !is_array($getdata)) || !isset($getdata)){
            $getdata=array();
        }
        if(count($getdata) && ($getdata!=false)){
            $getdata=http_build_query($getdata);
            $url.=(!strchr($url,'?') ? "?" : "&").$getdata;
        }
        $this->_prepare("HEAD",$url,$headers);
        return $this->_fetchHtml();
    }
    //-- Get a URL. $getdata is an associated array that contains query string variables
    //-- used with http_build_query. We use POST verb here.
    function post($url, $postdata, $headers, $type="application/x-www-form-urlencoded"){
        $sendHeaders = array();
        if(is_array($postdata)){
            $postdata = http_build_query($postdata);
            $contentType = "application/x-www-form-urlencoded";
        }else{
            $contentType = $type;
        }
        //--
        $this->configCurl(CURLOPT_POSTFIELDS, $postdata);
        $this->configCurl(CURLOPT_POSTFIELDSIZE, strlen($postdata));
        //--
        $sendHeaders["Content-Type"]    = $contentType;
        $sendHeaders["Content-Length"]    = strlen($postdata);
        //-- The Class is right not the user!
        $this->_prepare("POST",$url,$headers,$sendHeaders);
        return $this->_fetchHtml();
    }
    //-- Internal ... DO NOT USE!
    function _parseHeaders($headers){
        if(is_string($headers)) $headers = preg_split("/[\r\n]+/",$headers);
        $hdret        = array("Raw" => array());
        $httpinf    = $headers[0];
        $hdret['HTTP'] = $httpinf;
        array_splice($headers,0,1);
        foreach($headers as $hdr){
            $hdr=trim($hdr);
            if(!strlen($hdr)) continue;
            if(!preg_match("/([^:]+):(.*)/",$hdr,$pcs)){
                array_push($hdret['Raw'],$hdr);
                continue;
            }
            $key = trim($pcs[1]);
            $val = trim($pcs[2]);
            if(isset($hdret[$key])){
                if(!is_array($hdret[$key]))
                    $hdret[$key]=array($hdret[$key]);
                array_push($hdret[$key],$val);
            }else{
                $hdret[$key]=$val;
            }
        }
        if(!count($hdret['Raw'])) unset($hdret['Raw']);
        return $hdret;
    }
    //-- Internal ... DO NOT USE!
    function _fetchHtml(){
        $html    = curl_exec ($this->curl);
        $inf        = $this->getInfo();
        $reqsize    = $this->getInfo(CURLINFO_HEADER_SIZE);
        $req        = substr($html,0,$reqsize);
        $req        = str_replace("\r","",$req);
        $lines    = explode("\n",$req);
        $pos        = 0;
        $reqbkt    = array();
        $this->httpRecvHeaders = array();
        while(count($lines)){
            $line = $lines[0];
            array_splice($lines,0,1);
            if(strlen($line)==0){
                if(!count($reqbkt)) continue;
                array_push($this->httpRecvHeaders,$reqbkt);
                $reqbkt=array();
                continue;
            }
            if(!count($reqbkt)){
                if(preg_match("/^[^\s]+\s([0-9]+)\s.*$/i",$line,$pcs)){
                    $reqbkt['HTTP']=$pcs[1];
                    continue;
                }
            }
            if(!preg_match("/^([^\s:]+):\s?(.*)$/i",$line,$pcs)) continue;
            $reqbkt[trim($pcs[1])]=trim($pcs[2]);
        }
        return substr($html,$reqsize);
    }
    //-- Get the CURL info
    function getInfo($cfg){
        if(!isset($cfg)) return curl_getinfo($this->curl);
        return curl_getinfo($this->curl,$cfg);
    }
    //-- Get Received headers. In case of redirects you will find more then one.
    function getHeaders(){
        return $this->httpRecvHeaders;
    }
    //-- Get last header. In case of redirects you will find last one.
    function getHeader(){
        $hdr=array_pop($this->httpRecvHeaders);
        array_push($this->httpRecvHeaders,$hdr);
        return $hdr;
    }
    //-- Get the exact sent headers ... good for debugging
    function getSentHeaders(){
        $sentHeaders = curl_getinfo($this->curl, CURLINFO_HEADER_OUT);
        return $this->_parseHeaders($sentHeaders);
    }
    //-- HTTP AUTH data for ... cPanel or WordTracker Login :)
    function setAuth($user,$pass){
        if(func_num_args()==0){
            return $this->resetAuth();
        }
        if(!strlen($user) || !strlen($pass)) return;
        $this->authUserName = $user;
        $this->authPassword = $pass;
    }
    //-- Clear HTTP Auth Data
    function resetAuth(){
        $this->authUserName = "";
        $this->authPassword = "";
    }
    //-- For more info comment form is below. If you like it ... link back :)
};
//-----------------------------------------------------------------
?>

Get usage sample - How to download a page

<?
/* Download google.com pretending to be refered by yahoo.com */
$hc        = new eHttpClient();
$hc->setReferer("http://www.yahoo.com/");
$html        $hc->get("http://www.google.com/");
$headers    $hc->getHeaders();
$header        $hc->getHeader();
$inf        $hc->getInfo();
?>

POST usage sample - How to post a trackback

<?
/* Sample function of using the class to POST a trackback */
function postTrackBack($target,$blog_name,$blog_url,$subject,$message){
    
$hc=new eHttpClient();
    
$pvars = array(
        
"title" => $subject,
        
"url" => $blog_url,
        
"excerpt" => $message,
        
"blog_name" => $blog_name
    
);
    
$html=$hc->post($target,$pvars,0);
    return 
$html;
}
?>

For more info replies are welcome

For further informations do not hesitate to post comments.

87 Comments Posted By Readers :

Add your comment
#1 jason from United States
Posted on Sunday, 11 November, 2007
Hey, I get an error trying to use your cUrl class. I am trying to use it with your pingback script and article scraper and I get an error at line 11 which is

"Fatal error: Call to undefined function curl_init() in C:xampphtdocsarticleinsert.php on line 11"

I am using PHP5 and PHP4 and have curl enabled on both, but I keep getting this error on your curl class.

Any suggestions?
#2 5ubliminal web
Posted on Sunday, 11 November, 2007
I have no other idea that the fact that you don't have curl enabled in php.ini or any potential dependencies installed.
Make sure php_curl.dll is in ext folder and php.ini is configured properly to point to ext folder and have curl enabled.
#3 Jason from United States
Posted on Sunday, 11 November, 2007
It was it, I had enabled it and saved the ini file, then restarted Apache. It didnt work and then I went back in only to find my change didnt save to enable cUrl.

Once enabled it was fine.

Thanks. Works good!
#4 Alfred from Portugal
Posted on Thursday, 22 November, 2007
Hello,

This seems to be useless. I have tested on StatsCounter and when you say:
/* Download google.com pretending to be refered by yahoo.com */ I can't see yahoo referer, but the real page! So spoof is not working.

Thanks for the hard work,
Alfred


Also, you have a bug on get("http://www.google.com/"); as get($url,$qs,$hdr) needs 3 vars.
#5 5ubliminal web
Posted on Thursday, 22 November, 2007
My friend ... sience when does a cUrl + PHP downloader access JavaScript ?:) StatCounter uses JavaScript. Have you ever seen Googlebot visits in StatsCounter? Only browsers load JavaScripts. Never cUrl + PHP or other methods of page retrieval.
I've been using this class for 2 years now and works very well. To see if it did visit your site you need to use raw access logs from your webserver or take my word for it. Or just create a PHP page to output $_SERVER['HTTP_REFERER'] and load that page using my class see what comes out.

Use this : error_reporting(E_ALL^(E_WARNING|E_NOTICE)); before your PHP code and learn from PHP manual about it. Functions in PHP can take variable parameters count (as advanced coders do) but in basic beginner state of error reporting config (including warnings and notices) it warns you. But those are not errors just warning ... read them well and disable them or your coding career will end abruptly.

Get your act together before making negative statements on others work.
PS: Let me know how right I was when it's all done.
#6 Alfred from Portugal
Posted on Thursday, 22 November, 2007
Hello again my friend. I am sorry, English is not my native language and thus it may seem my mood is diferent than what it should. I agree the word "useless" was to far off. Sorry for that.

You're class is great and provides an easy and fast use of CURL.

You're right, it's not errors, it's warnings. You're wrong that CURL does not access Javascript, it does. I have tested it and it prints the results on Statscounter and also it executes other javascript fuctions. (IMHO)

I have now went trying to feed the CURLOPT_HTTPHEADER array manualy with HOST and REFERER but it is also useless. I've learned most current weblog scripts don't mind about what you feed the headers and try to get their own data executing javascript or resolving the IP.

I gave up on CURL and went on to fsockopen direct sock requests on port 80. Now I get the pages in stealth mode but this time the javascript does not executes.

Regards and thanks,
Alfred
#7 Alfred from Portugal
Posted on Thursday, 22 November, 2007
Hello again my friend.

Too good I posted IMHO on the last post! You're right again!!! CURL DOES NOT access javascript, I was doing a classical mistake. I was echoing the downloaded page on a browser and thus the javascript was getting executed!

I am very sorry, please accept my sincere appologies.

Regards and thanks,
Alfred
#8 5ubliminal web
Posted on Thursday, 22 November, 2007
No problem. We were all beginners once ... Just don't be too drastic in affirmations before you verify. Just say: you might have an error ... works better and I always reply and help.

cUrl is better then fsockopen because it handles https and ftp which fsockopen does not!
Instead of rewriting the protocol, which I also did long time ago, use cUrl as it does the magic for you much easier!

I've been coding for the past 9 years. I don't make mistakes too often ;) !
PS: Your English is just fine. I'm not a native EN speaker either.
#9 Jarrod from United States
Posted on Friday, 21 December, 2007
When running the above code I get a whole bunch of the following Warnings for the _init function:

Warning: curl_setopt(): supplied argument is not a valid cURL handle resource in ..

Any ideas as to what might be causing this? I'm using PHP 4.4.7 for what it's worth.
#10 5ubliminal web
Posted on Saturday, 22 December, 2007
Yes. Your PHP, older than 5, does not know how to use __construct function as class initializer.
Add this new function to the class and it will work:

function eHttpClient() { $this->__construct(); }

This function is the default constructor for PHP<5 but I totally forgot to add it. I'll add it to the code when I return but now I'm on vacation.

If you got other problems let me know and:
Merry Christmas and A Happy New Year.
#11 Jason B from United States
Posted on Saturday, 16 February, 2008
Wow 5ubliminal, you got so much going on here that it made my brain hurt reading it all, can you give some example usage? There is so much going on, I would almost stick to reg cUrl calls unless you can explain some of the workings of your script and what you have done.

thanks.
#12 5ubliminal web
Posted on Saturday, 16 February, 2008
Yeah … it's made to be used … not to be understood :)
The demo uses are at the bottom of the post but I'm away for the next 4 days.
I'll comment this code entirely and then I'll show some more detailed ways to use it as soon as I return to 'office'.

PS: But it is so easy :)
#13 Jason B from United States
Posted on Saturday, 16 February, 2008
Thanks, I didnt see the examples before, maybe something with my browser...

Keep up the good work, your about the only blackhat blog I read anymore as no one else takes the time to really update or explain things on the level you do.

Cant wait for more details on this, I have a rather large PHP lib I am trying to build up and keep track off and any thing you can offer more on this script would be great!

Have a nice vacation dude, I'm about to go on vacation in a few weeks myself to somewhere warm and sunny ( beach )
#14 5ubliminal web
Posted on Saturday, 16 February, 2008
I'll have more scripts up by the end of this month.
I also have a 'decent' php lib with no external intrusions I'll slowly share here…

Have fun on vacation and thanks :)
#15 r0n from United States
Posted on Thursday, 28 February, 2008
love the class. is there a way for it to display images as well?
#16 5ubliminal web
Posted on Thursday, 28 February, 2008
You kind'of lost me … what do you mean by 'display images'?
#17 r0n from United States
Posted on Thursday, 28 February, 2008
I'm using your class to spoof referrer information so that all users clicking on a link to a particular host will appear to come from the same IP address. When the page comes back to the client browser none of the images are displayed. Is there a way to get your class (or curl) to fetch the images as well?
#18 5ubliminal web
Posted on Thursday, 28 February, 2008
You need to find all images in output HTML and fetch them too or … the easy way:
Rewrite their addresses to the original server.
#19 r0n from United States
Posted on Thursday, 28 February, 2008
Went with the Rewrite. Thanks!
#20 stwinnie from Spain web
Posted on Thursday, 13 March, 2008
Hey man, this class is gorgeous!
I've just found ur blog through google doing some research on XMLRPC methods
And I read all the posts from the beginning. Every post is very usefull, thanks for ur job.

Subscribed to RSS and waiting for new posts.
#21 5ubliminal web
Posted on Thursday, 13 March, 2008
@stwinnie: You're welcome and Thanks :)
#22 elusid from United States web
Posted on Thursday, 20 March, 2008
Hello, I am testing out your curl class here and trying the first example I get this error...

Warning: Missing argument 2 for eHttpClient::get(), called in C:xampphtdocsping est.php on line 6 and defined in C:xampphtdocspingcurl.class.php on line 123

Warning: Missing argument 3 for eHttpClient::get(), called in C:xampphtdocsping est.php on line 6 and defined in C:xampphtdocspingcurl.class.php on line 123

Warning: Missing argument 4 for eHttpClient::_prepare(), called in C:xampphtdocspingcurl.class.php on line 131 and defined in C:xampphtdocspingcurl.class.php on line 74

Warning: Missing argument 1 for eHttpClient::getInfo(), called in C:xampphtdocspingcurl.class.php on line 197 and defined in C:xampphtdocspingcurl.class.php on line 226

Warning: Missing argument 1 for eHttpClient::getInfo(), called in C:xampphtdocsping est.php on line 9 and defined in C:xampphtdocspingcurl.class.php on line 226

im still using php4 could that be the problem?
#23 5ubliminal web
Posted on Thursday, 20 March, 2008
It might be the problem but please paste your code here so I can see where it fails.
Just the section where you actually declare and use the class and explain the parameters you feed it.

Regards.
#24 elusid from United States web
Posted on Thursday, 20 March, 2008
I am using the same exact code that you posted in the first example usage:



the only change I made was to include the curl class....
#25 5ubliminal web
Posted on Thursday, 20 March, 2008
I use PHP to its fullest so, sometimes, I use functions with variable parameters count or with dynamic parameters.
By adding: error_reporting(E_ALL^(E_NOTICE|E_WARNING)); I get rid of Notices and Warnings which can help sometimes, when you are a beginner and need PHP to take care of you but don't mix with the advanced coders.
PHP allows a lot more to be done, nasty things, which it permits but warns you about. Like this:

function no_param_function(){
$params = func_get_args();
// Params is an array of variable length based on parameters provided.
}
and call it with parameters:

no_param_function($par1);
or
no_param_function($par1,$par2);

PHP will issue warnings but this is valid PHP coding. So dump WARNINGS and NOTICES using error_reporting(E_ALL^(E_NOTICE|E_WARNING)); and keep just errors.

Let me know if it works.
#26 elusid from United States web
Posted on Thursday, 20 March, 2008
Thanks for that error reporting tip :) I used it and now just get a blank page.... Are some of the functions in the eHttpClient class php5 specific? I am using php4 in a xampp enviroment.
#27 5ubliminal web
Posted on Thursday, 20 March, 2008
Oh my God! I hope you are aware my sample function does not output anything.

Add these right before the end:

print_r($headers); echo($html);
#28 elusid from United States web
Posted on Thursday, 20 March, 2008
Oh my god! hehe your right.... doh! thats what I get for messing around with new code way past my bedtime. rest assured it works (as you already know) removing all that error reporting did the trick. Also I want to add you are amazing help even to help trouble shoot code that you are giving away is awesome man. I'm learning a shit ton from your blog and hopefully soon I will have something to contribute. cheers!
#29 5ubliminal web
Posted on Thursday, 20 March, 2008
Yeah … I'm silly that way (about the trouble shooting) but why would I share this if others can't use it? This is why I'll walk through anyone in need.
Glad to have helped.

Cheers.
#30 Alex from United States
Posted on Thursday, 20 March, 2008
Thank you for your class. I included 'print_r($headers); echo($html);' in your original example and I am facing 2 problems: the text on the top of the screen loks a bit messy and I cannot see the Google image. (see my url above). About the image, I suspect that my browser has some special settings that don't allow me to see the image (Do you know which ones?).
Thank you in advance.
#31 5ubliminal web
Posted on Thursday, 20 March, 2008
Dude … the image has a relative URL and will never load. You get the HTML but you don't have the image. The URLs are relative to where you get it from.
I gave you how to get the page, fixing images (even if I can't imagine why you require it) is your own task.

The top text is messy bacause it has no HTML formatting.
#32 Alex from United States
Posted on Thursday, 20 March, 2008
Thanks. I appreciate your fast response.
#33 Jarod from United States
Posted on Thursday, 27 March, 2008
A quick question: Do you have examples on how to do remote logins with CURL? I know it's possible, I had a script going awhile back (2 - 3 months) but for the life of me can't remember where I put it. I need to remotely log in to a website I use for work, prase a bit of information and display it. The website I must login to uses .NET so all the forms have viewstate variables. I don't like it as I could not get some of the forms to submit properly when I had CURL working before. Thanks for the hard work you've put in to create this.

Jarod
#34 5ubliminal web
Posted on Thursday, 27 March, 2008
Look at IEHTTPHeaders, use it in IE to follow the login sequence and see the variables sent. Parse pages for those variables and fill user and password yourself. Keep sending requests following the login sequence and make sure you enable the cookie jar. It's not easy but with the right amount of work it can be done.

Regards.