feat(core): FILIUS' web server and web browser after Java, measured against Java

The servers share ServerAnwendung's frame (server.ts); the web server serves
/webserver with virtual hosts, the browser loads a page and its images over
one connection to port 80 (web.ts); HTTP in Java's text form (http.ts).
WebRun records eleven stories on the new web-lan network, with the server's
files; webJava.test.ts plays them card by card. A program's close is a
request, as Java's schliessen. Not taken from Java: /../ serving any file of
the host; an unreadable request closing the connection without a word.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-01 16:53:00 +00:00
co-authored by Claude Opus 5.5
parent de3a1d4dfe
commit 4cd5749350
33 changed files with 53601 additions and 216 deletions
+44
View File
@@ -0,0 +1,44 @@
// Base64 as FILIUS writes and reads it (filius.rahmenprogramm.Base64,
// iHarder Base64 2.x): how image and other binary files are kept in Java's
// file system, and how its web server sends them.
import { base64Encode } from './swiftString.js';
/**
* FILIUS's Base64.encodeBytes: a line break after every 76 characters —
* also after the last full line — then the padded rest.
*/
export function javaBase64(bytes: Uint8Array): string {
const full = bytes.length - (bytes.length % 3);
let text = '';
for (let offset = 0; offset < full; offset += 57) {
const end = Math.min(offset + 57, full);
text += base64Encode(bytes.subarray(offset, end));
if (end - offset === 57) text += '\n';
}
return text + base64Encode(bytes.subarray(full));
}
const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
/**
* Base64.decode: white space skipped; undefined where a character is none
* of Base64's or the length does not come out (iHarder throws).
*/
export function javaBase64Decode(text: string): Uint8Array | undefined {
const characters = text.replace(/[ \t\r\n\f]/g, '');
if (characters.length % 4 !== 0) return undefined;
const bytes: number[] = [];
for (let index = 0; index < characters.length; index += 4) {
const quad = characters.slice(index, index + 4);
const values = [...quad].map((character) => (character === '=' ? 0 : ALPHABET.indexOf(character)));
if (values.some((value) => value < 0)) return undefined;
const padding = quad.endsWith('==') ? 2 : quad.endsWith('=') ? 1 : 0;
if (quad.slice(0, 4 - padding).includes('=') || (padding > 0 && index + 4 < characters.length)) return undefined;
const chunk = (values[0]! << 18) | (values[1]! << 12) | (values[2]! << 6) | values[3]!;
bytes.push((chunk >> 16) & 255);
if (padding < 2) bytes.push((chunk >> 8) & 255);
if (padding < 1) bytes.push(chunk & 255);
}
return new Uint8Array(bytes);
}