<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Recent changes to HTTP-Server</title><link>https://sourceforge.net/p/v1-script/wiki/HTTP-Server/</link><description>Recent changes to HTTP-Server</description><atom:link href="https://sourceforge.net/p/v1-script/wiki/HTTP-Server/feed" rel="self"/><language>en</language><lastBuildDate>Sun, 21 Dec 2025 16:36:32 -0000</lastBuildDate><atom:link href="https://sourceforge.net/p/v1-script/wiki/HTTP-Server/feed" rel="self" type="application/rss+xml"/><item><title>HTTP-Server modified by Kalle</title><link>https://sourceforge.net/p/v1-script/wiki/HTTP-Server/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v47
+++ v48
@@ -151,7 +151,7 @@
                header = strtoupper (trim (substr(line,0,p)));
                value = trim (substr(line,p+1));
                if (header=="CONTENT-LENGTH")
-                       contentLength = value;
+                    contentLength = value;
                headerList[header]=value;
            }
        }
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Kalle</dc:creator><pubDate>Sun, 21 Dec 2025 16:36:32 -0000</pubDate><guid>https://sourceforge.net6afbd1ba30295a5f55ad5d0ba0282294da751897</guid></item><item><title>HTTP-Server modified by Kalle</title><link>https://sourceforge.net/p/v1-script/wiki/HTTP-Server/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v46
+++ v47
@@ -1,54 +1,52 @@
 ~~~
 :::php
  "text/css",
-  "js" =&amp;gt; "application/x-javascript",
-  "jpg" =&amp;gt; "image/jpeg",
-  "jpeg" =&amp;gt; "image/jpeg",
-  "png" =&amp;gt; "image/png",
-  "gif" =&amp;gt; "image/jpeg",
-  "svg" =&amp;gt; "image/svg+xml",
-  "exe" =&amp;gt; "application/octet-stream",
-  "pdf" =&amp;gt; "application/pdf",
-  "doc" =&amp;gt; "application/msword",
-  "docx" =&amp;gt; "application/msword",
-  "ico" =&amp;gt; "image/x-icon",
-  "mp4" =&amp;gt;"video/mp4",    
-  "xml" =&amp;gt; "text/xml",
-  "txt" =&amp;gt; "text/plain",
-  "sh" =&amp;gt; "text/plain",
-  "bat" =&amp;gt; "text/plain"
-); 
+   "css" =&amp;gt; "text/css",
+   "js" =&amp;gt; "application/x-javascript",
+   "jpg" =&amp;gt; "image/jpeg",
+   "jpeg" =&amp;gt; "image/jpeg",
+   "png" =&amp;gt; "image/png",
+   "gif" =&amp;gt; "image/gif",
+   "svg" =&amp;gt; "image/svg+xml",
+   "exe" =&amp;gt; "application/octet-stream",
+   "pdf" =&amp;gt; "application/pdf",
+   "doc" =&amp;gt; "application/msword",
+   "docx" =&amp;gt; "application/msword",
+   "ico" =&amp;gt; "image/x-icon",
+   "mp4" =&amp;gt;"video/mp4",
+   "xml" =&amp;gt; "text/xml",
+   "txt" =&amp;gt; "text/plain",
+   "sh" =&amp;gt; "text/plain",
+   "bat" =&amp;gt; "text/plain"
+);


 fExitAll = false;
 docPath = getcwd ();
 if (isset (argv[2]))
-  docPath = argv[2];
+   docPath = argv[2];

 realDocPath = realpath (docPath);
 print ("Document path is ".realDocPath);
