The Frame Stomper
Everyone who uses frames to build up his website is familiar with this: you design a nice frameset,
searchengines crawl your site for content and interested people are pointed to your content:
One single frame is displayed.
The rest of the frameset is blown into oblivion. For some people: no big deal. They litter there links and URL's throughout all of their files. Easy when making the pages, but terrible for maintenance. So I use three frames as standard:
So my Holy Task was to create the Frame Stomper!
How it's done
Below are the top 12 lines from this HTML document:
<!doctype html>
<html lang="en">
<head>
<script>
<!--
if (parent.location.href == self.location.href)
{ window.location.href =
'http://verhoeven272.nl/cgi-bin/FS?fruttenboel%2Fcgi&CGI+with+Mocka&cgitop&framestomper&cgicontent'
}
// -->
</script>
The piece of JavaScript checks if the frame is part of a frameset, or loaded itself in the parent frame. If
so, it starts the executable called
Source of the Frame Stomper.
Below is the sourcecode for FS.mod (the actual name of the Frame Stomper). It's not a big file. The
interesting sections are GetChar, GetWord and ConvertHex. The rest is rather straightforward.
The parameters are retrieved from the Query_String CGI environment variable as if it was some kind of command
line. The procedure 'CreateHTML' creates the HTML code for the file 'index.html' that sets up the frameset and
fills it with the right topframe, content frame and subject frame.
MODULE FS2;
(* FrameStomper new style with improved root file handling. March 10, 2007 *)
(* Changed it after the attack of 02-01-2008. January 12, 2008 *)
IMPORT ASCII, InOut, cgi, NumConv, Strings;
VAR content, path, Title : Strings.String;
Frame : ARRAY [0..7] OF Strings.String;
ok, Exhausted, error : BOOLEAN;
i, j : CARDINAL;
ch : CHAR;
PROCEDURE ConvertHex;
VAR str : ARRAY [0..1] OF CHAR;
num : CARDINAL;
BEGIN
str [0] := content [i];
str [1] := content [i+1];
INC (i, 2);
NumConv.Str2Num (num, 16, str, ok);
IF NOT ok THEN
InOut.WriteString ("Error in number : ");
InOut.WriteString (str);
InOut.WriteLn;
InOut.WriteBf;
HALT
END;
ch := CHR (num)
END ConvertHex;
PROCEDURE GetChar;
BEGIN
ch := content [i];
INC (i);
IF ch = '+' THEN
ch := ' '
ELSIF ch = '%' THEN
ConvertHex
ELSIF (ch = 0C) OR (i = HIGH (content)) THEN
Exhausted := TRUE
END
END GetChar;
PROCEDURE GetWord (VAR str : Strings.String);
BEGIN
j := 0;
LOOP
GetChar;
IF Exhausted OR (ch = '&') THEN EXIT END;
str [j] := ch;
INC (j)
END;
str [j] := 0C
END GetWord;
PROCEDURE ProcessGet;
VAR str : Strings.String;
index : CARDINAL;
BEGIN
index := 0;
REPEAT
GetWord (str);
IF index = 0 THEN
path := '/';
IF str [0] # '.' THEN
Strings.Append (path, str);
Strings.Append (path, '/')
END
ELSIF index = 1 THEN
Title := str
ELSE
Frame [index - 2] := str
END;
INC (index);
IF (Condition removed) THEN RETURN END
UNTIL Exhausted;
END ProcessGet;
PROCEDURE CreateHTML;
BEGIN
InOut.WriteString ('<html><head><title>');
InOut.WriteString (Title);
InOut.WriteString ('</title></head>');
InOut.WriteLn;
InOut.WriteString ('<frameset rows="60, *" border="0">');
InOut.WriteLn;
InOut.WriteString ('<frame src="');
InOut.WriteString (path);
InOut.WriteString (Frame [0]);
InOut.WriteString ('.html" scrolling="no" noresize="yes">');
InOut.WriteLn;
InOut.WriteString ('<frameset cols="*, 16%" border="0">');
InOut.WriteLn;
InOut.WriteString ('<frame src="');
InOut.WriteString (path);
InOut.WriteString (Frame [1]);
InOut.WriteString ('.html" name="main" marginheight="0" marginwidth="0">');
InOut.WriteLn;
InOut.WriteString ('<frame src="');
InOut.WriteString (path);
InOut.WriteString (Frame [2]);
InOut.WriteString ('.html" name="sidebar">');
InOut.WriteLn;
InOut.WriteString ('</frameset></frameset></html>')
END CreateHTML;
PROCEDURE Init;
BEGIN
Exhausted := FALSE;
error := FALSE;
Title := "Framestomper at work";
FOR i := 0 TO 7 DO Frame [i] := "main.html" END;
i := 0
END Init;
BEGIN
Init;
cgi.InformServer (cgi.Html);
IF cgi.GetEnvVar (Condition removed) = FALSE THEN error := TRUE END;
IF Strings.StrEq (Condition removed) = FALSE THEN error := TRUE END;
IF cgi.GetEnvVar (Condition removed) = FALSE THEN error := TRUE END;
IF cgi.GetEnvVar (Condition removed) = FALSE THEN error := TRUE END;
IF error = FALSE THEN
ProcessGet;
CreateHTML
ELSE
InOut.WriteString ("<html><head><title>Framestomper Abused</title></head>");
InOut.WriteString ("<body><center><h1>You have abused the FrameStomper!<p></h1></center>");
InOut.WriteString ("<p>Where would you like to go?<p>");
InOut.WriteString (" ");
InOut.WriteString ('<a href="http://www.verhoeven272.nl">Visit the family site</a><p>');
InOut.WriteString (" ");
InOut.WriteString ('<a href="http://fruttenboel.verhoeven272.nl">Visit the technical site</a><p>');
InOut.WriteString (" ");
InOut.WriteString ('<a href="http://www.politie.nl">Prison</a><p>');
InOut.WriteString ('<a href="mailto:jan@verhoeven272.nl?subject=framestomper perils">Mail me about the framestomper</a>');
InOut.WriteString ('<p><hr><p>Copyright Jan Verhoeven, 2008');
InOut.WriteString ("</body></html>")
END;
InOut.WriteLn;
InOut.WriteBf
END FS2.
As you can see, the program makes checks on a lot of items. And although I am a believer in open source
software I took the liberty to hide the security measures in 'Condition removed' phrases in order to make sure
my webhost will run errorfree.
This kind of program needs to be failsafe. If an error condition occurs it must lead to a controlled state of
the executable. The program runs on an unattended webserver so there is no one to check for a runaway program
with ps aux followed by a kill -9.
I don't just get a string from the environment. I first check if that strings is available. And if it isn't,
the program is set into an error condition before it starts creating nonsense data thereby possibly crashing
(or at least slowing down) the webserver. In this context: check out the section called 'CGI loop'.
The Croatians tried to break the old framestomper. They failed, but it caused me to increase the security a
few steps up. Silly Yugo's.
Making it work.
For details about how to develop CGI executables I refer to the webpage 'Debugging CGI' which is also in this section. In short, this is the bottomline:
In the download section is the source for FS.mod as a tar.gz file. I have also included the related FS executable to store and run on your own server or hosted webspace. Please do not use the executable in my webspace. It won't run on your site.
A dedicated Google Stomper..
The FrameStomper 'as-is' will only serve HTML files in a frameset. But I also have several gzipped files that I want served. And the FrameStomper will not do this. So I made a dedicated FrameStomper-gz. It is identical to the FrameStomper which is published above. Only the 'PROCEDURE CreateHTML' is slightly different, as you can see here:
PROCEDURE CreateHTML;
BEGIN
WriteString ('<html><head><title>'); WriteString (Title);
WriteString ('</title></head>'); WriteLn;
WriteString ('<frameset rows="60, *" border="0">'); WriteLn;
WriteString ('<frame src="');
WriteString (path); WriteString (Frame [0]);
WriteString ('.html" scrolling="no" noresize="yes">'); WriteLn;
WriteString ('<frameset cols="*, 16%" border="0">'); WriteLn;
WriteString ('<frame src="');
WriteString (path); WriteString (Frame [1]);
WriteString ('.html.gz" name="main" marginheight="0" marginwidth="0">');
WriteLn;
WriteString ('<frame src="');
WriteString (path); WriteString (Frame [2]);
WriteString ('.html" name="sidebar">'); WriteLn;
WriteString ('</frameset></frameset></html>'); WriteLn;
InOut.WriteBf
END CreateHTML;
Only the line just above the single 'WriteLn' command has been changed. This new version of the FrameStomper
has been running several weeks now and operates without any problems on the machine of my webhost.
You want to have one too.
This version of the frame Stomper only works if you use a frameset like mine. The text in red must be passed to the CGI program by the client.
<html>
<head>
<title>Your title</title>
</head>
<frameset rows="60, *" border="0">
<frame src="Frame1.html" scrolling="no" noresize="yes">
<frameset cols="*, 16%" border="0">
<frame src="Frame2.html" name="main" marginheight="0" marginwidth="0">
<frame src="Frame3.html" name="sidebar">
</frameset>
</frameset>
</html>
So, if this is the case, you can just download the free version of the FrameStomper in the file
FrameStomper.tar.gz which is available in the download section. In all other cases there are two ways to
obtain a dedicated Frame Stomper for your style:
Page created 8 April 2006
Page equipped with FroogleBuster technology