Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > search.pl

Reply
Thread Tools

search.pl

 
 
Robin
Guest
Posts: n/a
 
      04-30-2004
I have some questions on this , why isn't sub parse and sub search not
performing the way I want them too, they are supposed to go through all of
the directories and then open the files in them and then if the contents of
the file match param ('query') print the results. It's been driving me
crazy, if someone could point me in the right direction it would be great.
This is very incomplete and doesn't use all of it's data yet, so I would
appreciate comments that don't point that out, for example, what if it opens
binary files? I dunno..thanks in advance, by the way, I know that it's
somewhere in the methods search or parse, but other than that I don't have
the foggiest.

-Robin


#!/usr/bin/perl

use strict;
use warnings;

use Fcntl qw (:flock);

use CGI qw(:all);

$CGI:OST_MAX=1024 * 100; # max 100K posts
$CGI:ISABLE_UPLOADS = 1; # no uploads

$" = '';

$ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin';

my @directories = ("./", "../", "../design"); #change this to the
directories you want to have searched.
my $action = url_param ('action');
my $rootfile = url (relative=>1);
my $headerfile = "searchheader.txt";
my $footerfile = "searchfooter.txt";
my $errorfile = "ERR.txt";
my @head = getheader ($headerfile);
my @foot = getfooter ($footerfile);
my $date = getdate ();
my @errors;

if ($action eq "search")
{
search ();
}

else
{
newsearch ();
}

sub search
{
print header;
print (@head);
print <<END;
<p><strong><em>Infused Search</em></strong>
<br>
<br>
Search Results:
</p>
END
#code for parsing results
foreach my $dir (@directories)
{
opendir (DIR, $dir);
my @files_from_dir = readdir (DIR);
closedir (DIR);
foreach my $file (@files_from_dir)
{
if (! -d $file)
{
parse ($file, $dir);
}
}
}
print <<END;
<hr size="1">
</body>
</html>
END
}