@@ -57,337 +55,415 @@


 function maintenanceThread () {
-  fFirstStart = true;
-  while (true) {
-    sleep (500);
-    // Do some maintenance
-    if (fFirstStart &amp;amp;&amp;amp; isset (argv[3])) {
-      // Start Webbrowser URL
-      print ("Start ".argv[3]);
-      shellexec (argv[3]); 
-      fFirstStart = false;
-    }
-  }
-}
-
+   global fExitAll;
+   fFirstStart = true;
+   while (!fExitAll) {
+       sleep (500);
+       // Do some maintenance
+       if (fFirstStart &amp;amp;&amp;amp; isset (argv[3])) {
+           // Start Webbrowser URL
+           print ("Start ".argv[3]);
+           shellexec (argv[3]);
+           fFirstStart = false;
+       }
+   }
+}
+
+// Function load certificate by servername from cert/ directory
 function servernameCallback (servername) {
-  global serverCertList;
-  // print ("Callback ".servername);
-  if (!isset (serverCertList[servername])) {
-    ctx = SSL_CTX_new ();
-    if (SSL_CTX_load_cert (ctx, CERT_DIR."/".servername.".crt", CERT_DIR."/".servername.".key")) {
-      serverCertList[servername]=ctx;
-    }
-    else {
-      print ("Cannot load SSL certificate ", CERT_DIR."/".servername.".crt");
-    }
-  }
-  return serverCertList[servername];
-}
-
+   global serverCertList;
+
+   if (!isset (serverCertList[servername])) {
+       // Check with/without www.
+       fOnlyCheck = false;
+       if (strpos (servername, "www.")===0) {
+           servername2 = substr (servername, 4, strlen (servername)-4);
+       }
+       else {
+           fOnlyCheck = true;
+           servername2 = "www.".servername;
+       }
+       if (isset (serverCertList[servername2])) {
+           return serverCertList[servername2];
+       }
+       if (!fOnlyCheck)
+           servername = servername2;
+
+       if (!is_file (CERT_DIR."/".servername.".crt")) {
+           // Create self signed certificate
+           if (!SSL_create_selfsigned_cert (CERT_DIR."/".servername.".crt", CERT_DIR."/".servername.".key" , servername, 315360000, "sha256", 2048))
+               print ("Cannot create self signed certificate for ".servername);
+       }
+
+       ctx = SSL_CTX_new ();
+       if (SSL_CTX_load_cert (ctx, CERT_DIR."/".servername.".crt", CERT_DIR."/".servername.".key")) {
+           serverCertList[servername]=ctx;
+       }
+       else {
+           SSL_CTX_free (ctx);
+           print ("Cannot load SSL certificate ", CERT_DIR."/".servername.".crt");
+       }
+   }
+   return serverCertList[servername];
+}

 function clientWrite (&amp;amp;client, &amp;amp;str, ssl=null) {
-  if (ssl)
-    return SSL_write (ssl, str);
-  return fwrite (client, str);
+   if (ssl)
+       return SSL_write (ssl, str);
+   return fwrite (client, str);
 }

 function clientWriteLen (&amp;amp;client, &amp;amp;str, len, ssl=null) {
-  if (ssl)
-    return SSL_write (ssl, str, len);
-  return fwrite (client, str, len);
+   if (ssl)
+       return SSL_write (ssl, str, len);
+   return fwrite (client, str, len);
 }

 function clientReadln (&amp;amp;client, &amp;amp;str, ssl=null) {
-  if (ssl)
-    return SSL_readln (ssl, str);
-  return freadln (client, str);
+   if (ssl)
+       return SSL_readln (ssl, str);
+   return freadln (client, str);
 }

 function workerThread (client, ssl=null) {
-  global docPath, realDocPath, mimeTypeList;
+   global docPath, realDocPath, mimeTypeList;
+
+   if (ssl) {
+       SSL_set_fd (ssl, client);
+       if (!SSL_accept (ssl)) {
+           // SSL problems
+           SSL_free (ssl);
+           fclose (client);
+           return;
+       }
+   }
+
+   lineIdx = 0, contentLength=0, headerList=array ();
+
+   // Read the HTTP headers
+   line = "";
+   while (clientReadln (client, line, ssl)) {
+       if (lineIdx==0) {
+           assign (method, uri, protocol) = explode (" ", line);
+       }
+       else {
+           if ((p=strpos (line, ":"))!==false) {
+               header = strtoupper (trim (substr(line,0,p)));
+               value = trim (substr(line,p+1));
+               if (header=="CONTENT-LENGTH")
+                       contentLength = value;
+               headerList[header]=value;
+           }
+       }
+       if (empty (line))
+           break;
+       lineIdx++;
+   }
+
+   if (!isset (uri)) {
+       // No URI given, close connection and finish thread
+       if (ssl)
+           SSL_free (ssl);
+       fclose (client);
+       return;
+   }
+
+   // Get path and query string
+   queryString = "";
+   p = strpos (uri, '?');
+   if (p!==false) {
+       queryString = substr (uri, p+1, strlen (uri)-p-1);
+       path = substr (uri, 0, p);
+   }
+   else {
+       path = uri;
+   }
+   path = url_decode (path);
+
+   fFound = fRedirect = false;
+
+   // Check for auto index files
+   filename = realDocPath.path;
+   if (is_file (filename)) {
+       fFound = true;
+   }
+   else
+   if (is_dir (filename)) {
+       if (substr (path, -1, 1)!="/")  {
+           path.="/";
+           fRedirect = true;
+       }
+       else {
+           autoIndexList = array ("index.html", "index.v1", "index.htm");
+           foreach (autoIndexList as autoFile) {
+               path2=path."/".autoFile;
+               if (is_file (realDocPath.path2)) {
+                   path = path2;
+                   filename = realDocPath.path;
+                   fFound = true;
+                   break;
+               }
+           }
+       }
+   }
+
+   // Handle the filename
+   fileSize = 0;
+   if (fFound) {
+       fileSize = filesize (filename);
+   }
+   pi = pathinfo (filename);
+   fileExt = strtolower (pi["extension"]);
+
+   // Check if filename is outside docPath or special file extensions for security reasons
+   realFilename = realpath (filename);
+   if ((fFound &amp;amp;&amp;amp; fileSize&amp;gt;0 &amp;amp;&amp;amp; strpos (realFilename, realDocPath)!==0) || fileExt=="key" || fileExt=="htaccess") {
+       // Send HTTP status forbidden
+       clientWrite (client, "HTTP/1.1 403 Forbidden\r\nServer: V1 HTTP-Server\r\nConnection:close\r\nContent-Type: text/html\r\n\r\nRequested ressource ".path." is forbidden.\r\n\r\n", ssl);
+   }
+   else
+   if (fFound) {
+       // Get MIME type from file extension
+       mimeType = mimeTypeList[fileExt];
+       if (empty (mimeType))
+           mimeType = "text/html";
+
+       if (fileExt=="v1")
+       {
+           // Execute V1 Script as CGI
+           output = "", retCode = 0;
+           envStr = "QUERY_STRING=".queryString;
+           envStr.="\0";
+           envStr.='CONTENT_TYPE='.headerList["CONTENT-TYPE"];
+           envStr.="\0";
+           envStr.='SCRIPT_FILENAME='.filename;
+           envStr.="\0";
+           envStr.='SCRIPT_NAME='.path;
+           envStr.="\0";
+           envStr.='DOCUMENT_ROOT='.realDocPath;
+           envStr.="\0";
+           envStr.='REQUEST_URI='.uri;
+           envStr.="\0";
+           envStr.='REMOTE_ADDR='.fsockip (client);
+           envStr.="\0";
+           // HTTP vars
+           foreach (headerList as k =&amp;gt; v) {
+               envStr.='HTTP_'.str_replace ("-", "_", strtoupper (k)).'='.v;
+               envStr.="\0";
+           }
+           envStr.="\0";
+
+           cmd = './v1 -w "'.filename.'"';
+           if (exec (cmd, output, retCode, (contentLength&amp;gt;0 ? (ssl ? ssl : client) : null), contentLength, envStr)) {
+               responseStatus = "200 OK";
+               //  Analyze response header
+               p = strpos (output, "\n\n");
+               if (p!==false || ((p = strpos (output, "\r\n\r\n"))!=false)) {
+                   responseHeader = substr (output, 0, p);
+                   if (strpos (responseHeader, "\nLocation:")!==false) {
+                       responseStatus = "301 Moved Temporarly";
+                   }
+                   if ((p2=strpos (responseHeader, "\nStatus:"))!==false) {
+                       p2+=8;
+                       p3 = strpos (responseHeader, "\n", p2);
+                       if (p3===false)
+                           p3 = strlen (responseHeader);
+                       responseStatus = trim (substr (responseHeader, p2, p3-p2), " \r");
+                   }
+               }
+               clientWrite (client, "HTTP/1.1 ".responseStatus."\r\nServer: V1 HTTP-Server\r\n", ssl);
+               clientWrite (client, output, ssl);
+           }
+           else {
+               clientWrite (client, "HTTP/1.1 500 Internal Server Error\r\nServer: V1 HTTP-Server\r\n\r\nCannot execute: ".cmd."\r\n\r\n", ssl);
+           }
+       }
+       else {
+           // Send file HTTP status 200 OK
+           lastModified = gmdate (HTTP_DATE_FORMAT, filemtime(filename));
+
+           fSendFile = true;
+           ifModSince = headerList["IF-MODIFIED-SINCE"];
+           if (isset (ifModSince))
+           {
+               // print ("Check modification ",ifModSince, " vs. ", lastModified );
+               if (!strcmp (ifModSince, lastModified)) {
+                   clientWrite (client, "HTTP/1.1 304 Not Modified\r\nServer: V1 HTTP-Server\r\nDate:".gmdate (HTTP_DATE_FORMAT)."\r\nLast-Modified:".lastModified."\r\nContent-Length:".fileSize."\r\nContent-Type: ".mimeType."\r\nConnection:close\r\n\r\n", ssl);
+                   fSendFile = false;
+               }
+           }
+           if (fSendFile) {
+               clientWrite (client, "HTTP/1.1 200 OK\r\nServer: V1 HTTP-Server\r\nDate:".gmdate (HTTP_DATE_FORMAT)."\r\nLast-Modified:".lastModified."\r\nContent-Length:".fileSize."\r\nContent-Type: ".mimeType."\r\nConnection:close\r\n\r\n", ssl);
+
+               // Send the file
+               fh = null;
+               if (fh = fopen (filename, "r")) {
+                   str = "";
+                   while (!feof (fh)) {
+                       len = fread (fh, str);
+                       clientWriteLen (client, str, len, ssl);
+                   }
+                   fclose (fh);
+               }
+           }
+       }
+   }
+   else
+   if (fRedirect) {
+       clientWrite (client, "HTTP/1.1 301 Moved permanently\r\nServer: V1 HTTP-Server\r\nConnection:close\r\nLocation: ".path."\r\n\r\n", ssl);
+   }
+   else {
+       // Send HTTP status 404 Not found
+       clientWrite (client, "HTTP/1.1 404 Not Found\r\nServer: V1 HTTP-Server\r\nConnection:close\r\nContent-Type: text/html\r\n\r\n".path." not found on this server.\r\n\r\n", ssl);
+   }
+
+   // Close connection and finish thread
+   if (ssl)
+       SSL_free (ssl);
+   fclose (client);
+}
+
+
+function port80Thread (fh) {
+   global fExitAll;
+
+   currThreadIdx = 0;
+   threadList = array ();
+
+   fh2 = null;
+
+   while (!fExitAll &amp;amp;&amp;amp; (fh2 = fsockaccept (fh, RECV_TIMEOUT))) {
+       // print ("Connection from ", fsockip (fh2), " / ", gethostbyaddr(fsockip (fh2)));
+
+       // Get current thread
+       do {
+           if (currThreadIdx&amp;gt;MAX_THREADS)
+               currThreadIdx = 0;
+           if (isset (threadList[currThreadIdx])) {
+               if (!thread_is_active (threadList[currThreadIdx])) {
+                   thread_close (threadList[currThreadIdx]);
+                   break;
+               }
+           }
+           else {
+               break;
+           }
+
+           currThreadIdx++;
+           if (currThreadIdx&amp;gt;MAX_THREADS) {
+               // print ("Server seems busy.");
+               sleep (10); // Wait until thread is available
+           }
+       } while (true);
+
+       // Create new thread
+       t = thread_create ("workerThread", fh2);
+       threadList[currThreadIdx]=t;
+       thread_start (t, false); // false = dont wait until thread is running
+   }
+
+   fclose (fh);
+}
+
+
+function port443Thread (fh) {
+   global fExitAll, serverCertList;
+
+   currThreadIdx = 0;
+   threadList = array ();
+
+   // Create SSL Context
+   ctx = SSL_CTX_new ("TLS_server_method");
+
+   if (!is_file (CERT_DIR."/".SERVER_HOST.".crt")) {
+       // Create self signed
+       if (!SSL_create_selfsigned_cert (CERT_DIR."/".SERVER_HOST.".crt", CERT_DIR."/".SERVER_HOST.".key" , SERVER_HOST, 315360000, "sha256", 2048)) {
+           print ("Cannot create self signed certificate for ".SERVER_HOST);
+           exit (1);
+       }
+   }
+
+   if (!SSL_CTX_load_cert (ctx, CERT_DIR."/".SERVER_HOST.".crt", CERT_DIR."/".SERVER_HOST.".key")) {
+       print ("Cannot load SSL certificate ", CERT_DIR."/".SERVER_HOST.".crt");
+       exit (1);
+   }
+   serverCertList[SERVER_HOST]=ctx;
+
+   SSL_CTX_set_tlsext_servername_callback (ctx, "servernameCallback");
+
+   fh2 = null;
+   while (!fExitAll &amp;amp;&amp;amp; (fh2 = fsockaccept (fh, RECV_TIMEOUT))) {
+       // print ("Connection from ", fsockip (fh2), " / ", gethostbyaddr(fsockip (fh2)));
+
+       // Create SSL
+       ssl = SSL_new (ctx);
+
+       // Get current thread
+       do {
+           if (currThreadIdx&amp;gt;MAX_THREADS)
+               currThreadIdx = 0;
+           if (isset (threadList[currThreadIdx])) {
+               if (!thread_is_active (threadList[currThreadIdx])) {
+                   thread_close (threadList[currThreadIdx]);
+                   break;
+               }
+           }
+           else {
+               break;
+           }
+
+           currThreadIdx++;
+           if (currThreadIdx&amp;gt;MAX_THREADS) {
+               // print ("Server seems busy.");
+               sleep (10); // Wait until thread is available
+           }
+       } while (true);
+
+       // Create new thread
+       t = thread_create ("workerThread", fh2, ssl);
+       threadList[currThreadIdx]=t;
+       thread_start (t, false); // false = dont wait until thread is running
+   }

-  if (ssl) {
-    SSL_set_fd (ssl, client);
-    if (!SSL_accept (ssl)) {
-      // SSL problems
-      SSL_free (ssl);
-      fclose (client);
-      return; 
-    }
-  }
-
-  lineIdx = 0, contentLength=0, headerList=array ();
-  
-  // Read the HTTP headers
-  line = "";
-  while (clientReadln (client, line, ssl)) {
-    if (lineIdx==0) {
-      assign (method, uri, protocol) = explode (" ", line);
-    }
-    else {
-      if ((p=strpos (line, ":"))!==false) {
-        header = strtoupper (trim (substr(line,0,p)));
-        value = trim (substr(line,p+1));
-        if (header=="CONTENT-LENGTH")
-            contentLength = value;
-        headerList[header]=value;
-      }
-    }
-    if (empty (line))
-      break;
-    lineIdx++;
-  }
-    
-  if (!isset (uri)) {
-    // No URI given, close connection and finish thread
-    if (ssl)
-      SSL_free (ssl);
-    fclose (client);
-    return;
-  }
-  
-  // Decode URI and get path
-  uri = url_decode (uri);
-  queryString = "";
-  p = strpos (uri, '?');
-  if (p!==false) {
-   queryString = substr (uri, p+1, strlen (uri)-p-1);
-   path = substr (uri, 0, p);
-  }
-  else {
-   path = uri;
-  }
-  
-  fFound = false;
-  
-  // Check for auto index files
-  if (!is_file (docPath.path)) {
-    autoIndexList = array ("index.html", "index.v1", "index.htm");
-    foreach (autoIndexList as autoFile) {
-       path2=path."/".autoFile;
-       if (is_file (docPath.path2)) {
-           path = path."/".autoFile;
-        fFound = true;
-           break;
-       }
-    }
-  }
-  else {
-    fFound = true;
-  }
-  
-  // Handle the filename
-  filename = docPath."/".path;
-  fileSize = 0;
-  if (fFound) {
-    fileSize = filesize (filename);
-  }
-  // Check if filename is outside docPath for security reasons
-  realFilename = realpath (filename);
-  if (fFound &amp;amp;&amp;amp; fileSize&amp;gt;0 &amp;amp;&amp;amp; strpos (realFilename, realDocPath)!==0) {
-    // Send HTTP status forbidden
-    clientWrite (client, "HTTP/1.1 403 Forbidden\r\nServer: V1 HTTP-Server\r\nConnection:close\r\nContent-Type: text/html\r\n\r\nPath points outside home directory.", ssl);    
-  }
-  else
-  if (fFound) {
-    // Get MIME type from file extension
-    pi = pathinfo (filename);
-    fileExt = strtolower (pi["extension"]);            
-    mimeType = mimeTypeList[fileExt];
-    if (empty (mimeType))
-      mimeType = "text/html";
-  
-    if (fileExt=="v1") 
-    {
-      // Execute V1 Script as CGI
-      output = "", retCode = 0;
-      envStr = "QUERY_STRING=".queryString;
-      envStr.="\0";
-      envStr.='CONTENT_TYPE='.headerList["CONTENT-TYPE"];
-      envStr.="\0";
-      envStr.='SCRIPT_FILENAME='.filename;
-      envStr.="\0";
-      envStr.='SCRIPT_NAME='.path;
-      envStr.="\0";
-      envStr.='DOCUMENT_ROOT='.docPath;
-      envStr.="\0";
-      envStr.='REQUEST_URI='.uri;
-      envStr.="\0\0";
-
-      cmd = './v1 -w "'.filename.'"';
-      if (exec (cmd, output, retCode, (contentLength&amp;gt;0 ? (ssl ? ssl : client) : null), contentLength, envStr)) {                               
-        clientWrite (client, "HTTP/1.1 200 OK\r\nServer: V1 HTTP-Server\r\n", ssl);
-        clientWrite (client, output, ssl);
-      }
-      else {
-        clientWrite (client, "HTTP/1.1 500 Internal Server Error\r\nServer: V1 HTTP-Server\r\n\r\nCannot execute: ".cmd, ssl);                         
-      }
-    }
-    else {
-      // Send file HTTP status 200 OK      
-      lastModified = gmdate (HTTP_DATE_FORMAT, filemtime(filename));
-      
-      fSendFile = true;
-      ifModSince = headerList["IF-MODIFIED-SINCE"]; 
-      if (isset (ifModSince))
-      {    
-          // print ("Check modification ",ifModSince, " vs. ", lastModified );
-          if (!strcmp (ifModSince, lastModified)) {                  
-              clientWrite (client, "HTTP/1.1 304 Not Modified\r\nServer: V1 HTTP-Server\r\nDate:".gmdate (HTTP_DATE_FORMAT)."\r\nLast-Modified:".lastModified."\r\nContent-Length:".fileSize."\r\nContent-Type: ".mimeType."\r\nConnection:close\r\n\r\n", ssl);
-              fSendFile = false;
-          }
-      }
-      if (fSendFile) {
-        clientWrite (client, "HTTP/1.1 200 OK\r\nServer: V1 HTTP-Server\r\nDate:".gmdate (HTTP_DATE_FORMAT)."\r\nLast-Modified:".lastModified."\r\nContent-Length:".fileSize."\r\nContent-Type: ".mimeType."\r\nConnection:close\r\n\r\n", ssl);
-  
-         // Send the file
-        fh = null;
-        if (fh = fopen (filename, "r")) {
-          str = "";
-          while (!feof (fh)) {
-            len = fread (fh, str);
-            clientWriteLen (client, str, len, ssl);
-          }
-          fclose (fh);
-        }
-      }
-    }
-  }
-  else {
-    // Send HTTP status 404 Not found
-    clientWrite (client, "HTTP/1.1 404 Not Found\r\nServer: V1 HTTP-Server\r\nConnection:close\r\nContent-Type: text/html\r\n\r\n".path." not found on this server.", ssl);
-  }
-
-  // Close connection and finish thread
-  if (ssl)
-    SSL_free (ssl);
-  fclose (client);
-}
-
-
-function port80Thread (fh) {
-  global fExitAll;
-    
-  currThreadIdx = 0;
-  threadList = array ();
-  
-  fh2 = null;
-
-  while (!fExitAll &amp;amp;&amp;amp; (fh2 = fsockaccept (fh, RECV_TIMEOUT))) {
-    // print ("Connection from ", fsockip (fh2), " / ", gethostbyaddr(fsockip (fh2))); 
-        
-    // Get current thread
-    do {
-      if (currThreadIdx&amp;gt;MAX_THREADS)
-        currThreadIdx = 0;  
-      if (isset (threadList[currThreadIdx])) {                
-        if (!thread_is_active (threadList[currThreadIdx])) {
-          thread_close (threadList[currThreadIdx]);                    
-          break;              
-        }            
-      }
-      else {
-        break;
-      }
-
-      currThreadIdx++;        
-      if (currThreadIdx&amp;gt;MAX_THREADS) {
-        // print ("Server seems busy.");
-        sleep (10); // Wait until thread is available
-      }
-    } while (true);
-
-    // Create new thread
-    t = thread_create ("workerThread", fh2); 
-    threadList[currThreadIdx]=t;  
-    thread_start (t, false); // false = dont wait until thread is running
-    
-  }
-  fclose (fh);
-}
-
-
-function port443Thread (fh) {
-  global fExitAll;
-  
-  currThreadIdx = 0;
-  threadList = array ();
-
-  // Create SSL Context
-  ctx = SSL_CTX_new ("TLSv1_2_server_method");
-  if (!SSL_CTX_load_cert (ctx, CERT_DIR."/".SERVER_HOST.".crt", CERT_DIR."/".SERVER_HOST.".key")) {
-    print ("Cannot load SSL certificate ", CERT_DIR."/".SERVER_HOST.".crt");
-    exit (1);
-  }
-  SSL_CTX_set_tlsext_servername_callback (ctx, "servernameCallback");
-  
-  fh2 = null;
-  while (!fExitAll &amp;amp;&amp;amp; (fh2 = fsockaccept (fh, RECV_TIMEOUT))) {
-    // print ("Connection from ", fsockip (fh2), " / ", gethostbyaddr(fsockip (fh2))); 
-    
-   // Create SSL
-    ssl = SSL_new (ctx); 
-    
-    // Get current thread
-    do {
-      if (currThreadIdx&amp;gt;MAX_THREADS)
-        currThreadIdx = 0;  
-      if (isset (threadList[currThreadIdx])) {                
-        if (!thread_is_active (threadList[currThreadIdx])) {
-          thread_close (threadList[currThreadIdx]);                    
-          break;              
-        }            
-      }
-      else {
-        break;
-      }
-
-      currThreadIdx++;        
-      if (currThreadIdx&amp;gt;MAX_THREADS) {
-        // print ("Server seems busy.");
-        sleep (10); // Wait until thread is available
-      }
-    } while (true);
-  
-    // Create new thread    
-    t = thread_create ("workerThread", fh2, ssl); 
-    threadList[currThreadIdx]=t;  
-    thread_start (t, false); // false = dont wait until thread is running
-  }
-  SSL_CTX_free (ctx);  
-  fclose (fh);
+   SSL_CTX_free (ctx);
+   fclose (fh);
 }

 // Create Port 80
