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

I seem to get this error and cant figure out why, i think its something to do with the header. Its also not assigning a cookie/session, so I know im doing something wrong but cant figure it out. Error: Name "main::cookie" used only once.
#!/usr/bin/perl -w use CGI; use HTML::Template; use CGI::Session; use lib ('/home/scott/intranet/cgi/mods'); use Digest::SHA2; use DBI; use DBD::mysql; CGI::Session->name("test"); my $query = new CGI; my $sid = $query->cookie( 'test' ) || undef; my $session = CGI::Session->new("driver:File", $sid, {Directory=>' +/tmp'}); $query->param( 'session' => $session); if (!$sid or $sid ne $session->id ) { my $cookie = $query->cookie( -name => 'test', -value => $session->id, #-expires => '' makes it so on close session expires. ) } init($session, $query); sub init { my ($session, $cgi) = @_; # receive two args if ( $session->param("~logged-in") ) { return 1; # if logged in, don't bother going further } my $lg_name = $cgi->param("lg_nick") or return; my $lg_psswd=$cgi->param("lg_pass") or return; # if we came this far, user did submit the login form # so let's try to load his/her profile if name/psswds match if ( my $profile = login($lg_name, $lg_psswd) ) { $session->param("~profile", $profile); $session->param("~logged-in", 1); $template->param(PROFILE => 1); $session->clear(["~login-trials"]); return 1; } # if we came this far, the login/psswds do not match # the entries in the database my $trials = $session->param("~login-trials") || 0; return $session->param("~login-trials", ++$trials); } my $template = HTML::Template->new(filename => 'index.tmpl', path => '/home/scott/intranet/cgi/ +intranet/', associate => $query); sub getpassword { # MySQL CONFIG VARIABLES my($username) = @_; my $host = "localhost"; my $database = "write"; my $user = "userid"; my $pw = "dbpass"; my $dsn = "dbi:mysql:$database:localhost:3306"; my $dbstore = DBI->connect($dsn, $user, $pw) or die "Unable to con +nect: $DBI::errstr\n"; my $prepquery = $dbstore->prepare("SELECT * FROM userlogin WHERE U +SERNAME='$username'") or die "Unable to connect: $DBI::errstr\n"; $prepquery->execute(); my $timestampUpdate = $dbstore->prepare("UPDATE write.userlogin SE +T userlogin.TIMESTAMP = NOW( ) WHERE userlogin.USERNAME = '$username' +" ) or die "Unable to connect: $DBI::errstr\n"; $timestampUpdate->execute(); my $ref = $prepquery->fetchrow_hashref(); my $password = $ref->{'PASSWORD'}; $prepquery->finish(); $timestampUpdate->finish(); $dbstore->disconnect(); return $password; } sub login{ my($nick, $pass) = @_; my($password) = getpassword($nick); my $encryptobj = new Digest::SHA2 512; $encryptobj->add($pass); my $digest = $encryptobj->hexdigest(); if($digest eq $password){ # replace this check above with something real ie lookup f +rom a database return 0; } else { return 1; } } $template->param('TEST', $query->param('lg_nick')); $template->param(MYURL => 'http://192.168.1.9/cgi-bin'); print $query->header( -cookie=>$cookie ), $template->output;

