Gossamer Forum
Home : General : Perl Programming :

Help with UN WEBIFY

Quote Reply
Help with UN WEBIFY
I wrote a short script to display files on my system at work through my web browser. This way I can vew text files, log files, html or anything. Now I want to update it to either DISPLAY html code or NOT display it at all and use it. I can do the input code, no problem. My question is this: In my Print somefile routine, how do I replace < with the asci code for it. Replacing the < will in effect negate the html from being parsed and display the raw code. I do it all the time when I write how-to's for html. I figure this would be the easy method and will allow me to use nice fonts that the <pre> tag will not. At any rate, here is my script.



Code:

#!/usr/local/bin/perl
#This script adds to the database file
#



use CGI;
$in = new CGI;

$header = "header.html";
$footer = "footer.html";
$filename = $in->param('filename');
$dir = $in->param('dir');


print "Content-type: text/html\n\n";

open (CROWEHEADER,"<$header");
@header_in=<CROWEHEADER>;
foreach $_ (@header_in)
{ print $_ ; }
close (CROWEHEADER);

open (CROWEFOO,"<$dir/$filename");
@somefile_in=<CROWEFOO>;
foreach $_ (@SOMEFILE_in)
{
print "<font size=2 face=verdana,arial>";
print $_ ;
print "<br>";
}
close (CROWEFOO);


open (CROWEFOOTER,"<$footer");
@footer_in=<CROWEFOOTER>;
foreach $_ (@footer_in)
{ print $_ ; }
close (CROWEFOOTER);



An help would be appreciated!






------------------
The Crowe crowe@charter.net
www.lit.org Links Engine for Writing on the net!



Quote Reply
Re: Help with UN WEBIFY In reply to
Two ways.

1) if you only need to replace < and > use &lt ; and &gt ; (without the spaces... needed to do them here so the board wouldnt parse them)

2) you are using CGI.pm so you could just do:
$blah = escapeHTML(param('whatever'));

and that should work, though i can't test it right this moment.

--mark
Quote Reply
Re: Help with UN WEBIFY In reply to
also... why are you doing things like:

foreach $_ (@header_in)

?

That is wrong.

