in reply to How to login to a form which has Javascript OnSubmit method usirng Perl

I don't know if there is a sufficient javascript interpreter in Perl, but you could look at the javascript function validate_form, and mimic its behaviour in Perl.

It doesn't just validate the form as the name suggests, but encodes the password in base64, copies that to a hidden field of the form, removes the plain text entry of the password (I don't understand the paranoia - they are using ssl after all) and does some md5 magic.

  • Comment on Re: How to login to a form which has Javascript OnSubmit method usirng Perl
  • Download Code

Replies are listed 'Best First'.
Re^2: How to login to a form which has Javascript OnSubmit method usirng Perl
by ragas (Initiate) on Nov 04, 2007 at 15:52 UTC
    Thank you for the suggestion. I also considered that idea of mimicing the validate_form's behavior in my code. But, even then, hitting the OnSubmit Javascript method in the form is unavoidable before POSTing. Is there any way to bypass this OnSubmit at the client side and send the values directly to the server?
      Of course you can POST any data you like to a HTTP server, with LWP::UserAgent for example, and I'm quite sure WWW::Mechanize allows that as well. Your perl script doesn't hit any button, it just sends data to the server.

      All a server does is send data to a user agent - and that data has the form of HTML with embedded javascript - it doesn' t have any kind of control over how the user agent interprets the data.

      So all your script has to do is to send the same data as a web browser would do.

      If you don't want a general solution, but only one that works for you, there might be shortcut. If you look at that function again:

      function validate_form(form) { if ( form.user_id.value == "" || form.password.value == "" ) { alert( "Enter a username and password." ); return false; } //short-cut if challenge/response is disabled. if ( !_useChallenge ) { form.encoded_pw.value = base64encode( form.password.value ); form.encoded_pw_unicode.value = b64_unicode( form.password.value ) +; form.password.value = ""; return true; } ... }

      There seems to be a chance that the system accepts login without challenge/response, so all you have to do is to login once manually, and record the the values that are stored in form.encoded_pw_unicode and in the username field, and then uses this data each time you want to log in.

        Thank you very much to all the PerlMonks. I was finally able to figure out how to work around the Javascript problem. As moritz suggested, I recorded the values of encoded_pw and and encoded_pw_unicode (which were being set by Javascript) by logging in once using the browser. I used 'Tamper Data' add-on of Mozilla Firefox to get those values. It is a wonderful tool. Then, I used those values in my program. Here is my final working program:
        #!/usr/bin/perl -w use strict; use LWP::UserAgent; use WWW::Mechanize; use HTTP::Cookies; use HTTP::Request::Common qw(POST); #use LWP::Debug qw(+); my $user_name = '...'; my $encoded_pw = urldecode('...'); my $encoded_pw_unicode = urldecode('...'); my $base_url = 'https://courses.northwestern.edu/webapps/login/'; my $target_url = '...'; my $agent = WWW::Mechanize->new( autocheck => 1 ); $agent->cookie_jar(HTTP::Cookies->new); #Get the page once to get the initial cookies and store them #in the cookie jar $agent->get($base_url); die $agent->response->status_line unless $agent->success; my $req = POST $base_url, [ user_id => $user_name, encoded_pw => $encoded_pw, encoded_pw_unicode => $encoded_pw_unicode]; #This POSTs the form and also gets the new cookies and #stores them in the cookie jar $agent->request($req); die $agent->response->status_line unless $agent->success; #Get the desired page my $res = $agent->get($target_url); die $agent->response->status_line unless $agent->success; print $agent->content(); ...