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

I didn't get much response from beginners@ so I thought I'd ask this here. I thought I had it all figured out. Hash within hashes really made my code cleaner until I came up with this code: While looping, I was creating a key 'webloginpostdata' with value of anonymous hash as seen below;
$all_ap{$_}->{'webloginpostdata'} = { 'var:main' => 'menu', 'testwebcm' => 'webcm', 'login:command/username' => '', 'login:command/password' => '', 'var:connecting1' => '0' };
Now following the creation above, i'm creating another key 'webadminpostdata' which has a value of an anonymous hash again.
$all_ap{$_}->{'webadminpostdata'} = { 'var:main' => 'menu', 'var:style' => 'style5', 'settings/username' => $all_ap{$_}->{'webuser'}, 'settings/password' => $all_ap{$_}->{'webpass'}, 'settings/password_confirm' => $all_ap{$_}->{'we +bpass'}, 'settings/idle_timeout' => '30' };
Then there's two subroutines. The first one ("loginweb") is called. If successful, the next one ("changewebpass") is called
my $login_status = loginweb($all_ap{$_}->{'webloginurl'}, $all_ap{$_}- +>{'webloginpostdata'}); if ($login_status eq 'success'){ ## Call next subroutine my $setpassword = changewebpass($all_ap{$_}->{'webadminurl'}, $all_ap{ +$_}->{'webadminpostdata'}); if ($setpassword ne 'success'){ print "Can\'t change password\n"; }else{ print "New login created:\n\t username: $all_ap{$_}->{'webuser'} + \n\t password: $all_ap{$_}->{'webpass'}\n"; }
"loginweb" sub is really simple:
sub loginweb{ my $url = shift; my $postdata = shift; my $username; my $password; open PASSLIST, "appasswd.txt" or die $!; while (<PASSLIST>){ $username = (split / === /, $_)[0]; $password = (split / === /, $_)[1]; chomp ($username, $password); print "\nTrying username: \'$username\' password: \'$password\'"; $$postdata{'login:command/username'} = ($username eq '')?'':$usernam +e; $$postdata{'login:command/password'} = ($password eq '')?'':$passwor +d; my $res = $ua->request(POST $url, $postdata); if ($res->content =~ /Basic\s+Home\s+Menu/){ print " SUCCESS!!!\n"; return 'success'; }else{ next; } }
Finally, here's the "changewebpass"
sub changewebpass{ my $url = shift; my $postdata = shift; my $res = $ua->request(POST $url, $postdata); if ($res->is_success){ return 'success'; }else{ return 'failed'; } }
When I run my program, I get an error: "Need a field name at (eval 11) line 1" That's all. No mention of line number, or whatever. Perhaps that is because the error was not a syntax error but a perl module (HTTP::Request...etc.) error. Further investigation showed that after calling loginweb, my $all_ap($_}->{'webadminpostdata'} gets emptied. calling 'changewebaccess', nothing is being assigned to $postdata. That is why i'm getting that error. Any idea where to look into?? In my code before, I only had to declare the actual hashes:
my %webloginpostdata = (...); my %webadminpostdata = (...); </code ## Then pass their references to the sub routines: ie, <code> loginweb(\%webloginpostdata)
I didn't have any troubles doing so. Please enlighten me.

Replies are listed 'Best First'.
Re: passing hash reference to HTTP::Request::Common destroys my other hash
by kennethk (Abbot) on May 21, 2009 at 14:32 UTC
    Your error states that you have a problem on line 1 of your script file. The fact that it also mentions eval suggests that line 1 is a module and perhaps you are invoking it improperly. What does line 1 in the error-generating file look like?
      As i've mentioned, the call to the second subroutine (changewebpass) where a module HTTP::Request::Common is called again fails because the $postdata which is supposed to contain $all_ap{$_}->{'webadminpostdata'} gets emptied after calling the first sub (loginweb) where that module is called the first time. before calling the loginweb sub, I can easily print $all_ap{$_}->{'webadminpostdata'} or access any of its members/field. This is really weird. I wanted to debug it, but I haven't done any debugging before. I wanted to but I'm having a hard time reproducing the code in a smaller dummy program. Any more idea? Btw, i've checked that my syntax is correct, passing hash reference to that module's sub routine. I've also tried putting the creation of 'webadminpostdata' right after the call to login and the program runs fine.
Re: passing hash reference to HTTP::Request::Common destroys my other hash
by Anonymous Monk on May 21, 2009 at 13:12 UTC
    Sorry, but that code doesn't compile :)
      Oh, i thought i've described my problem thoroughly.. I wanted to reproduce the same by writing smaller program but the program interacts with a web application. Anyways, i'll try my best to write a smaller dummy program... thanks