-fh = fsockserver (SERVER_HOST, SERVER_PORT);
-if (!fh) {
-  print ("Cannot create HTTP-Server on ",  SERVER_HOST, ":", SERVER_PORT);
-  exit (1);
-}
-else {
-  print ("HTTP-Server created on ",  fsockip (fh), ":", fsockport(fh));
-  thread_start (thread_create ("port80Thread", fh));
-}
-
+fh = null;
+httpThread = null;
+if (SERVER_PORT&amp;gt;0) {
+   fh = fsockserver (SERVER_HOST, SERVER_PORT, 0);
+   if (!fh) {
+       print ("Cannot create HTTP-Server on ",  SERVER_HOST, ":", SERVER_PORT);
+       exit (1);
+   }
+   else {
+       print ("HTTP-Server created on ",  fsockip (fh), ":", fsockport(fh));
+       thread_start (httpThread = thread_create ("port80Thread", fh));
+   }
+}
+
+fh2 = null;
+httpsThread = null;
 if (SERVER_SSL_PORT&amp;gt;0) {
-  // Create Port 443
-  fh2 = fsockserver (SERVER_HOST, SERVER_SSL_PORT);
-  if (!fh2) {
-    print ("Cannot create HTTP-Server on ",  SERVER_HOST, ":", SERVER_SSL_PORT);
-    exit (1);
-  }
-  else {
-    print ("HTTP-Server created on ",  fsockip (fh2), ":", fsockport(fh2));
-    thread_start (thread_create ("port443Thread", fh2));
-  }
+   // Create Port 443
+   fh2 = fsockserver (SERVER_HOST, SERVER_SSL_PORT);
+   if (!fh2) {
+       print ("Cannot create HTTP-Server on ",  SERVER_HOST, ":", SERVER_SSL_PORT);
+       exit (1);
+   }
+   else {
+       print ("HTTP-Server created on ",  fsockip (fh2), ":", fsockport(fh2));
+       thread_start (httpsThread = thread_create ("port443Thread", fh2));
+   }
 }

 // Maintenance thread
