Populating HTML Form Fields with Data before serving it to Client

Populating HTML Form Fields with Data before serving it to Client

Post by jbk » Mon, 19 Apr 2004 05:24:26


I have a Indy HTTPServer Component serving html templates to clients. I
have no problem reading the data out of the templates once the user post
it. The question is how do I populate the fields in these templates
with data before serving them to the client?

Thanks in Advance

JBK
 
 
 

Populating HTML Form Fields with Data before serving it to Client

Post by Team » Mon, 19 Apr 2004 05:47:51


Put placeholders in the template that your code can look for. Then store
the template data into memory, such as in a simple String, and then scan
through the data looking for the placeholders where you should be inserting
your data, and replace the placeholders with your actual data. Then serve
the final data.


Gambit

 
 
 

Populating HTML Form Fields with Data before serving it to Client

Post by Team » Mon, 19 Apr 2004 06:31:01


inserting

In other words, say you have the following template:

<html>
<body>
Hello, <%remoteip%>
</body>
</html>

You would then load the template into memory, scan for <%remoteip%>, and
replace it as needed, ie (untested):

var
Strm: TFileStream;
Template, Str, DataToServe: String;
Begin, Tmp, TagStart: TagEnd: PChar;
begin
// load the template file into memory
Strm := TFileStream.Create('c:\somefile.tmp', fmOpenRead or
fmShareDenyWrite);
try
SetLength(Template, Strm.Size);
Strm.Read(Template[1], Strm.Size);
finally
Strm.Free;
end;

// locate the first '<%' opening tag
Begin := PChar(Template);
TagStart := AnsiStrPos(Begin, '<%');

if (TagStart = nil) then
begin
// tag not found, return the template as-is
AResponseInfo->ContentType := 'text/html';
AResponseInfo->ContentText := Template;
Exit;
end;

// scan through the template looking for "<%name%>" tags
// and adding the appropriate values to the data to serve

// first append the template data up to the first "<%" opening tag
if (TagStart <> Begin) then
DataToServe := Copy(1, Cardinal(TagStart)-Cardinal(Begin),
Template)
else
DataToServe := '';

repeat

// locate the next '%>' closing tag
Tmp := PChar(Cardinal(TagStart)+2);
TagEnd := AnsiStrPos(Tmp, '%>');

if (TagEnd = nil) then
begin
// tag not found, append the remaining template data and
serve it
DataToServe := DataToServe + String(TagStart);
Break;
end;

// extract the token and append its value to the data being
served
SetString(Str, Tmp, Cardinal(TagEnd)-Cardinal(Tmp));
if (Str = 'remoteip') then DataToServe := DataToServe +
ARequestInfo.RemoteIP;

// locate the next '<%' opening tag
Tmp := PChar(Cardinal(TagEnd)+2);
TagStart := AnsiStrPos(Tmp, '<%');

if (TagStart = nil) then
begin
// tag not found, append the remaining template data and
serve it
DataToServe := DataToServe + String(Tmp);
Break;
end;

// append the template data between the previous "%>"
// closing tag and the next "<%" opening tag and continue
DataToServe := DataToServe + Copy(Cardinal(Tmp)-Cardinal(Begin),
Cardinal(TagStart)-Cardinal(Tmp), Template)
until False;

// serve the resulting data
AResponseInfo->ContentType := 'text/html';
AResponseInfo->ContentText := DataToServe;
end;


Gambit
 
 
 

Populating HTML Form Fields with Data before serving it to Client

Post by Ben Hochst » Mon, 19 Apr 2004 07:26:33


Hmm. If you're using windows, there's an easy way to have the operating
sytem fill in the values:

var
buf: array[0..32000] of char;
i: integer;
begin
SetEnvironmentVariable('remoteip', PChar(TheRemoteIP));
(...)
i := ExpandEnvironmentStrings(PChar(OldHtmlCode.Text),
@buf[0], SizeOf(buf));
if i > 0 then
NewHtmlCode.Text := Copy(buf, 1, i - 1);
SetEnvironmentVariable('remoteip', nil);
end;

of course, some precautions (such as checking whether i > SizeOf(buf)
etc) must be made, but I've used a similar function for a number of text
utilities now.
Another advantage (or disadvantage, depends...) is that you can use all
other environment variables. This is funnier in .cgi applications (where
the webserver defines a shitload of useful stuff), but may serve you here
too.

Just an idea...

--
Ben
 
 
 

Populating HTML Form Fields with Data before serving it to Client

Post by Team » Mon, 19 Apr 2004 07:47:12


True. However:

1) it is Windows specific.

2) it only works with "%name%" strings specifically, which such a format may
not be desireable. Using custom opening/closing tags for tokens reduces the
risk of detecting mismatched/invalid tokens.

3) if a string is not found in the environment, the original string and
sorrounding "%" tokens is left untouched, whereas my code stripped them out
indicating an empty string.

4) the input and output strings are limited to 32K max, so you wouldn't be
able to process larger templates. Do do so would require breaking the
strings into 32K blocks and calling ExpandEnvironmentStrings() multiple
times, and as well as dealing with tokens overlapping at the block
boundaries.


Gambit
 
 
 

Populating HTML Form Fields with Data before serving it to Client

Post by Ben Hochst » Mon, 19 Apr 2004 08:15:58


That's what I said too. :)


Well, you came up with the "percent-tokens"; that's why I had this idea.


That is true.


The 32K were only in my example. Is there a hard-coded limit?

Oh, while we're discussing this - in HTML line breaks do not matter
(unless between <pre>...</pre> tags). So I'd write the template in a way
that had the placeholder in a line of its own which would greatly
simplify searching/replacing...

--
Ben
 
 
 

Populating HTML Form Fields with Data before serving it to Client

Post by Team » Mon, 19 Apr 2004 15:14:57


I chose that because such an approach is commonly used in several
server-side scripting languages, such as ASP, PHP, etc. PHP uses "<?php ...
?>" instead of "<% ... %>". The point I am trying to make is to use SOME
kind of unique identifiers should be used to denote where special processing
should start and stop. Which tokens are actually decided on is jbk's
personal choice.


Yes, there is, and it is clearly stated as such in the Win32 API
documentation for ExpandEnvironmentStrings():


http://www.yqcomputer.com/

"The size of the lpSrc and lpDst buffers is limited to 32K."


Not exactly. From a theoritical standpoint, you are correct that line
breaks should not make any difference. In real world use, however, you have
to be careful with them because line breaks DO make a difference in certain
situations. Depending on what the surrounding HTML content is, line breaks
can actually introduce extra spacing in the browser display, amongst other
possible minor/subtle side effects. That may or may not be
desirable/acceptable to the user.


It may help the parser some, but in actuality the more inline the processing
tags are allowed to be, the more flexible the parser will be overall.



Gambit
 
 
 

Populating HTML Form Fields with Data before serving it to Client

Post by jbk » Wed, 21 Apr 2004 01:07:17


Thanks for your help.

Jef