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

I am beginning to think I am going about this all wrong. My news script makes me happy. Any client can use the form to update their pages. The script writes new table rows to a txt file (used later as an SSI)and delimits each entry with 3 newlines. Currently clients edit via a script which makes a form with a text area containing the whole contents of the text file, HTML and all. They complain that it is hard to see which post they want to delete or edit due to the HTML. So I have, with help from Physi and others, made the script below whose output looks like this.

Problem is that I can't figure how to identify the post to be deleted via the checkboxes. Should I be thinking line numbers and use seek to excise the selected bits? I tried making the checked value of each button eq $_ (whose value creates the contents of the nested table next to the checkbox, but that made the script go crazy.

Advice on high level logic most welcome, I'm not asking for a code handout, but maybe a map on a cocktail napkin?
TIA
jg

#!/usr/bin/perl -w use strict; use CGI; use CGI ':standard'; use CGI::Carp qw/fatalsToBrowser /; my $q = CGI->new(); my $path_to_text="/home/nolaflash/www/exp/news/body.txt"; my $post_number; print header; #only just beginning to work out using standard print "<HTML><BODY><center>"; print "<form method=post action=http://www.nolaflash.com/cgi-bin/editi +ngscript.pl>\n"; print "<TABLE width=600>"; print "<TR bgcolor=#000066><TD colspan=2 align=center><font color=#ff +ffff>"; print "<h2>Edit Your Posts</h2></font></TD>"; open (FH, "$path_to_text") or die "where's the damn file? : $!"; $/="\n\n"; #set the input Record seperator to + a double newline while (<FH>) { next if /^\n+$/; #ignore lines which contains only +newlines $post_number++; print "<TR><TD valign=top>Delete This Post?<input type=checkbox name +=box$post_number value=onepost> </TD>\n"; print "<TD><table width=295><TR><TD>$_\n"; #print the textblock in +a nested table with an ... print "</TD></TR></TABLE></TD></TR>\n"; print "<TR bgcolor=#000066><TD colspan=2>&nbsp;</TD>"; #appending +darkline print "</TR>\n"; } close FH; print "<TR bgcolor=#333333><TD align=center colspan=2><input type=subm +it name=Submit value=\"Delete Checked Posts\"></TD>"; print "</form></center></table></body></html>"; exit;
_____________________________________________________
If it gets a little bit out of hand sometimes, don't let it fool you into thinkin' you don't care.TvZ