-thread_start (thread_create ("maintenanceThread"));
-while (!fExitAll)
-  sleep (1000);
-
+thread_start (mainThread = thread_create ("maintenanceThread"));
+while (true) {
+       sleep (1000);
+}
 ?&amp;gt;

 ~~~
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Kalle</dc:creator><pubDate>Sun, 21 Dec 2025 16:35:30 -0000</pubDate><guid>https://sourceforge.net19f79601380ffd8d8b340cd999c8af62245036fd</guid></item><item><title>HTTP-Server modified by Kalle</title><link>https://sourceforge.net/p/v1-script/wiki/HTTP-Server/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v45
+++ v46
@@ -315,8 +315,7 @@
   threadList = array ();

   // Create SSL Context
-  ctx = SSL_CTX_new ("SSLv23_method"); // TLSv1_2_server_method, SSLv23_method
-  // SSL_CTX_set_cipher_list (ctx, "HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4");    
+  ctx = SSL_CTX_new ("TLSv1_2_server_method");
   if (!SSL_CTX_load_cert (ctx, CERT_DIR."/".SERVER_HOST.".crt", CERT_DIR."/".SERVER_HOST.".key")) {
     print ("Cannot load SSL certificate ", CERT_DIR."/".SERVER_HOST.".crt");
     exit (1);
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Kalle</dc:creator><pubDate>Wed, 01 May 2024 13:25:47 -0000</pubDate><guid>https://sourceforge.netfd6b8cac8a69b7f9417d960a5de79f1db116bfef</guid></item><item><title>HTTP-Server modified by Kalle</title><link>https://sourceforge.net/p/v1-script/wiki/HTTP-Server/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v44
+++ v45
@@ -354,7 +354,7 @@
     // Create new thread    
     t = thread_create ("workerThread", fh2, ssl); 
     threadList[currThreadIdx]=t;  
-    thread_start (t);    
+    thread_start (t, false); // false = dont wait until thread is running
   }
   SSL_CTX_free (ctx);  
   fclose (fh);
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Kalle</dc:creator><pubDate>Thu, 24 Dec 2020 16:10:17 -0000</pubDate><guid>https://sourceforge.netca69fdb8d994d2c91865f0e276b8e93f37bce159</guid></item><item><title>HTTP-Server modified by Kalle</title><link>https://sourceforge.net/p/v1-script/wiki/HTTP-Server/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v43
+++ v44
@@ -301,7 +301,7 @@
     // Create new thread
     t = thread_create ("workerThread", fh2); 
     threadList[currThreadIdx]=t;  
