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

As I begin my first major CGI undertaking, I find myself making lots of little CGI programs which I am passing parameters to and from and feel like there is probably a more elegant, and secure, way to do the whole thing as one CGI program with subroutines. Example: currently I have a database, users can select an item to change it. So I have the database CGI, then then CGI file for asking what changes are needed for a particular entry, and then another CGI file to submit the changes. This could all be one file I feel, but I have questions about how to do this:

-can a single CGI script produce several HTML pages-say output one, wait 30 seconds and then output another. If this is possible, how do I do it?

-If put all my files together into subroutines of one big program, every time I execute it I need some mechanism to decide which subroutine to go to....do I pass some parameter like subroutine=editentry and then have some sort of PERL if statement to go to the proper subroutine? If I do this than I need to also know how to pass parameters from an HTML form which are not being entered by the user. How do I do this?

Any help would be great! Thanks!

Jeff

  • Comment on CGI: Make one big program or lots of little ones?

Replies are listed 'Best First'.
Re: CGI: Make one big program or lots of little ones?
by dvergin (Monsignor) on Feb 22, 2001 at 05:00 UTC
    One script or many: When the user is posting changes, I have found it helpful to have two scripts. Let's call them show.pl and post.pl. The various forms specify post.pl in the action for the <form...>. Then after processing the post, the post.pl script spits out an HTTP location header line that takes the client browser back to the show.pl script displaying whatever is appropriate.

    This is nice for separating functionality. But more importantly, because the page the browser sees is not a direct response to a form, the dreaded "Repost form data?" pop-up message does not appear if the user happens to hit Reload.

    Output, wait 30 seconds, output another page: Normally you cannot do that (check on push techniques if you want to explore doing it). Think about it, the server only serves when a browser requests a page. The browser only is ready to receive a page right after it has send the server a request. Even if you had the server spit out another page, the browser would not be waiting for a page and would just ignore it.

    If you meant, can a script respond to one browser request and then the same script respond to a different browser request 30 seconds later, the answer is Yes. Which brings us to:

    Some mechanism to decide which subroutine... Three ways come quickly to mind.

       1)Query string values
       2)Extended url path values
       3)<input type=hidden...>

    If you need more info about any of these, just repost and I or someone else is sure to respond.

    And of course you are using CGI.pm...

    Good luck.

Re: CGI: Make one big program or lots of little ones?
by DarkProphet (Novice) on Feb 22, 2001 at 18:10 UTC
    I find that its much easier to use a single script split up into subs. Its fairly easy to invoke the subs by setting a variable to do so in the form you are submitting:
    ... <input type="hidden" name="op" value="some_operation"> ...
    and in your script, you'll want to do something like this
    ... #(generic code / beginning of HTML dumped here) &$op(); ... #(generic code / end of HTML dumped here)
    of course, its possible that someone playing with your form could execute subs that you'd rather they not, so I suggest creating an array, with the names of subs that are "safe" to run: example:
      This is a technique that I use, either using hidden fields as you describe or passing flags in PATH_INFO.

      However, I would use a hash instead of your @safesubs and $ok:

      my %valid = map {$_ => undef} qw(this_sub that_sub other_sub); die unless exists $valid{$op}; &$op();
        Well passing flags in the PATH_INFO works fine, but wouldn't encourage doing it that way, beacause the browser will show the whole path (including flags). This is fine if there is no real sensitive info in the path, but it can be more of a security risk. Using hidden fields is a bit safer.
        But your code itself does look a lot nicer ;-)

        I've never claimed to be a Perl God(TM), and any claims to the converse are used fictitiously.
Re: CGI: Make one big program or lots of little ones?
by repson (Chaplain) on Feb 23, 2001 at 10:59 UTC
    The funtionality you are talking about is implemented in CPAN modules CGI::Screen and CGI::Application. Having never used them myself, I cannot tell if they are an exact solution, but they are probably worth looking at.

    If you want to produce multiple pages in a single http responce, then you are talking about http push, which can be done with CGI::Push, but is limited to netscape. Alternativly you can use a http pull through the Refresh http header, which is more widely supported but still relies on the clients.