Replies are listed 'Best First'.
(cLive ;-) Re: Working on Deleting Sections of Text File Delimited by Newlines
by cLive ;-) (Prior) on Nov 27, 2001 at 11:23 UTC
    Errr... something that springs to mind is that you create a cgi object $q (lovely), and then proceed to ignore it and do all your HTML by hand. wtf (that's why, not what :-). I suggest you read the CGI docs and maybe take a look at a couple of my recent posts.

    Anyway, apart from that (slap), if you insist on hand crafting inputs, please ="quote values" - you'll understnad why if you ever have a value that contains a space!

    You say 3 lines is the delimiter, so why:

    $/="\n\n"; # instead of $/="\n\n\n";
    ?

    OK, a few more notes. Here's how I'd parse (without rewriting this massively ;-)

    if ( $q->param() ) { open (FH, "$path_to_text") or die "where's the damn file? : $!"; # also set this in earlier part to match $/="\n\n\n"; #set the input Record seperator to a TPIPLE newline my @updated_text; while (<FH>) { next if /^\n+$/; #ignore lines which contains onl +y newlines $post_number++; # ignore deleted next if ( $q->param("box$post_number") ); # keep the rest push @updated_text, $_; } close(FH); # now update file open(FH,">$path_to_text") || die $!; print FH join "\n\n\n", @updated_text; close(FH); # show success here... }

    hth

    cLive ;-)

      please ="quote values"

      Here here! Never mind that it's the osking standard. They technically have to be there, yes yes prior to xHTML you were legally allowed to be lazy if your value was purely alpha-numeric. And no ' (tick) doesn't count.

      --
      perl -p -e "s/(?:\w);([st])/'\$1/mg"

Re: Working on Deleting Sections of Text File Delimited by Newlines
by boo_radley (Parson) on Nov 27, 2001 at 11:39 UTC
    print "<HTML><BODY><center>"; print "<form method=post action=http://www.nolaflash.com/cgi-bin/editi +ngscript.pl>\n"; print "<TABLE width=600>"; print "<TR bgcolor=#000066><TD colspan=2 align=center><font color=#ff +ffff>"; print "<h2>Edit Your Posts</h2></font></TD>";
    why are you using CGI again?
    Stop.
    Get the mouse book. Or this one. Yes, they cost some money. Suck it up -- sometimes you gotta pay to play. Alternately, pore over the POD until you know it backwards and forwards.

    Your checkboxes should be named box1.. boxn. How does this cause the script to break? These parameters will be available through CGI. .
    It is not required to create a cgi object if you're going to use CGI ":standard". Use one or the other.
    Your HTML is badly formatted compared to CGI -- if you insist on not using CGI for output (which is fine, if you know why) then remember that html code should be lower case, and all of the attributes should be quoted.
    Seeing this : "All HTML tags are supported!" in your web board made my eyes roll in the back of my head. Are you filtering out javascript? what about object tags? there's a lot of maliciousness you're opening yourself up to here. Try allowing a small range of allowed tags rather than any old thing.

      there's a lot of maliciousness you're opening yourself up to here.

      Particularly if executable SSIs are switched on. Allows the user to execute any command, I would think.

      andy.

Re: Working on Deleting Sections of Text File Delimited by Newlines
by jarich (Curate) on Nov 27, 2001 at 16:39 UTC
    I agree that you should either use the CGI module or not use it but not include it and then ignore it. I was going to say something along the lines of you should name all of your checkboxes the same and then just cycle through the values, but when I considered the code snippet below, that didn't work as well.... but often you should do that.

    Now I suspect that you're not asking about how to generate this form, but what to do with it after submission... as in how can you remove the actual posts from your file. You said that your file is separated by newlines. The easiet way - that I can see - to modify your file is to read it all in, change it and then write it out again. (just make sure that it won't ever be too huge). So... something like:

    $/ = ... # whatever my @posts = <FH>; # read all posts in at once and assign # each to an array element. my @keep_posts; for(my $index = 0; $index < @posts; $index++) { unless(defined($cgi->param("box$index")) { push @keep_posts, $posts[$index]; } } # open file... print all the kept ones out. print NEW_FILE join("\n\n\n", @keep_posts);
    should do the trick nicely.

    If this wasn't what you wanted, please ask again.

    update After actually reading cLive ;-)'s post I feel silly for saying much the same thing. His way has the definate advantage of not needing to read the entire thing into memory, just handling it post by post. That's probably the better approach.

(joealba) Re: Working on Deleting Sections of Text File Delimited by Newlines
by joealba (Hermit) on Nov 27, 2001 at 20:08 UTC
    I prefer writing out my HTML over using CGI.pm to write it -- primarily because when I'm not using templates, I often copy/paste from Dreamweaver (my favorite WYSIWYG HTML editor).

    But, I use the lovely qq() tag so I can format my code nicely. I'm anal when it comes to my code. :)
    print qq( <TR> <TD valign="top">Delete This Post? <input type="checkbox" name="box$ +post_number" value="onepost"></TD> <TD> <table width="295"> <TR> <TD>$_</TD> </TR> </TABLE> </TD> </TR> <TR bgcolor="#000066"> <TD colspan="2">&nbsp;</TD> </TR> );
    As for your question, I'd think about delimiting your records differently to make it easier to know which record you want to delete. I'd use HTML comments.
    <!MESSAGE 1006873233> This is my message. There are many like it, but this one is mine. <!/MESSAGE 1006873233>
    You could certainly expand those comments out to the more standard format: <!-- MESSAGE 1006873233 -->. But, I intentionally wrote it the other way because that's how I use it.. and I was hoping someone might see that and say "HEY, STUPID! That's really bad because..." Then I can waste a day and go run Perl code to change all 30000+ of these comments on my site.