sub parse
{
my ($filetoparse, $dirtoparse) = @_;
my @results;
open (FILE, $filetoparse) or push (@errors, "A file open operation
failed.");
flock (FILE, LOCK_SH) or push (@errors, "A file lock operation
failed.");
my @filecontents = <FILE>;
close (FILE);
chomp (@filecontents);
my $result;
my $filecontents = join ('', @filecontents);
if (param ('query') =~ /$filecontents/m and param ('query'))
{
$result = $filetoparse;
print "<a href=\"$dirtoparse" . "$filetoparse\">$result</a><br>";
}
}

sub newsearch
{
print header;
print (@head);
print <<END;
<strong><em>Infused Search</em></strong>
<br>
<br>
<hr size="1">
<form name="form1" method="post" action="search.pl?action=search">
<input type="text" name="query">
<input type="submit" name="Submit" value="Submit">
</form>
<hr size="1">
END
print (@foot);
}

sub checkerrors
{
if (@errors)
{
print header;
print "<html><body><center>";
print "There were errors while trying to execute Infused Search. They
are listed as follows.<br><br>\n";
foreach my $error (@errors)
{
print ($error, "<br>\n");
}
my $errflag = 0;
if (! open (ERRORF, ">>$errorfile") and flock (ERRORF, LOCK_EX))
{
print "There was an error logging the errors: file cannot be locked or
opened.<br>";
$errflag = 1;
}
else
{
print ERRORF ("Current date: $date", "\n");
foreach my $error2 (@errors)
{
print ERRORF $error2, "\n";
}
}
close (ERRORF);
if (! $errflag)
{
print "<br>", "Errors have been logged in $errorfile.";
}
print "</body></html>";
exit (0);
}
else
{
return;
}
}

sub getheader
{
my $header_sub = shift;
my (@headertoret);
if (-e $header_sub)
{
open (HEADERF, $header_sub);
flock (HEADERF, LOCK_SH);
@headertoret = <HEADERF>;
close (HEADERF);
}
else
{
open (HEADERF, ">$header_sub");
flock (HEADERF, LOCK_EX);
@headertoret = <<END;
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Untitled Document</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css">
<!--
body,td,th {
color: #FFA4A4;
}
body {
background-color: #000000;
}
a:link {
color: #66FFFF;
}
a:visited {
color: #66FFFF;
}
a:hover {
color: #FF9933;
}
a:active {
color: #66FFFF;
}
-->
</style></head>

<body>
END
print HEADERF @headertoret;
close (HEADERF);
}
return (@headertoret);
}

sub getfooter
{
my $footer_sub = shift;
my (@footertoret);
if (-e $footer_sub)
{
open (HEADERF, $footer_sub);
flock (HEADERF, LOCK_SH);
@footertoret = <HEADERF>;
close (HEADERF);
}
else
{
open (HEADERF, ">$footer_sub");
flock (HEADERF, LOCK_EX);
@footertoret = <<END;
</body></html>
END
print HEADERF @footertoret;
close (HEADERF);
}
return (@footertoret);
}

sub getdate
{
my ($day, $mon, $year)=(localtime)[3,4,5];
$mon++;
$year +=1900;
my $date = $mon . "/" . $day . "/" . $year;
return $date;
}



 
Reply With Quote
 
 
 
 
Sherm Pendley
Guest
Posts: n/a
 
      04-30-2004
Robin wrote:

> I have some questions on this , why isn't sub parse and sub search not
> performing the way I want them too, they are supposed to go through all of
> the directories and then open the files in them and then if the contents
> of the file match param ('query') print the results. It's been driving me
> crazy, if someone could point me in the right direction it would be great.


Your script passes the directory to parse(), but it doesn't look like
parse() is using it. So any file that isn't in the current directory ('./')
won't get parsed.

> open (FILE, $filetoparse) or push (@errors, "A file open operation
> failed.");


You should be using more helpful error messages. The above tells you nothing
more than that a file failed to open - it would be better if it also told
you what file and why. Including the file name and $! would make this bug
easier to find.

sherm--

--
Cocoa programming in Perl: http://camelbones.sourceforge.net
Hire me! My resume: http://www.dot-app.org
 
Reply With Quote
 
 
 
 
GreenLight
Guest
Posts: n/a
 
      04-30-2004
"Robin" <webmaster @ infusedlight . net> wrote in message news:<c6st0v$3de$(E-Mail Removed)>...
> #code for parsing results
> foreach my $dir (@directories)
> {
> opendir (DIR, $dir);
> my @files_from_dir = readdir (DIR);
> closedir (DIR);
> foreach my $file (@files_from_dir)
> {
> if (! -d $file)
> {
> parse ($file, $dir);
> }
> }
> }


Do you really indent your code like that, or is this just an artifact of
whatever utility that you use to post to clpm? That is so painful to look at
that I cannot even consider analyzing it to help you with your problems...

--
my real address is perl - at - milbaugh - dot - com
 
Reply With Quote
 
Mark Clements
Guest
Posts: n/a
 
      04-30-2004
GreenLight wrote:

> "Robin" <webmaster @ infusedlight . net> wrote in message news:<c6st0v$3de$(E-Mail Removed)>...

<snip>
> Do you really indent your code like that, or is this just an artifact of
> whatever utility that you use to post to clpm? That is so painful to look at
> that I cannot even consider analyzing it to help you with your problems...


Robin: you could do with looking at templating solutions, eg
HTML::Template or Template-Toolkit (though there are a fair number out
there and people tend to have strong opinions about choice of templating
package). Embedding HTML ie presentation and content directly within a
script makes it hard to read and hard to maintain. It also makes it very
difficult to work with web designers who may not have any knowledge of
Perl.

As far as the indenting goes, check out perltidy.

Mark
 
Reply With Quote
 
David K. Wall
Guest
Posts: n/a
 
      04-30-2004
Robin <webmaster @ infusedlight . net> wrote:

> I have some questions on this , why isn't sub parse and sub search
> not performing the way I want them too, they are supposed to go
> through all of the directories and then open the files in them and
> then if the contents of the file match param ('query') print the
> results. It's been driving me crazy, if someone could point me in
> the right direction it would be great.


use File::Find;

Writing your own code to recurse through directories is a useful
exercise, but if you just want to get the program written and use it,
File::Find is faster and easier to use, and almost certainly more
robust.

I'd also suggest not printing the results immediately, but save them
somewhere (possibly in an array of some sort, maybe of hashes) and
only print them out when the search has finished.

And please, *please*, format your code in a readable way. perlstyle
has suggestions. You don't have to follow them exactly, but at least
pick a style and use it *consistently*. If I didn't have perltidy
available to reformat your code I would not have even bothered to
skim over it. If you don't have an editor that assists with
indenting, then get one.


> sub parse
> {
> my ($filetoparse, $dirtoparse) = @_;
> my @results;
> open (FILE, $filetoparse) or push (@errors, "A file open
> operation failed.");


So if the open fails, save a non-informative message in an array
(which file? why did it fail?) ...

> flock (FILE, LOCK_SH) or push (@errors, "A file lock operation
> failed.");
> my @filecontents = <FILE>;


....and then try to read it anyway.

> close (FILE);
> chomp (@filecontents);


....and then do other stuff with an empty array.


Hmmm...

[I got tired at this point and stopped reading]
 
Reply With Quote
 
Michele Dondi
Guest
Posts: n/a
 
      04-30-2004
On Thu, 29 Apr 2004 22:50:38 -0800, "Robin" <webmaster @ infusedlight
.. net> wrote:

>I have some questions on this , why isn't sub parse and sub search not
>performing the way I want them too, they are supposed to go through all of
>the directories and then open the files in them and then if the contents of
>the file match param ('query') print the results. It's been driving me


I have not read your code, but I seemed to notice some readdir()s so
from what is described above I feel like pointing out that the
standard answer -and indeed generally a good one!- to this kind of
questions is 'use File::Find'. Maybe you knew, maybe you don't: if you
didn't, it's there for your ease!


Michele
--
you'll see that it shouldn't be so. AND, the writting as usuall is
fantastic incompetent. To illustrate, i quote:
- Xah Lee trolling on clpmisc,
"perl bug File::Basename and Perl's nature"
 
Reply With Quote
 
Joe Smith
Guest
Posts: n/a
 
      04-30-2004
Robin wrote:

> opendir (DIR, $dir);
> my @files_from_dir = readdir (DIR);
> closedir (DIR);
> foreach my $file (@files_from_dir)
> {
> if (! -d $file)
> {
> parse ($file, $dir);
> }
> }
> }


1) You really messed up on the indentation there.
2) Your main logic error is in the argument to -d() and parse(); it's
incomplete. Anytime $dir is not the same as ".", your code will fail.

foreach my $fil (@files_from_dir) {
my $file = "$dir/$fil";
parse($file,$dir) if -f $file;
}

-Joe
 
Reply With Quote
 
Tassilo v. Parseval
Guest
Posts: n/a
 
      04-30-2004
Also sprach Michele Dondi:

> On Thu, 29 Apr 2004 22:50:38 -0800, "Robin" <webmaster @ infusedlight
> . net> wrote:
>
>>I have some questions on this , why isn't sub parse and sub search not
>>performing the way I want them too, they are supposed to go through all of
>>the directories and then open the files in them and then if the contents of
>>the file match param ('query') print the results. It's been driving me

>
> I have not read your code, but I seemed to notice some readdir()s so
> from what is described above I feel like pointing out that the
> standard answer -and indeed generally a good one!- to this kind of
> questions is 'use File::Find'. Maybe you knew, maybe you don't: if you
> didn't, it's there for your ease!


As far as I could see, he is not recursing further into subdirectories.
For ordinary directory listings, I'd use readdir() alright.

Tassilo
--
$_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus}) !JAPH!qq(rehtona{tsuJbus#;
$_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexi ixesixeseg;y~\n~~dddd;eval
 
Reply With Quote
 
David K. Wall
Guest
Posts: n/a
 
      04-30-2004
Tassilo v. Parseval <(E-Mail Removed)> wrote:

> Also sprach Michele Dondi:
>
>> On Thu, 29 Apr 2004 22:50:38 -0800, "Robin" <webmaster @
>> infusedlight . net> wrote:
>>
>>>I have some questions on this , why isn't sub parse and sub
>>>search not performing the way I want them too, they are supposed
>>>to go through all of the directories and then open the files in
>>>them and then if the contents of the file match param ('query')
>>>print the results. It's been driving me

>>
>> I have not read your code, but I seemed to notice some readdir()s
>> so from what is described above I feel like pointing out that the
>> standard answer -and indeed generally a good one!- to this kind
>> of questions is 'use File::Find'. Maybe you knew, maybe you
>> don't: if you didn't, it's there for your ease!

>
> As far as I could see, he is not recursing further into
> subdirectories. For ordinary directory listings, I'd use readdir()
> alright.


Yeah, you're right. I didn't look closely enough either.

 
Reply With Quote
 
Robin
Guest
Posts: n/a
 
      04-30-2004

"Sherm Pendley" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Robin wrote:
>
> > I have some questions on this , why isn't sub parse and sub search not
> > performing the way I want them too, they are supposed to go through all

of
> > the directories and then open the files in them and then if the contents
> > of the file match param ('query') print the results. It's been driving

me
> > crazy, if someone could point me in the right direction it would be

great.
>
> Your script passes the directory to parse(), but it doesn't look like
> parse() is using it. So any file that isn't in the current directory

('./')
> won't get parsed.


parse uses the directory when the link is printed out.

> > open (FILE, $filetoparse) or push (@errors, "A file open operation
> > failed.");

>
> You should be using more helpful error messages. The above tells you

nothing
> more than that a file failed to open - it would be better if it also told
> you what file and why. Including the file name and $! would make this bug
> easier to find.


yes, this is my first draft and I haven't really worked in the error
checking routine, but I will....

-Robin


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off




Advertisments