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

First, you'll need a little background. I'm working on a template system (yes, I know there are modules out there, but I'm trying to learn how to do it in this manner first). Basically, I have an HTML document which contains HTML REM tags like this: <!-- fillin(getLogo) --> (this is the same template system I asked another qeustion about a couple of weeks ago, so the background info may sound familiar). Basically, whatever is within the parens within the fillin statement is a subroutine that gets called. Actually, it's just a variable that gets compared to a list of allowable subroutine calls (I do this for security). The point is that the REM tag gets replaced with the HTML that is generated from whatever subroutine is called. All this is compiled into a buffer which is then printed at the end.

Now, in some situations, I would like to manipulate header information. I can generate the header separately, but I would like to manipulate it from some of these subroutines. Specifically, I'd like to create a refresh meta tag, and I would like to have cookie information set by some of these subroutines. The problem is that I cannot seem to figure out how to return anything other than the following code snippet (I will explain variables after the code -- the program is way too large to paste here):

open(FILE, "<$template") or die "Template : Couldn't open $template : +$!\n"; while (<FILE>) { $HTML .= $_ } close(FILE); while ($HTML =~ /<!-- fillin\((.+?)\) -->/) { my $command_output = &{$templateCall->{$1}}; # a subroutine call $HTML =~ s/<!-- fillin\(.+?\) -->/$command_output/; }

Let me explain some of the variables:
$template is pulled from the user database. A user can change themes within this system, and therefore has a variable set within the database for this. There is no user input from the URL.
$HTML is pre-defined within this subroutine (local variable). This is basically the entire output which will be filtered.
$templateCall is a hash-reference that basically lists the subroutines associated with the template's fillin() commands. Again, I do this for security.

Now, assuming that I call a subroutine that checks a user's username and password, then logs them in, I want to be able to return cookie information (or refresh information) back to this subroutine so that I can run further tests. I basically want to add a line for a cookie if a cookie variable is defined. And I want to be able to add a meta tag to my header if said variable is defined. I modified the code to the following, and it doesn't really seem to work (assume that I do define all these variables):

while ($HTML =~ /<!-- fillin\((.+?)\) -->/) { my $command_output = &{$templateCall->{$1}}; # a subroutine call ($HTML, $cookie, $refresh) =~ s/<!-- fillin\(.+?\) -->/$command_outp +ut/; }

From the subroutine, I always return data to $HTML. Whether or not I return data to $cookie and $refresh or not depends on the nature of the subroutine. I think I know why it's not working (the tilde), but I can't seem to figure out a way around that.

I have no problem generating header information after this point, and just making sure that it prints the header first.

Any help would be appreciated.

--Coplan

Replies are listed 'Best First'.
Re: Header data from arbitrary calls
by ajwans (Scribe) on Mar 05, 2002 at 05:34 UTC
    You probably want to do something more like

    open (FILE, $file) or die ("Couldn't open $file: $!"); @HTML = <FILE>; for (@HTML) { s/<!-- fillin\((.+?)\) -->/&{$templateCall->{$1}}/eg; } splice (@HTML, 0, 0, @HEADERS); # this is a subroutine called by the templateCall to add # a header sub add_header { my $header = shift; unshift (@HEADERS, $header); }
    So that the headers get added to the start of the HTML.
      I'm not sure I follow.

      The subroutine that my code is contained within is the part that generates the entire HTML file, based on the template with the additional information filled in. I can generate the header information after the rest of the body is generated, that really isn't the problem. The problem is that I'm trying to return both the HTML buffer to be returned by the templateCall, as well as some other information (like if a cookie is set, or the refresh page information). For example...if I were working without a template model, I would be doing things differently. The subroutine called by templateCall would have a return line like this:

      sub SomeTemplateCall { my $refresh = "http://www.scenespot.org"; my $cookie = "some random number"; my $buffer .= "<b>Stuff</b>"; return ($buffer, $cookie, $buffer); } # The subroutine that called it: sub templateParser { my ($HTML, $cookie, $buffer) = SomeTemplateCall(); # Header would then be generated utilizing $buffer, $cookie # $HTML would then be the rest of the damn website }

      Due to the nature of my script, I can't really do things that way, apprently. At least it doesn't seem to work as I showed above.

      --Coplan

Re: Header data from arbitrary calls
by ajwans (Scribe) on Mar 05, 2002 at 21:28 UTC
    AFAIK cookies must be set in the header, which is why I suggested adding it to the start of the HTML, unless you dynamically generate some javascript to set the cookie inline. I've used this strategy before and you have to be careful due to different browsers supporting different flavours of javascript.