-    thread_start (t);
+    thread_start (t, false); // false = dont wait until thread is running

   }
   fclose (fh);
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Kalle</dc:creator><pubDate>Thu, 24 Dec 2020 16:09:15 -0000</pubDate><guid>https://sourceforge.net0fbee6e4deb01c9bf83530b933f2a333283d30a1</guid></item><item><title>HTTP-Server modified by Kalle</title><link>https://sourceforge.net/p/v1-script/wiki/HTTP-Server/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v42
+++ v43
@@ -1,5 +1,4 @@
- `
- ~~~
+~~~
 :::php
  &amp;lt;starturl&amp;gt;
+  Usage: v1 webserver.v1 [docPath] [startURL]
 */

 error_reporting (0); // 1 to show all warnings
@@ -389,5 +388,7 @@
 thread_start (thread_create ("maintenanceThread"));
 while (!fExitAll)
   sleep (1000);
+
 ?&amp;gt;
+
 ~~~
&amp;lt;/starturl&amp;gt;&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Kalle</dc:creator><pubDate>Thu, 15 Nov 2018 21:04:24 -0000</pubDate><guid>https://sourceforge.net5580a60d98a6d428a1a4cbc4e9c6e3de0a785822</guid></item><item><title>HTTP-Server modified by Kalle</title><link>https://sourceforge.net/p/v1-script/wiki/HTTP-Server/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v41
+++ v42
@@ -1,3 +1,4 @@
+ `
  ~~~
 :::php
 
