fix(fls): follow Java's formats, not Java's errors
Java stays the reference for the .fls format, but its errors are no longer copied. The Java oracle still measures Java as it is; each deliberate departure is named in the tests with its reason (JAVA_BUGS) and must really depart. The corpus - what Java itself writes - still reads exactly as in Java. - /dns/hosts: a label may start with a digit, holds no backslash, and the last one is not all digits (RFC 1123, RFC 3696); A, MX and NS are read in any case (RFC 4343); a negative TTL is invalid, so 3600 (RFC 2181). Also for the e-mail server's domain. - /mailserver/konten.txt: empty fields count (Java's StringTokenizer skips them and shifts the rest, so an empty password breaks the account); a short line alone is left out, with a warning (Java throws for the whole file); a message keeps an empty text or subject (Java's split loses it); a ";" in an unescaped subject stays in the message; CRLF lines. - /konten.txt: the last complete line is the account, also with an empty address (Java takes the last line and loses the account); CRLF lines. - Static DHCP assignments: a broken entry alone is left out (Java loses every entry after it). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -27,19 +27,18 @@
|
||||
// not know Java's constructors and sees a placeholder per path; they are
|
||||
// merged here.
|
||||
|
||||
import { JAVA_DOMAIN } from './dnsHosts.js';
|
||||
import { isDomainName } from './dnsHosts.js';
|
||||
import {
|
||||
EMAIL_CLIENT_FILE,
|
||||
EMAIL_SERVER_FILE,
|
||||
javaContacts,
|
||||
javaEmailAccounts,
|
||||
javaEmails,
|
||||
readJavaEmailClientFile,
|
||||
readJavaEmailServerFile,
|
||||
readEmailClientFile,
|
||||
readEmailServerFile,
|
||||
type JavaContact,
|
||||
type JavaEmail,
|
||||
type JavaEmailAccount,
|
||||
type JavaFailure,
|
||||
} from './javaEmail.js';
|
||||
import { javaFileContent } from './javaFileSystem.js';
|
||||
import {
|
||||
@@ -151,16 +150,16 @@ export interface FlsApplication {
|
||||
maxPeers?: number | null;
|
||||
/** Firewall: the personal firewall. */
|
||||
firewall?: FlsFirewall;
|
||||
/** EmailServer: its domain (Java keeps "filius.de" for one its pattern rejects). */
|
||||
/** EmailServer: its domain ("filius.de" for one that is not a domain name, as Java's setter keeps it). */
|
||||
mailDomain?: string;
|
||||
/** EmailServer: the accounts of the bean list. */
|
||||
beanAccounts?: JavaEmailAccount[];
|
||||
/**
|
||||
* EmailServer: the accounts of /mailserver/konten.txt, which Java reads at
|
||||
* every simulation start — null without the file (Java then starts with
|
||||
* none), a failure where Java throws.
|
||||
* none).
|
||||
*/
|
||||
fileAccounts?: JavaEmailAccount[] | JavaFailure | null;
|
||||
fileAccounts?: JavaEmailAccount[] | null;
|
||||
/** EmailAnwendung: its folders (Java's empfangene, gesendete, erstellte Nachrichten). */
|
||||
received?: JavaEmail[];
|
||||
sent?: JavaEmail[];
|
||||
@@ -313,10 +312,10 @@ function applications(map: JavaValue | undefined, root: FlsFileTree, warn: Warn)
|
||||
case 'filius.software.email.EmailServer': {
|
||||
entry.isActive = boolean(at('aktiv'), false, 'EmailServer aktiv', warn);
|
||||
const domain = optionalString(at('mailDomain'), 'EmailServer mailDomain', warn);
|
||||
entry.mailDomain = typeof domain === 'string' && JAVA_DOMAIN.test(domain) ? domain : 'filius.de';
|
||||
entry.mailDomain = typeof domain === 'string' && isDomainName(domain) ? domain : 'filius.de';
|
||||
entry.beanAccounts = javaEmailAccounts(at('listeBenutzerkonten'), warn);
|
||||
const file = javaFileContent(root, EMAIL_SERVER_FILE);
|
||||
entry.fileAccounts = file === undefined ? null : readJavaEmailServerFile(file);
|
||||
entry.fileAccounts = file === undefined ? null : readEmailServerFile(file, warn);
|
||||
break;
|
||||
}
|
||||
case 'filius.software.email.EmailAnwendung': {
|
||||
@@ -325,7 +324,7 @@ function applications(map: JavaValue | undefined, root: FlsFileTree, warn: Warn)
|
||||
entry.drafts = javaEmails(at('erstellteNachrichten'), warn);
|
||||
entry.addressBook = javaContacts(at('adressbuch'), warn);
|
||||
const file = javaFileContent(root, EMAIL_CLIENT_FILE);
|
||||
entry.fileAccount = file === undefined ? null : readJavaEmailClientFile(file);
|
||||
entry.fileAccount = file === undefined ? null : readEmailClientFile(file, warn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -406,16 +405,17 @@ function dhcpServer(server: JavaValue | undefined, warn: Warn): FlsDhcpServer {
|
||||
|
||||
/**
|
||||
* setStaticAssignedAddresses: each entry split at whitespace (StringUtils.split),
|
||||
* MAC and IP from the first two parts. An entry with fewer throws inside the
|
||||
* loop — XMLDecoder swallows it, and the entries after it are lost.
|
||||
* MAC and IP from the first two parts. An entry with fewer makes Java throw
|
||||
* inside the loop — XMLDecoder swallows it, and the entries after it are
|
||||
* lost. That error is not copied: such an entry alone is left out.
|
||||
*/
|
||||
function staticAssignments(list: JavaValue | undefined, warn: Warn): { mac: string; ip: string }[] {
|
||||
const result: { mac: string; ip: string }[] = [];
|
||||
for (const entry of listItems(list)) {
|
||||
const parts = typeof entry === 'string' ? javaWhitespaceSplit(entry) : [];
|
||||
if (parts.length < 2) {
|
||||
warn(`DHCPServer: static assignment ${describe(entry)} has no MAC and IP; Java stops reading here`);
|
||||
break;
|
||||
warn(`DHCPServer: static assignment ${describe(entry)} has no MAC and IP, left out`);
|
||||
continue;
|
||||
}
|
||||
result.push({ mac: parts[0]!, ip: parts[1]! });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user