A lot of webservers use client-side cookies for logging in. Here is some sample code of how to log in to an OpenACS 3.x server:
Login
package require http set login [::http::formatQuery email [email protected] password fooFoo!] set tok [::http::geturl http://mysite.net/register/user-login.tcl -query $login] upvar \#0 $tok state set cookies [list] foreach {name value} $state(meta) { if { $name eq "Set-Cookie" } { lappend cookies [lindex [split $value {;}] 0] } } ::http::cleanup $tok
Using it
set tok2 [::http::geturl http://mysite.net/some/restricted_page.html -headers [list Cookie [join $cookies {;}]]] ... your code ::http::cleanup $tok2
This method will work for a lot of websites that ask for a username and password. For each site, you'll probably want to read the page source of the login page of that site to see where it POSTs to and what fields you need to supply. And you may need to play with your User-Agent headers too. A lot of sites actually restrict which browsers can login...
male 12.05.2004:
What is to do be done, if a website has already stored its cookie with login information and if I want to reuse the cookie to get a page via the http page?
I read the cookie file and to pass its data like mentioned above with the "-headers [list Cookie ..." option and I changed the useragent string to look like the Internet Explorer, but nothing worked.
Any hint or suggestion?
KPV For starters try using sockspy to see what Internet Explorer is sending and how it differs from what you're sending.
male 12.05.2004:
I used sockspy and found out, what part of the already existing data inside the cookies file had to be used. Now it works fine! Thanks!
Kiko 12.01.2005:
Here's an example on how to login to some website store cookies in a global var for later use and sending defined headers...
Code...
set website http://website.com set timeout 10000;#maximum of milliseconds to wait for the page set agent "Mozilla/4.0 (compatible\; MSIE 6.0\; Windows NT 5.0)" set headers(Accept) "text/html\;q=0.9,text/plain\;q=0.8,image/png,*/*" set headers(Accept-Language) "en-us,en\;q=0.5" set headers(Accept-Charset) "ISO-8859-1,utf-8\;q=0.7,*\;q=0.7" set headers(Referer) http://somesite.com #return the headers.. [headers] proc headers {} { foreach header [array names ::headers] { lappend head $header lappend head $::headers($header) } return $head } #parses the cookies out of $state(meta) to a global COOKIES var proc parse:cookies {meta} { foreach {name value} $meta { if {[string equal -nocase set-cookie $name]} { set x "[split [lindex [split $value {;}] 0] =]" set ::COOKIES([lindex $x 0]) [lindex $x 1] } } if {[info exists ::COOKIES]} { set f [open cookies w+] #puts the cookies in a file with the current unixtime for later use #u can instead try to improve this function and use the unixtime of the expire date from the cookie foreach cookie [array names ::COOKIES] { puts $f "$cookie $::COOKIES($cookie) [clock seconds]" } close $f } } #returns a "ready to use" cookie line proc show:cookie:line {} { if {[info exists ::COOKIES]} { foreach cookie [array names ::COOKIES] {lappend cookies $cookie=$::COOKIES($cookie)} return [list Cookie [join $cookies {; }]] } } #returns a "ready to use" headers line putting together both cookies & headers (-headers) proc heads {} {return "[headers] [show:cookie:line]"} Using the functions above then u would only need to login using: ::http::config -useragent $agent set xx [http::geturl $website -query $::string -validate 1 -type $type -headers [heads] -timeout $timeout] set x [split [http::data $xx] \n];upvar #0 $xx state parse:cookies $state(meta) set f [open $pagina.html w+];puts $f [join $::PAGE \n];close $f;#stores the contents of the site in an html file $::string is the string u'll send to the server... imagine u already parsed out a form from an html page and the fiels are: 2i3ut5iu2y/o3ui4g52io34g5 2i3ut5iu2y (being a random field name for "username") o3ui4g52io34g5 (being a random field name for "password") and action=login the field to submit with the form... set string [::http::formatQuery action login 2i3ut5iu2y myuser o3ui4g52io34g5 mypass] $type is a header that some websites need on POST so just in case u can try using set type application/x-www-form-urlencoded in case u wanna reuse the cookies.... if {[file exists cookies]} { set f [open cookies r];set x [split [read $f] \n];close $f foreach cookie $x { set value [lindex $cookie 1];set time [lindex $cookie 2];set cookie [lindex $cookie 0] #restore the cookie if it's younger than 270 seconds if {[string equal -nocase PHPSESSID $cookie]&&[expr [clock seconds] - $time]<"270"} { set ::COOKIES($cookie) $value } } }
This page also serves as a reference for all pages that deal with Cookie management by CGI processing scripts.
Also see Cookies: give and take
Wub utility for cookie generation and parsing
Latest version may be sourced here [L1 ] and perused here [L2 ]
CMcC is the current custodian, but help and improvement is welcome.
DKF: I'm working on an update for http to support cookies. Work in progress…