just foreach (@header_in) {

and $_ will be automatically set on each iteration.

--mark
Quote Reply
Re: Help with UN WEBIFY In reply to
This is only my second perl program. I'm sure this program has already been written, but I did it to learn and I found it useful. I always find myself wanting to few a config file, or some html source without loading up my bloated ftp program or whatever.

Mark, Applied your suggestions! Very nice. I thought that was how $_ worked but wasn't sure. I've included my completed script in case anyone wants it or wants to learn from it, or better yet, has any more great suggestions!!!

One of these days I'll actually tacle sorting and reg expressions.

Code:
#!/usr/bin/perl
#This script adds to the database file
#



#use CGI;
use CGI qw/escapeHTML unescapeHTML/;

$in = new CGI;

print "Content-type: text/html\n\n";


$header = "header.html";
$footer = "footer.html";
$filename = $in->param('filename');
$dir = $in->param('dir');
$display = $in->param('display');



if ($display eq "txt") { &print_plain_txt; }
elsif ($display eq "html") { &print_html; }
else { &print_form; }





sub print_form {
&print_header;

print " <table width=750 cellpadding=0 cellspacing=0 border=0><td valign=top> \n";
print " <TABLE border=0 cellPadding=0 cellSpacing=0 width=100\%> \n";
print " <TR><TD align=middle bgcolor=000000 valign=center> \n";
print " <TABLE border=0 cellPadding=4 cellSpacing=2 width=100\%> \n";
print " <TR bgcolor=5C6E7F><TD align=left bgcolor=5C6E7F valign=center> \n";
print " <table cellpadding=0 cellspacing=0 border=0 width=100\%> \n";
print " <td valign=top align=left><FONT color=black face=verdana,arial size=1> \n";
print " <b>Show Me a File</b></FONT></td></td></table></TD></TR> \n";
print " <TR><TD bgcolor=343E47 valign=top> \n";
print " <font face=Verdana,Arial size=2 color=E0E0E0> \n";

print " <FORM METHOD=POST ACTION=show.cgi> \n";

print " Directory (include trailing slash)<br> \n";
print " <em>ie. /home/crowe/somedir/</em><br> \n";
print " <INPUT NAME=dir size=30><br> \n";


print " Filename (include extension)<br> \n";
print " <em>ie. crowe.txt</em><br> \n";
print " <INPUT NAME=filename size=30><br> \n";


print " <input type=radio name=display value=txt>Plain Text \n";
print " <input type=radio name=display value=html>HTML<br> \n";
print " <INPUT TYPE=submit VALUE=Submit> \n";
print " <INPUT TYPE=reset VALUE=Clear> \n";

print " <br><br></font></font></b><br><br></CENTER> \n";
print " </TD></TR></TABLE></td></tr></table> \n";
&print_footer;

}




sub print_html {

&print_header;
open (CROWEFOO,"<$dir/$filename") &#0124; &#0124; die "Error Opening File. $!\n";
@somefile_in=<CROWEFOO>;
foreach (@somefile_in) {
print "<font size=2 face=verdana,arial>";
print $_ ;
print "<br>";
}
close (CROWEFOO);
&print_footer;
}




sub print_plain_txt {
&print_header;
open (CROWEFOO,"<$dir/$filename") &#0124; &#0124; die "Error Opening File. $!\n";
@somefile_in=<CROWEFOO>;
foreach (@somefile_in) {
$line_to_print = escapeHTML($_);
print "<font size=2 face=verdana,arial>";
print $line_to_print ;
print "<br>";
}
close (CROWEFOO);
&print_footer;
}







sub print_header {
open (CROWEHEADER,"<$header") &#0124; &#0124; die "Error Opening File. $!\n";
@header_in=<CROWEHEADER>;
foreach (@header_in) { print $_ ; }
close (CROWEHEADER);
}


sub print_footer {
open (CROWEFOOTER,"<$footer") &#0124; &#0124; die "Error Opening File. $!\n";
@footer_in=<CROWEFOOTER>;
foreach (@footer_in) { print $_ ; }
close (CROWEFOOTER);
}

------------------
The Crowe crowe@charter.net
www.lit.org Links Engine for Writing on the net!



Quote Reply
Re: Help with UN WEBIFY In reply to
Another suggestion:
Code:
$display = $in->param('display');
if ($display eq "plain") {
print "Content-type: text/plain\n\n";
}
elsif ($display eq "html") {
print "Content-type: text/html\n\n";
}
else {
#do nothing or say something
}
... and then you go like this:
/cgi-bin/script.cgi?dir=&filename=script.cgi&display=plain
Quote Reply
Re: Help with UN WEBIFY In reply to
Pahs1, bsumengen,

Yeah, that's what I had before and that is an easy way around it.. but I wanted to be able to do some html formatting to the output as well as do all the wrapping so it looks like the rest of my site. Call me silly but I want it to look good too.. Wink


Also, if anyone uses this script, be aware it is a HUGE security risk. They can view any file on your system, including /etc/passwd .. though it doesn't decrypt the passwords, it gives them the USERNAME..We all know the most common password is USERNAME Wink

I've built in a password routine to mine ( simple, but a start ) and I us .htaccess now though.



------------------
The Crowe crowe@charter.net
www.lit.org Links Engine for Writing on the net!



Quote Reply
Re: Help with UN WEBIFY In reply to
Oh, I see what you mean. In this case you should use the following code to replace < with &lt;
Code:
foreach $_ (@SOMEFILE_in)
{
if ($display eq "plain")
{
$_ =~ s/\</\&lt;/ig;
}
print "<font size=2 face=verdana,arial>";
print $_ ;
print "<br>";
}
just make sure to define $display Smile

[This message has been edited by Pasha1 (edited March 16, 2000).]
Quote Reply
Re: Help with UN WEBIFY In reply to
Pasha,

Thats exactly what I thought would do it, but couldn't remember how to format that line! But Mark beat you to it and since I'm using CGI.pm, his solution reqire less typng Wink

Here is how I did it with Mark's imput, for future refrence if you us CGI.pm, it sure makes it easy.

Code:

sub print_plain_txt {&print_header; open (CROWEFOO,"<$dir/$filename") | | die "Error Opening File. $!\n"; @somefile_in=<CROWEFOO>; foreach (@somefile_in) { $line_to_print = escapeHTML($_); print "<font size=2 face=verdana,arial>"; print $line_to_print ; print "<br>"; } close (CROWEFOO); &print_footer;}





------------------
The Crowe crowe@charter.net
www.lit.org Links Engine for Writing on the net!



Quote Reply
Re: Help with UN WEBIFY In reply to
Pasha:

Quote:
else {
#do nothing or say something
}

VERY bad form (the else do nothing part).

--mark

[This message has been edited by Mark Badolato (edited March 16, 2000).]
Quote Reply
Re: Help with UN WEBIFY In reply to
Just replace:
print "Content-type: text/html\n\n";

with:
print "Content-type: text/plain\n\n";

Quote Reply
Re: Help with UN WEBIFY In reply to
There's a bit in the script I would clean up.

This is UNTESTED, but looks ok on an initial view (but again, not tested so you may need to debug).

http://www.cybernox.com/scripts/db.txt

--mark

[This message has been edited by Mark Badolato (edited March 16, 2000).]
Quote Reply
Re: Help with UN WEBIFY In reply to
Wow, that code is compact. I'll remember to use trap fatals to browser next time I write a script.

I just tested yours and it works fine for txt but the html doesn't fly .. Not sure why yet. Still, The code is very compact. Nice logic. I'll have to study this script.

Any reason you chose my $var? Is it just because of prefrence? Or just that its a short script and the variables will remain local to this small amount of code?

The way you shortened the header and footer routine is pretty awesome. I will put that bit of code in my ref file!

One other question abour your script vs mine. When I used the escapeHTML code, I had to add it to the top of the script in the use CGI statement, Your statements are different, and though I recognize them, I don't understand the difference.

Other than that, your script really shows some great short cuts in repetitive code. In every language I've ever programmed in, I always found the LONG way to do something first, which I guess is a good learning experience!

Thanks again for your help Mark. You know your just feeding the fire here. I'm just going to write more buggy code to post!!





------------------
The Crowe crowe@charter.net
www.lit.org Links Engine for Writing on the net!



Quote Reply
Re: Help with UN WEBIFY In reply to
 
Code:
if ($display eq 'txt') {
print '<font size=2 face=verdana, arial>', $in->escapeHTML($_), '<br>' foreach @file_in;
} else {
print "<font size=2 face=verdana, arial>$_<br>" foreach @file_in;
}

Quote:
Any reason you chose my $var? Is it just because of prefrence? Or just that its a short script and the variables will remain local to this small amount of code?

because of the use strict; pragrma. Essentially, all variables need to be declared (that's an overly simple defination of what it actually does)

Quote:
The way you shortened the header and footer routine is pretty awesome. I will put that bit of code in my ref file!

heh, standard modualization. thats the whole purpose of subroutines.

Quote:
One other question abour your script vs mine. When I used the escapeHTML code, I had to add it to the top of the script in the use CGI statement, Your statements are different, and though I recognize them, I don't understand the difference.

What you did was import the particular function into your script (which frankly, I didn't even realize that could potentially work!). Since use CGI; was already being defined, you had the function available anyway. Simply call the function with the text you want escaped:

print $in->escapeHTML('what><ever');

in this script's case, the contents of $_ are being passed to escapeHTML();

Quote:
Other than that, your script really shows some great short cuts in repetitive code. In every language I've ever programmed in, I always found the LONG way to do something first, which I guess is a good learning experience!

Heh, yup. It sometimes does help to do the long way out, and fully understand it, then find the short-cuts or better style or whatever.

Plus, you get to sing the Programmer's National Anthem, which goes like this:

"AHHHHHHHHHHHHHHHHHHH HAAAAAAAAAAAAAAAAAAAA!!!!!"

Smile

--mark

Thanks again for your help Mark. You know your just feeding the fire here. I'm just going to write more buggy code to post!!
Quote Reply
Re: Help with UN WEBIFY In reply to
BTW, this was a quick run. There are other little things I would optimize in there.

Like, in the print_standard routine, there really is no need to read the file into an array first before printing it.

Some tighter security etc.

Smile

--mark
Quote Reply
Re: Help with UN WEBIFY In reply to
Dammit, anal retentiveness and a strange need to do things more cute (perlish), caused me to work on this some more.

So now, same link, but the file is slightly different. No more reading into an array. Also, the "cuteness" is the $printer stuff in the print_it routine Smile

--mark
Quote Reply
Re: Help with UN WEBIFY In reply to
WoW!!!

You either liked the idea of this script or have become really bored! Either way I'm glad! I noticed your change, went back when I got home and you had changed it again! lol

I was going to ask you about restricting directories! I do have more questions now though, about some things you did. I think I get the gist of most of it, thank god!

First, this bit.
Code:
my $in = new CGI;
my $header = "header.html";
my $footer = "footer.html";
my $dir = $in->param('dir');

Why is my $dir using the param and the others not? I assume it has something to do with accessing it for the allowed directories, but not sure why you define this one this way and not $file also.

I understand the grep statement pretty well.. psuedo code here "die unless thisdirhere is in thisallowedlisthere" .. and before it print $in->header; just calles CGI.pm's Default text/html header ??


Now, this:
Code:
($in->param('display') =~ /^(txt|html)$/) ? print_it($in->param('display'), $dir, $in->param('filename')) : &print_form;

Could you tell me a little more about how this line works. why =~ /^ .. I see this alot in perl when pattern matching etc. Also, I guess this may answer my first question. Why not pre-assign $filename beforet his point. You do it inline here.

The line before and after is the header/footer calls. I get that part. Does the =~ sort of act like the if/then code. It seems this 3 line bit tells the script what to do. If txt/html print stuff, if not, print the form. Am I right? If so I understand why my form has the header and footer, if not, I don't know where it gets the calls from! Wink

Now, the print_it sub
Code:
sub print_it {
my ($display, $dir, $file) = @_;
my $printer = 'print "<font size=2 face=verdana, arial>$_<br>";';

$printer =~ s/(\$_)/", \$in->escapeHTML($1), "/ if ($display eq 'txt');

open (MYFILE, "$dir/$file") &#0124; &#0124; die "Error Opening File $file. Reason: $!\n";
eval $printer while (<MYFILE> );
close (MYFILE) or die "Error Closing File $file. Reason: $!\n";
}

The first line with the 3 $var's in it, I guess assings the value to $_ ?? (the $@)??

What about the two $printer lines? I thought using the same var name would over right the current info? And here we go with = and =~ .. How's that work? I know you can add when you use qq~ .. but this doesn't seem quite the same.

This line
Code:
$printer =~ s/(\$_)/", \$in->escapeHTML($1), "/ if ($display eq 'txt');
is the second one with the nice s/ etc crazy characters. Though my massive collection of perl books is pretty, without me know exactly what I'm looking for, I don't know what I'm seeing Wink Hey, I'm new!


I understand the loops in both sub routines. ( nice short cut btw! ) What I don't get though, is the eval in print_it sub. Is it eval'ing by the situation you gave it when you defined $printer?

One last question, I think. In print_standard you have use shift. What does that do?

Please, if your busy, don't worry about these questions! But if you got time, I apprecaite the answers. And maybe one day when I can program, I'll be able to return the favor to someone. ( And maybe find a way to repay you for your excellent advice and ideas! )

This stuff is just fun. I love perl.






------------------
The Crowe crowe@charter.net
www.lit.org Links Engine for Writing on the net!



Quote Reply
Re: Help with UN WEBIFY In reply to
heh, yup. Boredom has it's finest moments... Smile

Quote:
Why is my $dir using the param and the others not? I assume it has something to do with accessing it for the allowed directories, but not sure why you define this one this way and not $file also.

Because the value is used in a regex a few lines down. The regex could have problems with $in->param('dir'); so it is easier to just define it, then use a regular scalar in the regex.

I don't do it with $file because that one isn't used anywhere like $dir. No point in assigning another variable when $in->param('file') will work just fine. Plus, the variable DOES get assigned when it gets to the print_it routine (as a local var).

Quote:
I understand the grep statement pretty well.. psuedo code here "die unless thisdirhere is in thisallowedlisthere" .. and before it print $in->header; just calles CGI.pm's Default text/html header ??

correct on both counts.

Quote:
($in->param('display') =~ /^(txt|html)$/) ? print_it($in->param('display'), $dir, $in->param('filename')) : &print_form;

Could you tell me a little more about how this line works. why =~ /^ .. I see this alot in perl when pattern matching etc. Also, I guess this may answer my first question. Why not pre-assign $filename beforet his point. You do it inline here.

Regular pattern matching. Telling it do look at the value passed in to param('display'). If it matches txt or html, go to print_it, otherwise go to print_form.

basically: expr ? true : false;

evaluate the expression, do the first if the expresssion is true, second if is false.

As for the pattern itself:

$in->param('display') =~ /^(txt|html)$/

=~ means pattern matching. / is the deliminator (notice one at the beginning, one at the end. kind of like quotes). if the standard / delimiter is used then =~ is fine. If you have slashes in your regex, you can use a different delimiter so that the slashes won't need to be escaped. In that case, you have to use m to specify matching. For instance:

$in->param('display') =~ m,^(txt|html)$,
or
$in->param('display') =~ m!^(txt|html)$!
or
$in->param('display') =~ m#^(txt|html)$#
etc.

The ^ means "the very beginning of the string" and the $ means "the very end". (but, they can mean other things too, you really need to read about regex's).

so ^(txt|html)$ means the pattern must start right at the beginning of the string, and either be followed by txt or html, then immediedly end the string. This way, "text", "htm" etc are not valid.

Quote:
The line before and after is the header/footer calls. I get that part. Does the =~ sort of act like the if/then code. It seems this 3 line bit tells the script what to do. If txt/html print stuff, if not, print the form. Am I right? If so I understand why my form has the header and footer, if not, I don't know where it gets the calls from!

Sort of right! Basically, since you always print the header and footer, no matter what routine you go to, no point in reduntantly putting those calls in the routine. Always call the header, then to the ? : line to determine which subroutine to branch to (print_it, or print_form), then always print the footer. simple! Smile The 3 lines are not acting together.

the ? : line, is sort of like an if statement thoguh.

Quote:
The first line with the 3 $var's in it, I guess assings the value to $_ ?? (the $@)??

see up in the ? : statement where we call print_it with: print_it($in->param('display'), $dir, $in->param('filename')) ? We're passing three values to the subroutine.

The line you are asking about assigns the values passed to local variables in the subroutine for use in our operations.

@_ is kind of like $_ except an array instead of a scaler. so if you pass print_it(1, 2, 3);

in the subroutine

($a, $b, $c) = @_;

would assign 1 to $a, 2 to $b etc...

Quote:
What about the two $printer lines? I thought using the same var name would over right the current info? And here we go with = and =~ .. How's that work? I know you can add when you use qq~ .. but this doesn't seem quite the same.

Heh, this is where I was having fun with perl. Basically, if you are printing html, nothing needs to be done excpt print out the font tags around $_ while going though the file.

When printing txt, it's the exact same thing excet you want $_ html-escaped.

So, I assigned $printer to be the default output (along with a print statement...cuz of the eval).

Then this line:

$printer =~ s/(\$_)/", \$in->escapeHTML($1), "/ if ($display eq 'txt');

is doing a regex substitution. basically, if $display equals "text", replace $_ with $in->escapeHTML($_) (plus the " and , because of the formating that i want).

the \ inf front of $_ is because i want a literal $, and not the "end of string" position as explained above. then in the second part of the substitition, I use $1, which means the value of whatever matched in the first set of parentheses (notice the \$_ is in parenthesis). Again that sounds confusing, and you need to read up on regexes.

Substituitns are: =~ s/substutuite this/with this/; (and the i means case insensitive).

Quote:
What I don't get though, is the eval in print_it sub. Is it eval'ing by the situation you gave it when you defined $printer?

YES!

$printer will contain one of two strings. Either:

print "< font size=2 face=verdana, arial >$_< br >";

or

print "< font size=2 face=verdana, arial >", $in->escapeHTML($_), "< br>";

the word print is included in the string inside $printer. Also notice that I contained printer's string in single quotes, because I am using double quotes in the value inside printer (the print "<font etc")

You already know about looping and using $_ to mean "the one im on right now". well, I do the loop, but eval $printer.

What happens is, eval gets executed so literaly: print "< font blah blah blah> $_" gets executed!! (neat, eh?! Hope that made sense).

Quote:
One last question, I think. In print_standard you have use shift. What does that do?

In this instance, again assigns the value that was passed, to the local variable. @_ could have been used (or @_[0] for that matter) but since it was only one value, shift is fine.

Likewise, earlier I could have done:

$display = shift;
$file = shift;
$dir = shift;

but as you see, no need.

*whew* you are making me type today! Smile

anyway, hope that helps!

--mark


Quote Reply
Re: Help with UN WEBIFY In reply to
Ok, one last change and i'm DONE! Smile

Decided to play in the print_form routine.

cleaned it up (was some unnecessary html in there). also made it print using all CGI.pm methods, though it was unnecessary (most people dont use CGI.pm for stuff like tables. I felt like playing).

And, made it so the directory box gives a dropdown of acceptable directories, instead of asking them to type it in.

Added proper start and end html stuff to output pages.

done. I'm not bored anymore Smile Smile

--mark
Quote Reply
Re: Help with UN WEBIFY In reply to
Why not display it inside a frame?
Quote Reply
Re: Help with UN WEBIFY In reply to
Mark,

The new version looks pretty cool. I like the drop down box, sweet. But, it doesn't have the trailing / on it Wink Easy to fix.

The script works great, except if you press text, it just displays the form, and if you press html, it just displays the form.. lol. I'll try to debug it tonight when I get home. Thanks again for all your help! Breaking down the script for me really helped me alot. I'm going to buy Mastering Reg Ex next time I get to the bookstore. Seems that is the heart of perl and what I'll be trying to do!

bsumengen,

That would be easy enough. I assume you mean just put the form in one screen and the output in the other frame. Not really a problem. It would be easy enough to HARD CODE the form in html, but as you can see with Mark's new code, you can do cool dynamic stuff with running it from cgi. I could use the cgi and do it frame'd as well. Using files to "save state" from one form to the next. But I like it how it is Wink don't really need frames.

I will however be adding a link to the footer routine to print "return to the script" url Wink



















------------------
The Crowe crowe@charter.net
www.lit.org Links Engine for Writing on the net!



Quote Reply
Re: Help with UN WEBIFY In reply to
If you email me a link to where you are running the file, I can look to. I need to see what is happening (i have not even run this locally as a test)

--mark