&lt;/pre&gt;&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Kalle</dc:creator><pubDate>Thu, 15 Nov 2018 21:03:58 -0000</pubDate><guid>https://sourceforge.netd5f2a951dbf594d09ac45d3a0de8aad1fa33845a</guid></item><item><title>HTTP-Server modified by Kalle</title><link>https://sourceforge.net/p/v1-script/wiki/HTTP-Server/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v40
+++ v41
@@ -1,4 +1,4 @@
-* ~~~
+ ~~~
 :::php
 
&lt;/pre&gt;&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Kalle</dc:creator><pubDate>Thu, 15 Nov 2018 21:03:25 -0000</pubDate><guid>https://sourceforge.net81f72ad105b13874f70a45e2443c4e3e1279df76</guid></item><item><title>HTTP-Server modified by Kalle</title><link>https://sourceforge.net/p/v1-script/wiki/HTTP-Server/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v39
+++ v40
@@ -8,7 +8,7 @@

   Feel free to enhance!

-  Usage: v1 webserver.v1 [docPath] [startURL]
+  Usage: v1 webserver.v1 &amp;lt;docpath&amp;gt; &amp;lt;starturl&amp;gt;
 */

 error_reporting (0); // 1 to show all warnings
&amp;lt;/starturl&amp;gt;&amp;lt;/docpath&amp;gt;&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Kalle</dc:creator><pubDate>Thu, 15 Nov 2018 21:02:59 -0000</pubDate><guid>https://sourceforge.netcf714fedc8d1c3a2f6817938dfae640ddf55e752</guid></item><item><title>HTTP-Server modified by Kalle</title><link>https://sourceforge.net/p/v1-script/wiki/HTTP-Server/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v38
+++ v39
@@ -1,6 +1,16 @@
-~~~
+* ~~~
 :::php
 
&lt;/pre&gt;&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Kalle</dc:creator><pubDate>Thu, 15 Nov 2018 21:02:12 -0000</pubDate><guid>https://sourceforge.netd1e98fafd85945c158273cc4b61a734806225f0f</guid></item></channel></rss>