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

I have this script which takes input from a user-specified file parses it into a set of arrays
and then prints up a table with the relevant information.

I now want to allow the user to add and or remove entries. I have the table print out and underneath
it a form into which the user will enter the info to add or remove.

Here's where the problem is, I have yet to figure out a good way to pass all the original info through
to the next instance of the script. I thought that I could read out all the array elements into the form
as hidden elements but I hope that there is an easier way to do it.

I also thought of reading the arrays into a text file but the file never got written into. I was using this code:

open ORGIDATA, ">orig" || die "Couldn't open! $!"; for (my $k = 0; $k < @classid; $k++) { if ($classid[$k] != $classid[$k-1]) { print ORIGDATA $classid[$k], " ", @{$class[$k]}, " ", $location +[$k], " ", $credits[$k], "<br>\\ n"; } } close ORGIDATA;
This code didn't touch the file at all (i.e. not only not written into but not clobbered either).
Any advice would be appreciated. I'm open to fixes of my code, reasons it didn't work, suggestions as to better ways of doing it, anything.
Thanks in advance for all help.

Replies are listed 'Best First'.
Re: Keeping form information in CGI
by tachyon (Chancellor) on Jul 03, 2001 at 11:21 UTC

    Writing the data to a file is one way to do it. Your problem is the open statement and the issue of precedence. You need parentheses like this:

    open (ORGIDATA, ">orig") || die "Couldn't open! $!";

    This will work although it is usually wise to specify a path when you open a file even if it is ./ just so you know where to look for the file. You can write it like you did if you use 'or' instead of '||'

    open ORGIDATA, ">orig" or die "Couldn't open! $!";

    Because the || operator binds tighter than the comma what you had was seen by perl as

    open ORGIDATA, (">orig" || die "Couldn't open! $!");

    whereas the comma binds tighter than or. This is a really common problem until you work out what is going on. By the way your 'if ($classid[$k] != $classid[$k-1])' compares the first element to the last element of your array when $k=0 as $k-1 = -1 and -1 is the index of the last element. I presume the @classid contains numbers only as you are using the numeric comparator. If they are strings you will need 'ne'. I only mention this because when I was new to perl it took a bit of getting used to vis:

              numeric    string
    equality    ==         eq
    inequality  !=         ne
    sorting    <=>         cmp

    Whoops getting side tracked. Hope this helps.

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n\w+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Re: Keeping form information in CGI
by Zaxo (Archbishop) on Jul 03, 2001 at 11:59 UTC

    Regarding your code, tachyon has said it, no need to repeat.

    I suggest using CGI.pm, if you aren't already. That will solve your persistence problem, since re-invocations of the script automatically get the current cgi param=val pairs as hidden fields. The CGI pod calls these "sticky". You should treat this data as tainted.

    After Compline,
    Zaxo

    Update: Reply to deryni, CGI.pm places all the current cgi data gathered in the next form written as hidden fields. I believe that only happens if the form action refers to the current script. 'man CGI' and search for 'sticky', 'hidden', and see the section on urls.

Re: Help already received and request for more
by deryni (Beadle) on Jul 03, 2001 at 13:40 UTC
    First off, yes, tachyon the values in @classid are only numbers, but thank you for your vigilance.

    On a seperate and, I think, somewhat odd note I noticed that whatever I do after I have the open ORGIDATA, ">orig" || die "Couldn't open! $!"; line doesn't happen (i.e. prints don't print etc.). I'm completely baffled as to why.

    For example modifying the above code to this:

    open ORGIDATA, ">orig" || die "Couldn't open! $!"; for (my $k = 0; $k < @classid; $k++) { if ($classid[$k] != $classid[$k-1]) { print $classid[$k], " ", @{$class[$k]}, " ", $location +[$k], " ", $credits[$k], "<br>\\ n"; } } close ORGIDATA;
    prints nothing.
    However if the code is amended to comment out the open and close lines the information is printed.

    Yes, Zaxo, I am using CGI.pm, I hadn't known about that feature of CGI.pm so I went to do some research to see how it worked. I found the save function and tried using that but it didn't work (functioned same as above). If I missed your point please correct me.

      deryni,

      just a heads up...

      open ORGIDATA, ">orig" || die "Couldn't open! $!"; for (my $k = 0; $k < @classid; $k++) { if ($classid[$k] != $classid[$k-1]) { print $classid[$k], " ", @{$class[$k]}, " ", $location +[$k], " ", $credits[$k], "<br>\\ n"; } } close ORGIDATA;

      if the print within the loop is supposed to output to the "orig" file, then you'll want to use the file handle in the print statement:

      print ORGIDATA $classid[$k], " ", @{$class[$k]}, " ", $locatio +n
        Thank you for that information, I was using the print line with the filehandle but decided
        that in the interest of debugging I'd just have it print on the bottom of the webpage (easier to see if it worked).

        My real question here is why after the open line the print doesn't happen. Regardless of where I'm printing the print just does not occur.
        I have previously opened and closed two other filehandles in the program and there are something like 10 global arrays in the program. I don't know if any of that is important but thought I'd tell you anyway.

Re: Keeping form information in CGI
by rrwo (Friar) on Jul 03, 2001 at 20:11 UTC

    First suggestion: try using something like CGI::Persistent (admittedly not my favorite... I'm rolling my own CGI::Session for a project which does things very differently). There's a whole bunch of other persistent storage modules around, I think there's even a mailing list called <acronym>POOP</acronym> (Perl Object Oriented Persistence).

    Why use these? They keep track of individual sessions (what if multiple people go to your web page at the same time?) and the associated file management etc.

    As to your specific example: does the web user have permissions to modify the file? (I suggest you do not save session data in the same folder as your web scripts, which is what your example looks like it's doing ... you're asking for trouble securitywise if you do.)

    You're also not locking the file. That could get you into trouble if somebody else tries to access the process (hey? what if the user doesn't like the speed of the page and hits reload? Imagine two processes from the same script are accessing the file, even if only one user is using the script).