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

I'm sorry if this has already been asked, but I can't find an answer to this question anywhere even though it should be a common problem.

I have a Perl/CGI page which I will call foo.cgi. In foo.cgi, I have a form which action is to submit back to foo.cgi (<FORM name='form1' method='post' action='foo.cgi'). When the page reloads, if I detect that the form was submitted, I validate the input and then, if necessary, send the data off to one of about 10 other CGI pages, depending on which option the user selected in the form. I will call one of these other CGI pages bar.cgi. I call bar.cgi using an HTML meta refresh and pass in variables in the URL string using the GET method (<META http-equiv='refresh' content='0; URL=bar.cgi?array1=value1&array1=value2'>).

My question is, how do I validate in bar.cgi that foo.cgi called it? I don't want users being able to call bar.cgi directly entering in any value for any variable they want in the URL. My only idea was to use the referer() method in the CGI package, but apparently that method doesn't find any value when a META refresh is used. Any other ideas? If there's a better way to call bar.cgi from foo.cgi, I'd be open to it.

Replies are listed 'Best First'.
Re: Detect CGI page caller
by bellaire (Hermit) on Mar 02, 2009 at 16:35 UTC
    One way would be to store some session data using CGI::Session before forwarding the user to bar.cgi (which basically says "This user is being forwarded to bar.cgi from foo.cgi"), and then read that data using CGI::Session in bar.cgi. If, in bar.cgi, the data is not present or invalid, deny the request.
Re: Detect CGI page caller
by perrin (Chancellor) on Mar 02, 2009 at 17:17 UTC
    The key is to use data that the client end couldn't know. You can probably rig something with an HMAC and the Disgest::SHA1 module. Or generate a random string and stuff it into a database so you can verify that it came from you, and then delete it once it has been used.
Re: Detect CGI page caller
by hangon (Deacon) on Mar 02, 2009 at 16:44 UTC

    There is probably no easy foolproof way using HTTP (such as refresh, checking referer etc). I suggest that you convert the bar.cgi programs into modules, then modify foo.cgi to require the appropriate bar module when needed. The bar module would then receive its parameters from and pass its http content to foo.cgi, which would then serve the web page.

Re: Detect CGI page caller
by jettero (Monsignor) on Mar 02, 2009 at 17:02 UTC

    CGI::Session (above) is probably a good way to go. On multipage forms, particularly those interfacing with antiquated internal foxpro servers, I have also used Crypt::CBC signed hidden input form data to propagate data from one page to another. That's a lotta trouble though if CGI::Session will do.

    -Paul

Re: Detect CGI page caller
by satanicpuppy (Novice) on Mar 02, 2009 at 21:42 UTC
    If you're going to use CGI::Session, you might want to go ahead and pull the data out of the URL, and put it into the session cookie:

    $session->param('field_name', 'field_value');

    If you really care about data coming directly from foo.cgi, then you should put the data into a session cookie that can expire, rather than a URL that can be bookmarked.