epoptai has asked for the wisdom of the Perl Monks concerning the following question:

When activated by a form this sub needs to login to perlmonks, post a cb message, and call another sub in itself to redisplay the form. I've found several good nodes about this and tried their methods without success. I'm so bad at this even the perlmonks module didn't help. I use scripts that do this every day but couldn't steal their mojo! My latest failure involves the method from this node. The following code does appear to contact perlmonks but doesn't post messages.
use LWP::UserAgent; use HTTP::Cookies; use HTTP::Request::Common; use CGI qw(:standard); sub sendit{ my$message = shift; my$ua = LWP::UserAgent->new; my$cookies = HTTP::Cookies->new; my$perlmonks = 'http://perlmonks.org/index.pl'; my$req = POST ($perlmonks, [ op => 'login', user => $username, passwd => $password, node_id => '16046' ]); my$res = $ua->request($req); $cookies->extract_cookies($res); $req = POST ($perlmonks, [ op => 'message', message => $message, node_id => '16046', ]); $cookies->add_cookie_header($req); $res = $ua->request($req); print header; &talk(); # reload form }

Replies are listed 'Best First'.
Re: Login, post, reload.
by chromatic (Archbishop) on Feb 25, 2001 at 00:38 UTC
    HTTP::Cookies doesn't like the domain portion of the PerlMonks cookie. See the comment on the code in the set_cookie() method:
    # there must always be at least 2 dots in a domain return $self if ($domain =~ tr/././) < 2 && $domain !~ /\.local$/;

    You can either use 'www.perlmonks.org' or 'perlmonks.org.' to get around this. Otherwise, you could subclass HTTP::Cookies, but I'm not really interested in that.

      Thank you chromatic! The code in question works perfectly when the $perlmonks variable is changed to "www.perlmonks.org". I guess the upside to this debacle is learning a few different techniques for posting to cookie-login sites, and understanding why many cookies are set in the form: .domain.net

      Joy!

      Update: Here's the sub using merlyn's instructions for the cookie_jar. When using this code for perlmonks note the odd node_id=>'16046' parameter in the requests. This is done to ensure a small response. In this example it's an xml node. If omitted the monastery gates is returned making the operation much heavier than it needs to be.
      sub sendit{ my$message = shift; my$ua = LWP::UserAgent->new; $ua->cookie_jar(HTTP::Cookies->new); my$req = POST ($pmurl, [ op=>'login',user=>$username,passwd=>$password,node_id=>'16046']); my$res = $ua->request($req); $req = POST ($pmurl, [ op=>'message',message=>$message,node_id=>'16046']); $res = $ua->request($req); print header; &talk(); }

      Update2: After experimenting i found that the saved cookie file will be empty when merely using:

      $ua->cookie_jar(HTTP::Cookies->new(file => ".cookies", autosave => 1)) +;
      unless the cookie_jar is told to save cookies without an expiration date by adding the ignore_discard parameter:
      $ua->cookie_jar(HTTP::Cookies->new(file => ".cookies", autosave => 1, +ignore_discard => 1));
      or, better yet, by not using ignore_discard, but instead adding an 'expires' parameter to the login request:
      my$req = POST ($pmurl, [ op=>'login',user=>$username,passwd=>$password,expires=>'+10y',node_id= +>'16046']);
      Thanks merlyn.
Re: Login, post, reload.
by merlyn (Sage) on Mar 04, 2001 at 01:16 UTC
    You're working too hard on those cookies. Just tell your useragent that you're interested in cookies:
    $ua->cookie_jar(HTTP::Cookies->new(file => ".cookies", autosave => 1)) +;
    And now all requests will automatically be cookiefied, and the responses will be cookie-extracted, and the cookies will be saved between sessions, just like a browser!

    -- Randal L. Schwartz, Perl hacker