Oh... some issues there.
First of all, drop the DOCTYPE, stop using that. It's only needed for compatibility purposes, if you have some html content that actually uses deprecated html tags and other bad things from the past.
By default, browsers will assume you use HTML 5, which doesn't require you to specify the DOCTYPE, or in other words <!DOCTYPE html> is implicit. It's not needed.
Then, you don't need to say meta http-equiv = "content-type" because you already tell the browser through the HTML Response Header
( --- assume [ENTER] or [enter] means "\r\n" everywhere I say it, I type [enter] faster than \r\n --- )
You should have a function that does the HTTP Response, and a separate function that does the actual html headers:
function generate_headers( contentType="text/html", filename="", filesize=-1, extraHeaders = "" )
Your HTTP Response would be
HTTP/1.1 200 OK [enter]
Content-Type: text/html [enter] <= this "text/html" could be passed as parameter to the function that builds the string so you could reuse this function with "octet-stream" as well
[enter]
This is your basic header.
If you want to serve a file as a download, then you can add some lines after changing the content-type to octet-stream or something else:
Content-Disposition: attachment; filename="file.xyz" [ENTER]
Content-Length: <filesize> [ENTER]
<--- you can add the file name, file size as parameters to your generate header function, see above
In your generate_headers function you could do something as basic as this
if filesize != -1 then you know you have a download, so add those two lines. Optionally, only add "; filename="###" segment IF filename is not an empty string (filenane != ""). If it is, leave just "attachment"
You can add those no-cache tags as well, if you want.
You can also have an extra parameter to your generate_header function called "extraHeaders" which could be useful for example when you want to add an extra response line in your header, like Set-Cookie for example, to set the session info , token to determine if user is logged in or not.
You have to be careful how you glue these bits together, so that you'll only have an empty line when you're done with the Response Header lines.
ex generate_header("text/plain", "", -1, "Set-Cookie: token=value; Secure; Max-Age=3600 [ENTER]")
Once you're done sending the Response Header, you send the content ... which can be a html page, or it can be a download. As soon as you're done, you close the connection and everything ends here.
Your webserver will receive another request.
For your html responses, AFTER the Response Header lines, you will have the basic HTML header, which would show up in all html files :
<html>
<head>
<title> this title is optional but shows up in the title bar </title>
<link rel="shortcut icon" href="/favicon.ico" or href="data; ... " - see https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs - />
<link rel="stylesheet" href="filename.css" > <-- if you choose to serve a stylesheet as a separate CSS file (will be cached)
<script src="file.js"></script"> <-- if you choose to serve a javascript each time a html page is loaded (will be cached)
</head>
<body>
After body, you can put actual content that's visible on a page.
You could have everything up to <body> including it, in another function, let's call it generate_pageHeader(title="Main Page")
Then you print the stuff you want to be seen on the page, and last you close the body tag and the html tag.
The body tag, the html tag, some optional inline javascript if you wish ... you could have a function called generate_pageFooter() that outputs
</body>
</html>
After you output this, you close the connection, the server's job is done.
NOW ... for your main page with the menu ... & is a bad character to use, and you shouldn't rely on it to make distinction between menu options and actual downloads.
I would basically set a rule, for example :
anything that's in the root of the web server is a command or something that returns a html / picture response
* index.html = show main page
* login.html = login user
* logout.html = log out
*upload.html = upload file
* edit.html = edit a file
* delete.html = delete a file
* script.css = serve a css file by setting the proper mime type in the header function and then sending the css text after the response
* script.js = serve a javascript file, like with css file
* favicon.ico = serve favicon file
If the request has a folder in the url, then you know it's a download ex
* /FILES/CONFIG.INI - you receive the request, you see there's FILES/ there, so you know a download was requested, send proper response header then send the file, close the connection
If you do this, then in your html header, you would need to set any address as fixed to the root
anyway, we're going off topic... back to your default index page
B tags and <font> tags are kind of deprecated, it's best to use style= " " , or move what you put in the style, into separate CSS or inline CSS in the head
So your page after body could be this :
<h1>Menu</h1>
<a href="files.html">Files</a><br/>
<a href="status.html">Status</a><br/>
<a href="reboot.html">Reboot</a><br/>
<a href="test.html">Test</a><br/>
then you send the footer aka </body></html> and connection is closed.
<table>
<tr><td>Filename></td><td>Size</td><td>Attr.</td><td></td></tr>
<tr>
<td><a href="/FILES/CONFIG.INI">CONFIG.INI</a></td>
<td>954B</td>
<td>---a-</td>
<td> <a href="edit.html?filename=CONFIG.INI">edit</a> <a href="delete.html?filename="CONFIG.INI">delete</a></td>
</tr>
</table>
In the files list, there's no reason why you would refresh the file list often ... are files gonna be created all the time? No. Once you dump the list of files, connection is closed, job done. User can hit reload to refresh the page if needed.
When user clicks on the file name, the browser creates a new connection to your server and requests the file by asking for /FILES/CONFIG.INI or /FILES/WHATEVER ... your code sees that "FILES" and it can extract the file name desired to download from the string.
Or, you could have download.html?filename=CONFIG.INI I guess. But you still have to parse the URL in the request headers.
There's no reason to add that meta refresh to disable the refresh because it's not possible, it's like this request for a file is loaded in a different browser, or another computer, it has no connection to the previous page.
You can't mix that meta tag with the HTML Response Header lines, it doesn't work like that.
For downloads, you call your generate response header function but you DO NOT call the generate html header function and your generate html footer function, you simply outpout the proper response headers, then dump the file and close the connection.