print to a text file.
I've tryed over at sitepoint now im going to try here i know its this part of the script now thats wrong : -
sub printaddr {
open (data, ">>$banlist");
@data=;
close(data);
foreach $data(@data) {
@datax=($data);
unless ($input{'ipnumber'} eq "@datax[0]") {
open(ip, ">>$banlist");
print ip "$input{'ipnumber'}\n";
close(ip);
}
}
}
What inside that coding looks wrong?. i'm trying to get it to print an ip address to a text file. So if i typed in 234.234 and pressed enter the script would print it to the file but this coding dont ive played about with it for nearly 4 hours now some help or even a solution would be great.
Mark Hensler posted this at 23:40 — 15th October 2000.
He has: 4,048 posts
Joined: Aug 2000
1) your opening the file wrong the first time...open
(data, ">>$banlist"); This opens the file for appending. Use this: (data, "$banlist");
2) Why are you doing this?
foreach $data(@data) {
@datax=($data);
What is going to be used to split the string into an array?
3) Can we see the flat file?
If you just want to append to the flat file IPs that are not already in there, try this. (not tested):
open(FILE, $banlist);
@file = <FILE>;
close(FILE);
foreach $line (@file) {
if ($input{'ipnumber'} eq $line)
$found = "yes";
}
if ($found != "yes") {
open(ip, ">>$banlist");
print ip "$input{'ipnumber'}\n";
close(ip);
}
This could be compressed a bit more, but it should work fine for what you need.
Mark Hensler
If there is no answer on Google, then there is no question.
Technics posted this at 13:38 — 16th October 2000.
They have: 12 posts
Joined: Aug 2000
Thats the file. I added your coding too in place of the orignal and got my best friend the internal server error. I'm guessing i may have to start from scratch with the peice of code you said but wouldnt know where to begin. It shows in the file im not the brightest.
#!/usr/bin/perl
#########################
# Variables
$banfile = "/home/demon/demon-www/cgi-bin/badboys.txt";
# data path to your banned.txt file.
# it must be chmodded 777, or world-writable
# (it was most convenient for me to place it
# in my messages dir since that was already
# chmodded 777)
$password = "admin";
# admin password
$scriptfn = "everyadmin.cgi";
# filename of this script (full path not necessary)
#########################
&get_input;
if ($input{'password'} ne "$password") {
print <<"END";
Content-type: text/html
<HTML>
<HEAD>
<TITLE>PASSWORD REQUIRED</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#001F76" VLINK="#001F76">
<form method="post" action="$scriptfn">
<center><table border="0" cellspacing="0" width="250">
<tr><td bgcolor="#001F76"><font color="white" size="+1"><b>PASSWORD REQUIRED</b></font>
</td></tr><tr><td bgcolor="#DCDCDC" align="center">
<input type="password" name="password"></td></tr></table></center></form>
</BODY>
</HTML>
END
}
elsif ($input{'ipnumber'} ne "") {
&printaddr;
print <<"END";
Content-type: text/html
<HTML>
<HEAD>
<TITLE>IP NUMBER BANNED</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#001F76" VLINK="#001F76">
<center><table border="0" cellspacing="0" width="250">
<tr><td bgcolor="#001F76"><font color="white" size="+1"><b>IP NUMBER BANNED</b></font>
</td></tr><tr><td bgcolor="#DCDCDC" align="center">
The IP number you entered has been banned.</td></tr></table></center>
</BODY>
</HTML>
END
} else {
print <<"END";
Content-type: text/html
<HTML>
<HEAD>
<TITLE>BAN IP NUMBER</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#001F76" VLINK="#001F76">
<form method="post" action="$scriptfn">
<center><table border="0" cellspacing="0" width="250">
<tr><td bgcolor="#001F76"><font color="white" size="+1"><b>BAN IP NUMBER</b></font>
</td></tr><tr><td bgcolor="#DCDCDC" align="center">
<input type="text" name="ipnumber" value="IP NUMBER" maxlength="15"></td></tr></table>
</center><input type="hidden" name="password" value="$input{'password'}"></form>
</BODY>
</HTML>
END
}
sub printaddr {
open (data, "<$banfile");
@data=<data>;
close(data);
foreach $data(@data) {
@datax=($data);
unless ($input{'ipnumber'} eq "@datax[0]") {
open(ip, "$banfile");
print ip "$input{'ipnumber'}\n";
close(ip);
}
}
}
sub get_input {
if($ENV{'REQUEST_METHOD'} =~ /get/i)
{
@pairs=split(/&/,$ENV{'QUERY_STRING'});
}
else
{
$buffer = "";
read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
@pairs=split(/&/,$buffer);
}
foreach $pair (@pairs)
{
@a = split(/=/,$pair);
$name=$a[0];
$value=$a[1];
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$value =~ s/~!/ ~!/g;
$value =~ s/\+/ /g;
$value =~ s/(\r)+/\-\-/g;
$value =~ s/\n+//g;
push (@input,$name);
push (@input,$value);
}
%input=@input;
%input;
}
Mark Hensler posted this at 06:46 — 17th October 2000.
He has: 4,048 posts
Joined: Aug 2000
I haven't analyzed the rest of the file...
What happens when we do something like this:
sub printaddr {
open (FILE, "$banfile");
$ThePage = join('|', <FILE>);
close (FILE);
unless ($ThePage =~ /$input{'ipnumber'}/) {
$ThePage =~ s/\|/\n/g;
$ThePage .= "$input{'ipnumber'}\n";
open(FILE, ">$banfile");
print FILE $ThePage;
close(FILE);
} #END unless
} #END sub
Logic:
By default, pages are split up by newline characters. So I'm joining them into one string (memory saver). $ThePage will look like this:
"line1|line2|line3" ... etc.
Then I say 'unless $ThePage' contains the IP, do the following:
1) replace "|" with newline characters
2) add the IP to $ThePage
3) put $ThePage back into the file
Mark Hensler
If there is no answer on Google, then there is no question.
Mark Hensler posted this at 06:48 — 17th October 2000.
He has: 4,048 posts
Joined: Aug 2000
sorry about the face...
that one line looks like this:
$ThePage = join('|', );
Technics posted this at 14:13 — 17th October 2000.
They have: 12 posts
Joined: Aug 2000
thanks it works.
Whats the command to edit a text file from a cgi script?. To also remove the banned ip from the list. Instead of logging into ftp and removing it.
Thank you for your help.
Mark Hensler posted this at 22:22 — 17th October 2000.
He has: 4,048 posts
Joined: Aug 2000
You want to make a script to remove IPs from the list?
I'll use the same variable for the IP and let you make a new subroutin to put it in...
sub removeaddr {
open (FILE, "$banfile");
$ThePage = join('|', <FILE>;
close (FILE);
$ThePage =~ /(.*)$input{'ipnumber'}|(.*)/;
$ThePage = $1 . $2;
$ThePage =~ s/\|/\n/g;
open(FILE, ">$banfile");
print FILE $ThePage;
close(FILE);
} #END unless
} #END sub
Logic:
1) replace "|" with newline characters
2) match the pattern [wild card] IP [wild card]
3) make $ThePage the first wild card and the second (thus, removing the IP)
4) put $ThePage back into the file
Mark Hensler
If there is no answer on Google, then there is no question.
Orpheus posted this at 00:48 — 18th October 2000.
They have: 568 posts
Joined: Nov 1999
You can't push the entire contents of a file into a file into a string without saying local($\); first.
Just thought i'd point that out.
Mark Hensler posted this at 03:39 — 18th October 2000.
He has: 4,048 posts
Joined: Aug 2000
I don't understand?
your saying that this won't work?
open (FILE, "$banfile");
$ThePage = join('|', <FILE>;
close (FILE);
$ThePage =~ s/\|/\n/g;
print $ThePage;
Try it... I've used it before and it's worked fine.
what does local(); do?
I've seen $_ but not $\ ... do you mean local($_);?
Mark Hensler
If there is no answer on Google, then there is no question.
Orpheus posted this at 06:22 — 18th October 2000.
They have: 568 posts
Joined: Nov 1999
nope, that wont work
it will only do the first line of the file
try this
sub removeaddr {
local($/);
open (FILE, "$banfile");
$ThePage = join('|', <FILE>;
close (FILE);
$ThePage =~ /(.*)$input{'ipnumber'}|(.*)/;
$ThePage = $1 . $2;
$ThePage =~ s/\|/\n/g;
open(FILE, ">$banfile");
print FILE $ThePage;
close(FILE);
}
}
Orpheus posted this at 06:24 — 18th October 2000.
They have: 568 posts
Joined: Nov 1999
Ok, scratch that. It MIGHT work, i just noticed you didn't do a file to string right away, but it's best to be safe.
japhy posted this at 14:20 — 18th October 2000.
They have: 161 posts
Joined: Dec 1999
I really think we need to start from scratch here. WHAT does the file holding the IP addresses look like? Is it just one IP address per line? Or is there more data?
Next, all you want to do is see whether or not the IP address is in the file, and if it is not, add it?
If I have these basic ideas down correctly, then I suggest you try the following code. I'm going to present in stages.
Code 1.0
sub addIP {
my $to_add = shift;
my $found = 0;
# look for it in the file
open FILE, $IP_FILE or die "can't open $IP_FILE: $!";
while (<FILE>) {
chomp;
if ($_ eq $to_add) { $found = 1; last; }
}
close FILE;
# add it to the file if it wasn't there
if (not $found) {
open FILE, ">> $IP_FILE" or die "can't append to $IP_FILE: $!";
print FILE "$to_add\n";
close FILE;
}
}
This code saves us the trouble of reading through the entire file if the IP address is already in there, due to me calling last() if the IP address is found. This code can be made more efficient, though, by opening the file for reading AND writing:
Code 2.0
sub addIP {
my $to_add = shift;
my $found = 0;
# look for it in the file
open FILE, "+< $IP_FILE" or die "can't open $IP_FILE for read/write: $!";
seek FILE, 0, 0; # ensure we're at the beginning
while (<FILE>) {
chomp;
if ($_ eq $to_add) { $found = 1; last; }
}
# add it if not found
if (not $found) {
print FILE "$to_add\n";
}
close FILE;
}
This is better, since we only open the file once, and it still works as before. I'm going to streamline things a bit, to make it look a bit cleaner:
Code 2.1
sub addIP {
my $to_add = shift;
my $found = 0;
# look for it in the file
open FILE, "+< $IP_FILE" or die "can't open $IP_FILE for read/write: $!";
seek FILE, 0, 0; # ensure we're at the beginning
while (<FILE>) {
chomp;
last if $found = ($_ eq $to_add); # XXX
}
# add it if not found
print FILE "$to_add\n" if not $found;
close FILE;
}
The line I marked with XXX is pretty nifty -- if $_ and $to_add are the same, then $_ eq $to_add is true, and returns 1. Otherwise, it's false, and returns ''. In turn, $found gets set to the value returned by that test, so if the test returns 1, $found is set to 1, and we can exit the block.
There's another thing I'd suggest adding, which is file locking. This is so that if two people run your program at once, you needn't worry about your file getting corrupted.
Code 3.0
use Fcntl 'LOCK_EX'; # import the LOCK_EX constant
sub addIP {
my $to_add = shift;
my $found = 0;
# look for it in the file
open FILE, "+< $IP_FILE" or die "can't open $IP_FILE for read/write: $!";
flock FILE, LOCK_EX; # lock this file
seek FILE, 0, 0; # ensure we're at the beginning
while (<FILE>) {
chomp;
last if $found = ($_ eq $to_add);
}
# add it if not found
print FILE "$to_add\n" if not $found;
close FILE;
# file gets unlocked automatically
}
And last, but not least, let's localize the filehandle, so we can get rid of the $found variable too, as well as have Perl close the filehandle for us:
Code 3.1
use Fcntl 'LOCK_EX'; # import the LOCK_EX constant
sub addIP {
my $to_add = shift;
local *FILE; # localize the filehandle
# look for it in the file
open FILE, "+< $IP_FILE" or die "can't open $IP_FILE for read/write: $!";
flock FILE, LOCK_EX; # lock this file
seek FILE, 0, 0; # ensure we're at the beginning
while (<FILE>) {
chomp;
return if $_ eq $to_add; # return if found
}
# if we got here, it couldn't have been found
print FILE "$to_add\n";
# file gets unlocked automatically
}
Ok, that's all for now.
Technics posted this at 14:25 — 18th October 2000.
They have: 12 posts
Joined: Aug 2000
Thanks guys for your help but both codes both cause internal server errors .
japhy posted this at 14:33 — 18th October 2000.
They have: 161 posts
Joined: Dec 1999
Ok, so you're getting a server error. When you used my code, did you:
* make a variable called $IP_FILE that holds the path to the file you want to edit?
* call the function as addIP($addr), where $addr is a scalar holding an IP address?
* make sure the web user can write to the IP address file?
* check the error log to see WHY the program died?
I suggest you include this line of code near the top of your program:
use CGI::Carp 'fatalsToBrowser';
Assuming you HAVE the CGI::Carp module, this will send fatal errors to your browser, instead of just being less-than-helpful.
Technics posted this at 15:44 — 18th October 2000.
They have: 12 posts
Joined: Aug 2000
Thanks again.
Well im very stumped now. I tryed adding those to the script but dont know what im doing wrong because no matter what i get an internal server error. I'm no perl whizz as you can see.
Want to join the discussion? Create an account or log in if you already have one. Joining is fast, free and painless! We’ll even whisk you back here when you’ve finished.