Global symbol "$line" and "$addr" requires explicit package name - perl

I'm trying to get the output to show a list of ip addresses and login with the corresponding country but I keep getting these errors: Global symbol $line and $addr requires explicit package name. It works fine in Perl but I'm running this script from the server. Anyone have any ideas? Thanks.
#!/usr/bin/perl
my $psql = "/usr/local/pgsql/current/bin/psql";
my $db = 'cpi';
my $args = "-U postgres -qc";
my $date = `/bin/date +\%y\%m\%d%H`;
my $reportfile = "/tmp/multiiplogins-$date";
my $sendmail = "/usr/sbin/sendmail -t -fcpi\#cpi-syndication.com";
my $mailsubject = "Login Report";
my $mailto = 'user#yahoo.com';
my $query = "SELECT userid, login, email, logins, ips FROM (SELECT userid,login,email, count(userid) AS logins, count(ipaddr) AS ips FROM (SELECT l.userid, u.login, u.email$
my $query2 = "SELECT l.userid, login, email, ipaddr FROM synloginaccess l, synusers u where l.accesstime > (now() - interval '24 hours') and l.type=2 and l.userid=u.userid $
open (REPORT, ">$reportfile");
my $command = qq/$psql $db $args "$query"/;
my $command2 = qq/$psql $db $args "$query2"/;
my $result = `$command`;
my $result2 = `$command2`;
#update IP addresses with country
use strict;
use warnings;
use Net::IPInfoDB;
my $g = Net::IPInfoDB->new;
$g->key("api_key");
#we split $login into an array, line-by-line
my #lines = split("\n",$result2);
for my $line (#lines) {
#now we iterate through every line one-by-one
$line =~ /(?<ip>\d+\.\d+\.\d+\.\d+)/;
my $addr = $g->get_country("$1");
print "$line " . "| ". "$addr->country_name" ."\n";
}
#print REPORT "$result2\n";
#print REPORT "\n";
print REPORT "$line " . "| ". "$addr->country_name" ."\n";
close REPORT;
mailReport();
sub mailReport{
#mail it
open(MAIL, "|$sendmail");
print MAIL "To: $mailto\n";
print MAIL "Subject: $mailsubject\n";
print MAIL "\n";
open (INFILE, "$reportfile");
my #contents = <INFILE>;

Your $line and $addr variables are no longer in scope when you try to print them after your for loop:
#print REPORT "$result2\n";
#print REPORT "\n";
print REPORT "$line " . "| ". "$addr->country_name" ."\n";
I imagine this line is supposed to be commented out.

Related

How to exclude or not print previous found entries in script

Can someone shed some light on how to have my script kick off only if new entries are found for the current hour? Our logs are based in 00 01 02, etc.
When this runs it will look for any accounts specified within my for loop and send an email if this particular user made a cert change for the hour. If a match is found then everything is fine.
But I am interested only in new real-time entries which I can't figure out.
This will be run from a cron, and I can't have it repeating the same entry. I am new to Perl and can't seem to figure this out.
I have tried the File::Tail module and other CPAN mods but due to company policies some mods are not allowed.
#!/usr/bin/perl -w
use strict;
my $flag = 0;
my $few = shift || 1;
my $id;
my $newline;
my $partyId;
my $userid;
my $tid;
my $infile;
my #Takeraccounts = ( 'SCN', 'CX' );
my $mail_dest = 'xxxxx#cx.com';
my %TIME;
(
$TIME{SEC}, $TIME{MIN}, $TIME{HOUR}, $TIME{MDAY}, $TIME{MON},
$TIME{YEAR}, $TIME{WDAY}, $TIME{YDAY}, $TIME{ISDST}
) = localtime(time);
my $OLD_MIN = $TIME{MIN};
my $OLD_HOUR = $TIME{HOUR};
my $cmd = "cat /raid/logs/`date +%H`";
my $out_file = "/home/resource/certchange.txt";
open FF, "$cmd |";
open( OUT, ">> $out_file" ) || die "Cannot open $out_file"; # temp file to which to write the formated output
while ( <FF> ) {
my $line = $_;
#chomp ($now_time);
$line =~ s/\n/ /;
if ( /Updating cert/ .. /,permissions/ ) {
$newline = "$line";
if ( $line =~ /Updating cert.*updated by (\w+)/ ) {
$id = $1;
}
if ( $newline =~ /UPDATE.*id:(\w+).*partyId:(\w+),perm:/ ) {
$userid = $1;
$partyId = $2;
foreach (#Takeraccounts) {
if ( $partyId =~ /$_/ ) {
print OUT "Certificate cert Updated by $id for userid $userid, PartyID $partyId\n";
open ML, "| mutt -e\"set realname='Support'; set use_from=yes; set from='support\#cx.com'; set envelope_from=yes\" -s ' Alert! cert CHANGED' -i $out_file -- $mail_dest";
close ML;
}
}
}
}
}
close FF;
close(OUT);
unlink $out_file;

Sendmail with time and pause using Perl

I have the following code e works perfectly, however, I want to set a time to send each email.
Example: 100 e-mail is sent, the PAUSE script for 1 hour, and sends back another 100 emails.
This code here it sends direct. I need to make the 2 work, and send emails slowly according to the txt list.
#!/usr/local/bin/perl
## use: perl send.pl list-email.txt "noreply#mail.com" "subject" html.html
$ARGC = #ARGV;
if ( $ARGC != 4 ) {
printf "$0 <mailist> <tes#test.com> <HELLO friend> <html.htm>\n\n";
#printf "Script for sending emails";
exit(1);
}
$mailtype = "content-type: text/html";
$sendmail = '/usr/sbin/sendmail';
$sender = $ARGV[1];
$subject = $ARGV[2];
$efile = $ARGV[0];
$emar = $ARGV[0];
$count = 1;
open( FOO, $ARGV[3] );
#foo = <FOO>;
$corpo = join( "\n", #foo );
open( BANDFIT, "$emar" ) || die "Can't Open $emar";
while (<BANDFIT>) {
( $ID, $options ) = split( /\|/, $_ );
chop($options);
foreach ($ID) {
$recipient = $ID;
open( SENDMAIL, "| $sendmail -t" );
print SENDMAIL "$mailtype\n";
print SENDMAIL "Subject: $subject\n";
print SENDMAIL "From: $sender\n";
print SENDMAIL "To: $recipient\n\n";
print SENDMAIL "$corpo\n\n";
close(SENDMAIL);
printf "Enviado para $recipient [ OK $count ]";
$count++;
}
}
close(BANDFIT);
=============== other code / time pause===============
#!/usr/bin/env perl
sub mostraMensagem() {
while (1) {
sleep(1);
print("Hello World!\n");
$count++;
if ( $count == 5 ) {
print("PAUSE!\n");
$count = 0;
sleep(5);
print("CONTINUE..\n");
mostraMensagem;
}
}
}
mostraMensagem;
I got friends !! but still need you ...
it sends 5 emails and pause for 5 seconds, however, the count does not continue, it returns to zero. what can we do?
the counter back to zero after 5 ..
The new CODE:
#!/usr/local/bin/perl
## use: perl enviar.pl list-mail.txt "my#mail.com" "subject" html.html
$ARGC=#ARGV;
if ($ARGC !=4) {
printf "$0 <mailist> <my#myemail.com> <subject> <msg.htm>\n\n";
#printf "Script sending emails";
exit(1);
}
$mailtype = "content-type: text/html";
$sendmail = '/usr/sbin/sendmail';
$sender = $ARGV[1];
$subject = $ARGV[2];
$efile = $ARGV[0];
$emar = $ARGV[0];
$count=1;
open(FOO, $ARGV[3]);
#foo = <FOO>;
$corpo = join("\n", #foo);
open (BANDFIT, "$emar") || die "Can't Open $emar";
while(<BANDFIT>) {
($ID,
$options) = split(/\|/,$_);
chop($options);
foreach ($ID) {
$recipient = $ID;
## this changes =>>> ###
### send 5 email of list.txt, and pause 5 seconds, continue.. ###
if ( $count == 5 ) {
print("PAUSE!\n");
$count = 0;
sleep(5);
print("CONTINUE..\n");
}
open (SENDMAIL, "| $sendmail -t");
print SENDMAIL "$mailtype\n";
print SENDMAIL "Subject: $subject\n";
print SENDMAIL "From: $sender\n";
print SENDMAIL "To: $recipient\n\n";
print SENDMAIL "$corpo\n\n";
close (SENDMAIL);
printf "sending for $recipient [ Ok Send; $count ]";
$count++;
}
}
close(BANDFIT);
#### end #####
Essentially you would count the amount of emails sent, when you reach the 100 mark, pause for 3600 seconds and then continue.
** UDPATE - Full Code **
Tested (smaller numbers) on RHEL 5
Assuming email-list.txt looks like:
user_1_#company.com
user_2_#company.com
user_99_#company.com
user_100_#company.com
Code:
#!/usr/bin/perl
# =========================
# Assign $ARGV[x] -> var
# =========================
if (#ARGV < 4){ usage() }
my $sendAs = $ARGV[1];
my $subject = $ARGV[2];
my $htmlFile = $ARGV[3];
my $sendList = $ARGV[0];
# =========================
# Get Send List -> var
# =========================
open(LIST, $sendList) || die "Could not open $sendList: $!\n";
my #recipients = <LIST>;
close(LIST);
# =========================
# Iterate / Send Email
# =========================
my $count = 1;
foreach my $recipient (#recipients)
{
chomp($recipient);
if ( $count < 100 )
{
my $cmd = 'cat ' . $htmlFile . ' | /usr/sbin/sendmail -s "$(echo -e "' . $subject . '\nContent-Type: text/html")" ' . $recipient . ' -v -- -F ' . $sendAs;
my $results = `$cmd`;
}
elsif ( $count == 100 )
{
my $cmd = 'cat ' . $htmlFile . ' | /usr/sbin/sendmail -s "$(echo -e "' . $subject . '\nContent-Type: text/html")" ' . $recipient . ' -- -F ' . $sendAs;
my $results = `$cmd`;
sleep(3600);
$count = 0;
}
$count++;
}
# =========================
# Essential Subroutines
# =========================
sub usage()
{
print "\nUsage:\n\t$0 <mailist.txt> <test\#mail.com> <\"Hello friend\"> <test.html>\n\n";
exit;
}
P.S. LEARN PERL

Perl script works with -w switch but not without

This script works on localhost with the -w switch but not without. It also works when use strict and use warning are active.
apache2/error.log:
without switch (aborted script):
(2)No such file or directory: exec of ... failed
with the switch I get:
Use of uninitialized value $email_flag in string ne ...
which looks initialised to me.
On the live web server neither one works. Perl is new to me, but I know some BASH and PHP.
I run Debian Lenny, Apache2, Perl 5.10.
#!/usr/bin/perl -w
$| = 1;
my $mailprog = '/usr/sbin/sendmail'; # where the mail program lives
my $to = "not\#for.you"; # where the mail is sent
my ($command,$email,#pairs,$buffer,$pair,$email_flag) ;
read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
#pairs = split(/&/, $buffer);
foreach $pair (#pairs) {
# Split the pair up into individual variables. #
my($name, $value) = split(/=/, $pair);
# Decode the form encoding on the name and value variables. #
$name =~ tr/+/ /;
$name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
# If they try to include server side includes, erase them, so they
# aren't a security risk if the html gets returned. Another
# security hole plugged up.
$value =~ s/<!--(.|\n)*-->//g;
## print "Name of form element is $name with value of $value \n";
if ($name eq 'email') {
$email = $value;
}
if ($name eq 'command') {
$command = $value;
}
}
if ($email =~ /(#.*#)|(\.\.)|(#\.)|(\.#)|(^\.)/ ||
$email !~ /^.+\#(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,3}|[0-9]{1,3})(\]?)$/ ) {
$email_flag = "ERROR";
}
my $urlcommand = $command;
if ($command eq 'Subscribe') {
$command = "SUBSCRIBE rpc-news";
}
if ($command eq 'Unsubscribe') {
$command = "UNSUBSCRIBE rpc-news";
}
if ($command eq 'Suspend') {
$command = "SET rpc-news NOMAIL";
}
if ($command eq 'Resume') {
$command = "SET rpc-news MAIL";
}
my $getInfo = '';
print "Content-Type: text/html\n";
if ($email_flag ne "ERROR") {
open(MAIL,"|$mailprog -t");
print MAIL "To: $to\n";
print MAIL "From: $email\n";
print MAIL "Subject: [rpc-news] $command \n";
print MAIL "Reply-to: $email \n";
print MAIL "$command \n";
print MAIL "EXIT \n";
close (MAIL);
$getInfo = "?result=good";
}
if ($email_flag eq "ERROR") {
$getInfo = "?result=bad";
}
my $rootURL= $ENV{'SERVER_NAME'};
my $url = "http://${rootURL}/thank_you.html${getInfo}&action=${urlcommand}";
print "Location: $url\n\n";
Did you create your script on a Windows machine and upload it to a Linux server without fixing the line endings? Without the -w switch, the shebang line may look like "#!/usr/bin/perl\r", so the system goes looking for a program named "perl\r" (or however the line ending looks). With the -w switch, "#!/usr/bin/perl" doesn't have an indecipherable line ending stuck to it. Instead, that gets stuck to -w where it doesn't cause failure.
I thought there was a perlfaq about this, but I can't seem to find it in the docs at the moment.
Update: I found it over on PerlMonks, in a really old Q&A topic that seems unrelated until you read the body of the message: Answer: How to get rid of premature end of script headers. Yeah, I know, if you were just browsing threads you wouldn't even stop on that one. But here's the text of the post:
If you developed this script on
Windows, it's possible that the script
file has non-UNIX line endings. (The
perl interpreter can handle them, but
the shebang line is interpreted by the
shell, and is not tolerant of
incorrect line endings.) If this is
the problem, the script may terminate
with an error right at the shebang
line.
Use of uninitialized value $email_flag in string ne ...
which looks initialised to me.
if ($email =~ /(#.*#)|(\.\.)|(#\.)|(\.#)|(^\.)/ ||
$email !~ /^.+\#(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,3}|[0-9]{1,3})(\]?)$/
) {
$email_flag = "ERROR";
}
$email_flag only gets initialized here if the pattern matches - otherwise it's left undefined. You could add an else clause to ensure it gets initialized no matter what.
I would not use that code, it doesn't use CGI.pm (or CGI::Simple ...)
Get "TFMail -- Improved Form Mail" from "nms - web programs written by experts"
Its simple to install, and its written well ( it uses CGI ...)

cant connect to remote machine using WMI and Perl

I'm trying to write a script that will get event log information off of a remote windows machine using the win32::ole module and a WMI query. I can ping the machine but no matter what my WMI connection always fails using the ConnectServer() method. I'm pretty sure its not a firewall related problem. Here is my code:
use Win32::OLE qw(in);
use Net::Ping;
use constant wbemFlagReturnImmediately => 0x10;
use constant wbemFlagForwardOnly => 0x20;
my $computer = "10.10.10.15";
my $user = "Administrator";
my $pwd = "pass";
$p = Net::Ping->new();
print "$computer is alive.\n" if $p->ping($host);
$p->close();
my $locatorObj =Win32::OLE->new("WbemScripting.SWbemLocator") or die "ERROR CREATING OBJ";
$locatorObj->{Security_}->{impersonationlevel} = 3;
my $objWMIService = $locatorObj->ConnectServer($computer, "root\civm2", $user, $pwd) or die "WMI connection failed.\n";
my $colItems = $objWMIService->ExecQuery("SELECT * FROM Win32_NTLogEvent", "WQL",
wbemFlagReturnImmediately | wbemFlagForwardOnly);
foreach my $objItem (in $colItems) {
print "Category: $objItem->{Category}\n";
print "CategoryString: $objItem->{CategoryString}\n";
print "ComputerName: $objItem->{ComputerName}\n";
print "Data: " . join(",", (in $objItem->{Data})) . "\n";
print "EventCode: $objItem->{EventCode}\n";
print "EventIdentifier: $objItem->{EventIdentifier}\n";
print "EventType: $objItem->{EventType}\n";
print "InsertionStrings: " . join(",", (in $objItem->{InsertionStrings})) . "\n";
print "Logfile: $objItem->{Logfile}\n";
print "Message: $objItem->{Message}\n";
print "RecordNumber: $objItem->{RecordNumber}\n";
print "SourceName: $objItem->{SourceName}\n";
print "TimeGenerated: $objItem->{TimeGenerated}\n";
print "TimeWritten: $objItem->{TimeWritten}\n";
print "Type: $objItem->{Type}\n";
print "User: $objItem->{User}\n";
print "\n";
}
Any ideas why my attempt to connect always fails? Thanks :)
The ConnectServer call has a couple of potential issues:
I believe it needs two back slashes.
And It has a typo: civm2 -> cimv2
And it might reveal more information by adding a call to retrieve the error information:
my $objWMIService = $locatorObj->ConnectServer($computer, "root\\cimv2", $user, $pwd)
or die "WMI connection failed.\n", Win32::OLE->LastError;

Why do I get a blank page from my Perl CGI script?

The user enters a product code, price and name using a form. The script then either adds it to the database or deletes it from the database. If the user is trying to delete a product that is not in the database they get a error message. Upon successful adding or deleting they also get a message. However, when I test it I just get a blank page. Perl doesnt come up with any warnings, syntax errors or anything; says everything is fine, but I still just get a blank page.
The script:
#!/usr/bin/perl
#c09ex5.cgi - saves data to and removes data from a database
print "Content-type: text/html\n\n";
use CGI qw(:standard);
use SDBM_File;
use Fcntl;
use strict;
#declare variables
my ($code, $name, $price, $button, $codes, $names, $prices);
#assign values to variables
$code = param('Code');
$name = param('Name');
$price = param('Price');
$button = param('Button');
($code, $name, $price) = format_input();
($codes, $names, $prices) = ($code, $name, $price);
if ($button eq "Save") {
add();
}
elsif ($button eq "Delete") {
remove();
}
exit;
sub format_input {
$codes =~ s/^ +//;
$codes =~ s/ +$//;
$codes =~ tr/a-z/A-Z/;
$codes =~ tr/ //d;
$names =~ s/^ +//;
$names =~ s/ +$//;
$names =~ tr/ //d;
$names = uc($names);
$prices =~ s/^ +//;
$prices =~ s/ +$//;
$prices =~ tr/ //d;
$prices =~ tr/$//d;
}
sub add {
#declare variable
my %candles;
#open database, format and add record, close database
tie(%candles, "SDBM_File", "candlelist", O_CREAT|O_RDWR, 0666)
or die "Error opening candlelist. $!, stopped";
format_vars();
$candles{$codes} = "$names,$prices";
untie(%candles);
#create web page
print "<HTML>\n";
print "<HEAD><TITLE>Candles Unlimited</TITLE></HEAD>\n";
print "<BODY>\n";
print "<FONT SIZE=4>Thank you, the following product has been added.<BR>\n";
print "Candle: $codes $names $prices</FONT>\n";
print "</BODY></HTML>\n";
} #end add
sub remove {
#declare variables
my (%candles, $msg);
tie(%candles, "SDBM_File", "candlelist", O_RDWR, 0)
or die "Error opening candlelist. $!, stopped";
format_vars();
#determine if the product is listed
if (exists($candles{$codes})) {
delete($candles{$codes});
$msg = "The candle $codes $names $prices has been removed.";
}
else {
$msg = "The product you entered is not in the database";
}
#close database
untie(%candles);
#create web page
print "<HTML>\n";
print "<HEAD><TITLE>Candles Unlimited</TITLE></HEAD>\n";
print "<BODY>\n";
print "<H1>Candles Unlimited</H1>\n";
print "$msg\n";
print "</BODY></HTML>\n";
}
Running it at the command line with:
perl something.cgi Button=Save
...gives me an error:
Undefined subroutine &main::format_vars called at something.pl line 55.
If I change both references of format_vars() to "format_input()", I get what I think is the proper output.
You're not printing any output aside from the Content-Type header unless add or remove gets called. The problem is just that you forgot to display a form (presumably one containing the buttons) if no button has been clicked.
Edit: Copying your posted code and doing a little cleanup, then calling it at the URL http://localhost/~me/foo.cgi?Code=1;Name=2;Price=3;Button=Save or http://localhost/~me/foo.cgi?Code=1;Name=2;Price=3;Button=Delete, I do get proper HTML output. The cleaned up version of the code used for this is:
#!/usr/bin/perl
use strict;
use warnings;
print "Content-type: text/html\n\n";
use CGI qw(:standard);
use SDBM_File;
use Fcntl;
use strict;
#declare variables
my ($code, $name, $price, $button, $codes, $names, $prices);
#assign values to variables
$code = param('Code');
$name = param('Name');
$price = param('Price');
$button = param('Button');
($code, $name, $price) = format_input();
($codes, $names, $prices) = ($code, $name, $price);
if ($button eq "Save") {
add();
}
elsif ($button eq "Delete") {
remove();
}
exit;
sub format_input {
$codes =~ s/^ +//;
$codes =~ s/ +$//;
$codes =~ tr/a-z/A-Z/;
$codes =~ tr/ //d;
$names =~ s/^ +//;
$names =~ s/ +$//;
$names =~ tr/ //d;
$names = uc($names);
$prices =~ s/^ +//;
$prices =~ s/ +$//;
$prices =~ tr/ //d;
$prices =~ tr/$//d;
}
sub add {
# #declare variable
# my %candles;
#
# #open database, format and add record, close database
# tie(%candles, "SDBM_File", "candlelist", O_CREAT|O_RDWR, 0666)
# or die "Error opening candlelist. $!, stopped";
#
# format_vars();
# $candles{$codes} = "$names,$prices";
# untie(%candles);
#create web page
print "<HTML>\n";
print "<HEAD><TITLE>Candles Unlimited</TITLE></HEAD>\n";
print "<BODY>\n";
print "<FONT SIZE=4>Thank you, the following product has been added.<BR>\n";
print "Candle: $codes $names $prices</FONT>\n";
print "</BODY></HTML>\n";
} #end add
sub remove {
# #declare variables
# my (%candles, $msg);
#
# tie(%candles, "SDBM_File", "candlelist", O_RDWR, 0)
# or die "Error opening candlelist. $!, stopped";
#
# format_vars();
#
# #determine if the product is listed
# if (exists($candles{$codes})) {
# delete($candles{$codes});
# $msg = "The candle $codes $names $prices has been removed.";
# }
# else {
# $msg = "The product you entered is not in the database";
# }
# #close database
# untie(%candles);
#create web page
print "<HTML>\n";
print "<HEAD><TITLE>Candles Unlimited</TITLE></HEAD>\n";
print "<BODY>\n";
print "<H1>Candles Unlimited</H1>\n";
# print "$msg\n";
print "<p>Called remove</p>";
print "</BODY></HTML>\n";
}
Note that, with warnings enabled, this spews a lot of "uninitialized value" warnings because you're getting $code vs $codes, $name vs $names, and $price vs $prices confused with each other in bad ways. (Hint: You assign ($code, $name, $price) = format_input();, but format_input doesn't return three values.)
I suspect that, as suggested in an earlier comment, you're having case-sensitivity issues again/still. My first attempt at testing this failed because I used "button=Save" instead of "Button=Save" in the URL. HTTP request parameter names are generally all-lowercase by convention, and for good reason, as it helps to avoid problems of that sort.
Other random comments:
You can declare your variables at the same time as you first assign them, e.g., my $code = param('Code');. This is generally considered to be the better/preferred practice, as making your declaration as late as possible helps to minimize the variable's scope.
In format_input, it's redundant to both s/^ +//; s/ +$//; and tr/ //d;, as the tr will also remove leading and trailing spaces.
When getting values of your parameters, you should either supply default values for if the parameter is empty/missing or check for empty/missing and display an error to the user.
You should also have a final else clause after the elsif ($button eq "Delete") to display an error if $button is missing or invalid. Yes, I know this script is intended to be called from a specific form, so it should "always" have a valid $button, but it's trivial to bypass the form and submit any set of values (valid or not) to the script directly, so you still need to verify and validate everything on the server side because you don't know where it will actually be coming from or whether the client validated it properly.
This is how I ran the script and it did yield the proper results. Make sure wherever you are hosting the site, it has the proper PERL modules installed.
Note: The hosting service I am using (BlueHost) requires me to call up my Perl Modules via the #!/usr/bin/perlml
#!/usr/bin/perlml
use strict;
use warnings;
print "Content-type: text/html\n\n";
use CGI qw(:standard);
use SDBM_File;
use Fcntl;
use strict;
#declare variables
my ($code, $name, $price, $button, $codes, $names, $prices);
#assign values to variables
$code = param('Code');
$name = param('Name');
$price = param('Price');
$button = param('Button');
($codes, $names, $prices) = format_input();
($codes, $names, $prices) = ($code, $name, $price);
if ($button eq "Save") {
add();
}
elsif ($button eq "Delete") {
remove();
}
exit;
sub format_input {
$codes =~ s/^ +//;
$codes =~ s/ +$//;
$codes =~ tr/a-z/A-Z/;
$codes =~ tr/ //d;
$names =~ s/^ +//;
$names =~ s/ +$//;
$names =~ tr/ //d;
$names = uc($names);
$prices =~ s/^ +//;
$prices =~ s/ +$//;
$prices =~ tr/ //d;
$prices =~ tr/$//d;
}
sub add {
#declare variable
my %candles;
#open database, format and add record, close database
tie(%candles, "SDBM_File", "candlelist", O_CREAT|O_RDWR, 0666)
or die "Error opening candlelist. $!, stopped";
format_input();
$candles{$code} = "$name,$price";
untie(%candles);
#create web page
print "<HTML>\n";
print "<HEAD><TITLE>Candles Unlimited</TITLE></HEAD>\n";
print "<BODY>\n";
print "<FONT SIZE=4>Thank you, the following product has been added.<BR>\n";
print "Candle: $codes, $names, $prices</FONT>\n";
print "</BODY></HTML>\n";
} #end add
sub remove {
#declare variables
my (%candles, $msg);
tie(%candles, "SDBM_File", "candlelist", O_RDWR, 0)
or die "Error opening candlelist. $!, stopped";
format_input();
#determine if the product is listed
if (exists($candles{$code})) {
delete($candles{$code});
$msg = "The candle $code, $name, $price has been removed.";
}
else {
$msg = "The product you entered is not in the database";
}
#close database
untie(%candles);
#create web page
print "<HTML>\n";
print "<HEAD><TITLE>Candles Unlimited</TITLE></HEAD>\n";
print "<BODY>\n";
print "<H1>Candles Unlimited</H1>\n";
print "$msg\n";
print "</BODY></HTML>\n";
}