Replies are listed 'Best First'.
Re: CGI::Session error saying main::cookie used only once?
by shmem (Chancellor) on Jun 28, 2009 at 06:53 UTC

    Always use strict. Always use strict! With -w you get a warning only.

    You are using two variables $cookie, one here

    if ( !$sid or $sid ne $session->id ) { my $cookie = $query->cookie( -name => 'test', -value => $session->id, #-expires => '' makes it so on close session expires. ); }

    and the other here:

    print $query->header( -cookie => $cookie ), $template->output;

    At the first place, the my variable $cookie is confined to the if () { ... } block, so you are not re-using that at the second place, where $cookie is a package global. See Lexical scoping like a fox.

      Thanks for the help, I fixed those errors, pretty dumb of me to miss. The script is now error free, but for some reason it is still not assigning a cookie on my browser, and it seems to think the user is logged in. It is creating sessions on in the tmp folder though. Any ideas on what I am doing wrong?
      #!/usr/bin/perl -w use CGI; use HTML::Template; use CGI::Session; use lib ('/home/scott/intranet/cgi/mods'); use Digest::SHA2; use DBI; use DBD::mysql; my $query = new CGI; my $sid = $query->cookie( 'CGISESSID' ) || undef; my $session = new CGI::Session("driver:File", $sid, {Directory=>'/tmp' +}); if (!$sid or $sid ne $session->id ) { my $cookie = $query->cookie( -name => 'CGISESSID', -value => $session->id ); } my $template = HTML::Template->new(filename => 'index.tmpl', path => '/home/scott/intranet/cgi/intranet/', associate => $query); my $lg_name = $query->param("lg_nick"); my $lg_psswd = $query->param("lg_pass"); init($session, $lg_name, $lg_psswd, $template); if($session->param("~logged-in") eq 1) { $template->param(TEST => "YES"); } else { $template->param(TEST => "no"); } sub init { my ($session, $lg_name, $lg_psswd, $template) = @_; # receive two +args if ( $session->param("~logged-in") ) { return 1; # if logged in, don't bother going further } # if we came this far, user did submit the login form # so let's try to load his/her profile if name/psswds match if ( my $profile = login($lg_name, $lg_psswd) ) { $session->param("~profile", $profile); $session->param("~logged-in", 1); $session->clear(["~login-trials"]); return 1; } # if we came this far, the login/psswds do not match # the entries in the database my $trials = $session->param("~login-trials") || 0; return $session->param("~login-trials", ++$trials); } sub getpassword { # MySQL CONFIG VARIABLES my($username) = @_; my $host = "localhost"; my $database = "write"; my $user = "dbuser"; my $pw = "dbpass"; my $dsn = "dbi:mysql:$database:localhost:3306"; my $dbstore = DBI->connect($dsn, $user, $pw) or die "Unable to con +nect: $DBI::errstr\n"; my $prepquery = $dbstore->prepare("SELECT * FROM userlogin WHERE U +SERNAME='$username'") or die "Unable to connect: $DBI::errstr\n"; $prepquery->execute(); my $timestampUpdate = $dbstore->prepare("UPDATE write.userlogin SE +T userlogin.TIMESTAMP = NOW( ) WHERE userlogin.USERNAME = '$username' +" ) or die "Unable to connect: $DBI::errstr\n"; $timestampUpdate->execute(); my $ref = $prepquery->fetchrow_hashref(); my $password = $ref->{'PASSWORD'}; $prepquery->finish(); $timestampUpdate->finish(); $dbstore->disconnect(); return $password; } sub login{ my($nick, $pass) = @_; my($password) = getpassword($nick); my $encryptobj = new Digest::SHA2 512; $encryptobj->add($pass); my $digest = $encryptobj->hexdigest(); if($digest eq $password){ # replace this check above with something real ie lookup f +rom a database return 0; } else { return 1; } } $template->param(MYURL => 'http://192.168.1.9/cgi-bin'); print $query->header(-cookie=>$cookie),$template->output;
        I managed to get it to login, the return type on my database was wrong needed to add to the profile such as the $nick and not a false or true value. That seemed to fix it, but it still isnt giving a browser a cookie, maybe it doesnt do that since its a session. Thanks again :)
Re: CGI::Session error saying main::cookie used only once?
by Anonymous Monk on Jun 28, 2009 at 05:17 UTC
    You have scoping issues.
    C:\>perl -Mwarnings -e"$cookie = 6;" Name "main::cookie" used only once: possible typo at -e line 1. C:\>perl -Mwarnings -Mstrict -e"$cookie = 6;" Global symbol "$cookie" requires explicit package name at -e line 1. Execution of -e aborted due to compilation errors. C:\>perl -Mwarnings -Mdiagnostics -e"$cookie = 6;" Name "main::cookie" used only once: possible typo at -e line 1 (#1) (W once) Typographical errors often show up as unique variable nam +es. If you had a good reason for having a unique name, then just menti +on it again somehow to suppress the message. The our declaration is provided for this purpose. NOTE: This warning detects symbols that have been used only once s +o $c, @c, %c, *c, &c, sub c{}, c(), and c (the filehandle or format) are con +sidered the same; if a program uses $c only once but also uses any of the +others it will not trigger this warning. C:\>perl -Mwarnings -Mstrict -Mdiagnostics -e"$cookie = 6;" Global symbol "$cookie" requires explicit package name at -e line 1. Execution of -e aborted due to compilation errors (#1) (F) You've said "use strict vars", which indicates that all variab +les must either be lexically scoped (using "my"), declared beforehand +using "our", or explicitly qualified to say which package the global var +iable is in (using "::"). Uncaught exception from user code: Global symbol "$cookie" requires explicit package name at -e l +ine 1. Execution of -e aborted due to compilation errors. at -e line 1 C:\>