A project's own applications (classes under projekt/anwendungen, installed on a host) are no longer left out. The decoder now keeps the Java type of every primitive — at setters, constructor and call arguments, also through shared ids like Integer0 — and which properties an object's own getter made. beanCapture.ts turns a decoded bean back into what the writer writes, with the node's system software as a mark the writer replaces by the system software it writes; what the format cannot say is refused, not guessed (an unresolved value, a Field, a factory-made object, an object a getter reaches elsewhere in the file). The reader keeps own applications as captured beans; the corpus no longer warns. The capture first took a setter with another object's getter result for an own getter; the round-trip test found it. The Java oracle did not show whether an application runs on its node's system software, so a mutation writing the mark instead survived; it now reports onItsSystem (true for all 192 applications of the corpus). Checked by Java: from the files written again, FILIUS loads Accumulator and Broadcast installed, switched on and on their node's system software, as in the original. The round-trip test covers every primitive, null, a class, an array, shared objects, getter chains, constructed elements, map reads and static constants. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
577 lines
23 KiB
TypeScript
577 lines
23 KiB
TypeScript
// Every corpus file, read and written again: Java FILIUS loads the written
|
|
// file (tools/java-oracle, written.java.json) to the same topology as the
|
|
// original (corpus.java.json) — devices, names, positions, interfaces,
|
|
// system software, files, applications with their e-mail accounts,
|
|
// messages and address books, cables and documentation — up to one Java
|
|
// error the writer does not copy (RECIPIENTS_AS_STRINGS). Java against Java: no mapping of this package stands
|
|
// between the two.
|
|
//
|
|
// UPDATE_WRITTEN=1 writes the files to test/written/ (not checked in); the
|
|
// Java oracle then loads them and records each file's SHA-256, which must
|
|
// match what the writer makes now.
|
|
|
|
import { createHash } from 'node:crypto';
|
|
import { mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
|
|
import { dirname, join, relative } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
import { describe, expect, it } from 'vitest';
|
|
import { decodeJavaBeans, readFlsArchive, readTopology, writeFlsArchive } from '../src/index.js';
|
|
import type { JavaEmail } from '../src/javaEmail.js';
|
|
import { writeTopologyXml, type TopologyToWrite } from '../src/topologyWriter.js';
|
|
|
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
const corpusRoot = join(here, '../../../corpus');
|
|
const writtenRoot = join(here, 'written');
|
|
|
|
function flsFiles(directory: string): string[] {
|
|
return readdirSync(directory).flatMap((name) => {
|
|
const path = join(directory, name);
|
|
if (statSync(path).isDirectory()) return flsFiles(path);
|
|
return name.endsWith('.fls') ? [path] : [];
|
|
});
|
|
}
|
|
|
|
type JavaNode = {
|
|
class: string;
|
|
name: string | null;
|
|
bounds: number[];
|
|
useIpAsName: boolean;
|
|
useMacAsName: boolean;
|
|
ports: unknown;
|
|
system: Record<string, unknown>;
|
|
};
|
|
type JavaFile = { success: boolean; nodes: JavaNode[]; cables: unknown[]; documentation: unknown[]; sha256?: string };
|
|
|
|
const original = JSON.parse(readFileSync(join(corpusRoot, 'corpus.java.json'), 'utf8')) as Record<string, JavaFile>;
|
|
const written = JSON.parse(readFileSync(join(here, 'written.java.json'), 'utf8')) as Record<string, JavaFile>;
|
|
|
|
/**
|
|
* The Java error the writer does not copy: older files keep e-mail
|
|
* recipients as strings, which Java puts into its typed lists unchecked (its
|
|
* e-mail window then fails on them). The writer writes the AddressEntry
|
|
* Java's own AddressEntry(String) makes of each — the oracle reports it
|
|
* next to the string — and leaves a null recipient out.
|
|
*/
|
|
const RECIPIENTS_AS_STRINGS = ['java-examples/man-in-the-middle.fls'];
|
|
|
|
/** Java's view of the original as the writer means it: each recipient as Java reads its string, none null. */
|
|
function withRecipientsRead(value: unknown, key = ''): unknown {
|
|
if (Array.isArray(value)) {
|
|
if (key === 'empfaenger' || key === 'cc' || key === 'bcc') {
|
|
return value.filter((entry) => entry !== null).map((entry) => (entry[0] === 'string' ? entry[2] : entry));
|
|
}
|
|
return value.map((item) => withRecipientsRead(item));
|
|
}
|
|
if (value !== null && typeof value === 'object') {
|
|
return Object.fromEntries(Object.entries(value).map(([name, item]) => [name, withRecipientsRead(item, name)]));
|
|
}
|
|
return value;
|
|
}
|
|
|
|
/**
|
|
* The topology of Java's view: the label's position, not its size, which
|
|
* Java works out itself.
|
|
*/
|
|
function topologyOf(view: JavaFile) {
|
|
return {
|
|
success: view.success,
|
|
nodes: view.nodes.map((node) => ({
|
|
class: node.class,
|
|
name: node.name,
|
|
position: node.bounds.slice(0, 2),
|
|
useIpAsName: node.useIpAsName,
|
|
useMacAsName: node.useMacAsName,
|
|
ports: node.ports,
|
|
system: node.system,
|
|
})),
|
|
cables: view.cables,
|
|
documentation: view.documentation,
|
|
};
|
|
}
|
|
|
|
describe('the topology written again, as Java loads it', () => {
|
|
for (const file of flsFiles(corpusRoot)) {
|
|
const name = relative(corpusRoot, file);
|
|
it(name, () => {
|
|
const contents = readFlsArchive(new Uint8Array(readFileSync(file)));
|
|
const topology = readTopology(decodeJavaBeans(contents.configurationXml));
|
|
// With the archive's other entries: the classes of the project's own applications.
|
|
const archive = writeFlsArchive(new TextEncoder().encode(writeTopologyXml(topology)), contents.supplementalEntries);
|
|
if (process.env.UPDATE_WRITTEN === '1') {
|
|
mkdirSync(dirname(join(writtenRoot, name)), { recursive: true });
|
|
writeFileSync(join(writtenRoot, name), archive);
|
|
}
|
|
const java = written[name];
|
|
expect(java?.sha256, 'written.java.json is not about this output: UPDATE_WRITTEN=1, then npm run oracle:java').toBe(
|
|
createHash('sha256').update(archive).digest('hex'),
|
|
);
|
|
expect(topologyOf(java!)).toEqual(topologyOf(withRecipientsRead(original[name]!) as JavaFile));
|
|
});
|
|
}
|
|
|
|
it('departs from Java only where it keeps recipients as strings', () => {
|
|
const changed = flsFiles(corpusRoot)
|
|
.map((file) => relative(corpusRoot, file))
|
|
.filter((name) => JSON.stringify(withRecipientsRead(original[name])) !== JSON.stringify(original[name]));
|
|
expect(changed).toEqual(RECIPIENTS_AS_STRINGS);
|
|
});
|
|
});
|
|
|
|
/**
|
|
* An e-mail with a sender without address, recipients as entries, as the
|
|
* string an older file keeps (read as AddressEntry(String) reads it) and
|
|
* null (left out), a text with CR, and a date.
|
|
*/
|
|
const SYNTHETIC_MAIL: JavaEmail = {
|
|
sender: { name: 'Anna', mailAddress: null },
|
|
to: [{ name: null, mailAddress: 'ben@schule.de' }, 'Carla <carla@schule.de>', null],
|
|
cc: [{ name: 'Dora', mailAddress: 'dora@schule.de' }],
|
|
bcc: ['eva@schule.de'],
|
|
subject: 'Hallo',
|
|
text: 'Zeile 1\r\nZeile 2',
|
|
dateReceived: '1727690000000',
|
|
isNew: true,
|
|
isDeleted: true,
|
|
isSent: false,
|
|
};
|
|
|
|
/** SYNTHETIC_MAIL as the oracle describes it after Java loaded it. */
|
|
function javaMail(changes: Record<string, unknown> = {}) {
|
|
return {
|
|
absender: ['Anna', null],
|
|
empfaenger: [[null, 'ben@schule.de'], ['Carla', 'carla@schule.de']],
|
|
cc: [['Dora', 'dora@schule.de']],
|
|
bcc: [[null, 'eva@schule.de']],
|
|
betreff: 'Hallo',
|
|
text: 'Zeile 1\r\nZeile 2',
|
|
dateReceived: '1727690000000',
|
|
neu: true,
|
|
delete: true,
|
|
versendet: false,
|
|
...changes,
|
|
};
|
|
}
|
|
|
|
/** Text a file's content may hold: markup, CR and CRLF, a tab, beyond the BMP. */
|
|
const FILE_CONTENT = '<p>a & b</p>\r\nline\rend\ttab Grüße 😀\n';
|
|
|
|
/**
|
|
* What the corpus does not have: a name set to null, useMACAsName, fewer
|
|
* ports than the constructor makes, more interfaces; a PC's SSID, routes and
|
|
* DHCP server with static assignments; a router's firewall switched on, with
|
|
* every flag away from its default and rules of every protocol, one with a
|
|
* null address; a modem's own port and address.
|
|
*/
|
|
const SYNTHETIC: TopologyToWrite = {
|
|
nodes: [
|
|
{
|
|
javaClass: 'Rechner',
|
|
name: null,
|
|
x: 10,
|
|
y: 20,
|
|
useIpAsName: false,
|
|
useMacAsName: true,
|
|
interfaces: [{ ip: '10.0.0.1', mask: '255.0.0.0', mac: 'AA:BB:CC:DD:EE:01', gateway: null, dns: '10.0.0.53', wireless: true }],
|
|
portCount: 1,
|
|
system: {
|
|
ssid: 'Lab',
|
|
manualRoutes: [['10.1.0.0', '255.255.0.0', '10.0.0.254', '10.0.0.1']],
|
|
dhcpClient: true,
|
|
dhcpServer: {
|
|
isActive: true,
|
|
lowerBound: '10.0.0.100',
|
|
upperBound: '10.0.0.199',
|
|
gateway: '10.0.0.254',
|
|
dnsServer: '10.0.0.53',
|
|
useOwnSettings: true,
|
|
staticAssignedAddresses: [{ mac: 'AA:BB:CC:DD:EE:77', ip: '10.0.0.77' }],
|
|
},
|
|
fileSystem: {
|
|
kind: 'directory',
|
|
name: '/',
|
|
children: [
|
|
{
|
|
kind: 'directory',
|
|
name: 'docs',
|
|
children: [
|
|
{ kind: 'file', name: 'a.txt', type: 'text', content: FILE_CONTENT, children: [] },
|
|
{ kind: 'directory', name: null, children: [] },
|
|
],
|
|
},
|
|
{ kind: 'file', name: 'untyped', type: null, content: null, children: [] },
|
|
{ kind: 'directory', name: 'webserver', children: [{ kind: 'file', name: 'index.html', type: 'html', content: '<p>own</p>', children: [] }] },
|
|
{ kind: 'directory', name: 'dns', children: [{ kind: 'file', name: 'hosts', type: null, content: 'a.de. A 3600 10.0.0.1\n', children: [] }] },
|
|
],
|
|
},
|
|
applications: [
|
|
{
|
|
key: 'filius.software.firewall.Firewall',
|
|
javaClass: 'filius.software.firewall.Firewall',
|
|
firewall: {
|
|
activated: false,
|
|
defaultPolicy: 1,
|
|
dropICMP: true,
|
|
filterSYNSegmentsOnly: false,
|
|
filterUdp: false,
|
|
rules: [{ srcIP: '10.0.0.0', srcMask: '255.0.0.0', destIP: '', destMask: '', port: 22, protocol: 6, action: 1 }],
|
|
},
|
|
},
|
|
{ key: 'filius.software.www.WebServer', javaClass: 'filius.software.www.WebServer', isActive: true, port: 8080, useVirtualHosts: true },
|
|
{
|
|
key: 'filius.software.dns.DNSServer',
|
|
javaClass: 'filius.software.dns.DNSServer',
|
|
isActive: true,
|
|
port: 5353,
|
|
recursiveResolutionEnabled: true,
|
|
},
|
|
{ key: 'filius.software.clientserver.ServerBaustein', javaClass: 'filius.software.clientserver.ServerBaustein', isActive: true, port: 7777 },
|
|
{
|
|
key: 'filius.software.clientserver.ClientBaustein',
|
|
javaClass: 'filius.software.clientserver.ClientBaustein',
|
|
targetAddress: '10.0.0.9',
|
|
targetPort: 7777,
|
|
},
|
|
{ key: 'filius.software.dateiaustausch.PeerToPeerAnwendung', javaClass: 'filius.software.dateiaustausch.PeerToPeerAnwendung', maxPeers: 7 },
|
|
{ key: 'filius.software.lokal.Terminal', javaClass: 'filius.software.lokal.Terminal' },
|
|
{ key: 'filius.software.lokal.TextEditor', javaClass: 'filius.software.lokal.TextEditor' },
|
|
{ key: 'filius.software.lokal.FileExplorer', javaClass: 'filius.software.lokal.FileExplorer' },
|
|
{ key: 'filius.software.lokal.ImageViewer', javaClass: 'filius.software.lokal.ImageViewer' },
|
|
{ key: 'filius.software.www.WebBrowser', javaClass: 'filius.software.www.WebBrowser' },
|
|
{
|
|
key: 'filius.software.email.EmailServer',
|
|
javaClass: 'filius.software.email.EmailServer',
|
|
isActive: true,
|
|
mailDomain: 'schule.de',
|
|
beanAccounts: [
|
|
{
|
|
username: 'anna',
|
|
password: 'geheim',
|
|
lastName: 'Muster',
|
|
firstName: '',
|
|
emailAddress: 'anna@schule.de',
|
|
pop3Server: null,
|
|
pop3Port: null,
|
|
smtpServer: null,
|
|
smtpPort: null,
|
|
messages: [SYNTHETIC_MAIL],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
key: 'filius.software.email.EmailAnwendung',
|
|
javaClass: 'filius.software.email.EmailAnwendung',
|
|
received: [SYNTHETIC_MAIL],
|
|
sent: [{ ...SYNTHETIC_MAIL, isSent: true, isNew: false }],
|
|
drafts: [{ ...SYNTHETIC_MAIL, subject: null, text: null, dateReceived: null, to: [] }],
|
|
addressBook: [
|
|
{
|
|
name: 'Muster',
|
|
firstName: 'Anna',
|
|
street: null,
|
|
houseNumber: 12,
|
|
postalCode: 20095,
|
|
city: 'Hamburg',
|
|
email: 'anna@schule.de',
|
|
phone: null,
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
},
|
|
{
|
|
javaClass: 'Switch',
|
|
name: 'S',
|
|
x: 100,
|
|
y: 20,
|
|
useIpAsName: false,
|
|
useMacAsName: false,
|
|
interfaces: [],
|
|
portCount: 3,
|
|
system: { ssid: 'S-net', retentionTime: 1234 },
|
|
},
|
|
{
|
|
javaClass: 'Vermittlungsrechner',
|
|
name: 'R',
|
|
x: 200,
|
|
y: 20,
|
|
useIpAsName: false,
|
|
useMacAsName: false,
|
|
interfaces: ['1', '2', '3'].map((octet) => ({
|
|
ip: `10.0.${octet}.1`,
|
|
mask: '255.255.255.0',
|
|
mac: `AA:BB:CC:DD:EE:1${octet}`,
|
|
gateway: '',
|
|
dns: '',
|
|
wireless: false,
|
|
})),
|
|
portCount: 3,
|
|
system: {
|
|
ripEnabled: true,
|
|
fileSystem: { kind: 'directory', name: 'root', children: [{ kind: 'directory', name: 'www.conf', children: [] }] },
|
|
templateFiles: true,
|
|
firewall: {
|
|
activated: true,
|
|
defaultPolicy: 1,
|
|
dropICMP: true,
|
|
filterSYNSegmentsOnly: false,
|
|
filterUdp: false,
|
|
rules: [
|
|
{ srcIP: '10.0.1.0', srcMask: '255.255.255.0', destIP: '', destMask: '', port: -1, protocol: -1, action: 1 },
|
|
{ srcIP: '', srcMask: '', destIP: '10.0.2.5', destMask: '255.255.255.255', port: 80, protocol: 6, action: 0 },
|
|
{ srcIP: null, srcMask: '', destIP: '', destMask: '', port: 53, protocol: 17, action: 1 },
|
|
{ srcIP: '', srcMask: '', destIP: '', destMask: '', port: -1, protocol: 1, action: 0 },
|
|
],
|
|
},
|
|
},
|
|
},
|
|
{
|
|
javaClass: 'Modem',
|
|
name: 'M',
|
|
x: 300,
|
|
y: 20,
|
|
useIpAsName: false,
|
|
useMacAsName: false,
|
|
interfaces: [],
|
|
portCount: 1,
|
|
system: { modem: { mode: 1, port: 4242, ipAddress: '192.168.1.5' } },
|
|
},
|
|
{
|
|
javaClass: 'Gateway',
|
|
name: 'G',
|
|
x: 400,
|
|
y: 20,
|
|
useIpAsName: false,
|
|
useMacAsName: false,
|
|
interfaces: ['4', '5'].map((octet) => ({
|
|
ip: `10.0.${octet}.1`,
|
|
mask: '255.255.255.0',
|
|
mac: `AA:BB:CC:DD:EE:1${octet}`,
|
|
gateway: '',
|
|
dns: '',
|
|
wireless: false,
|
|
})),
|
|
portCount: 2,
|
|
system: {
|
|
fileSystem: { kind: 'directory', name: 'own', children: [{ kind: 'file', name: 'x', type: 'text', content: 'y', children: [] }] },
|
|
templateFiles: false,
|
|
},
|
|
},
|
|
],
|
|
links: [
|
|
{ ends: [{ node: 0, port: 0 }, { node: 1, port: 2 }], wireless: false, panel: [0, 1] },
|
|
{ ends: [{ node: 2, port: 2 }, { node: 1, port: 0 }], wireless: true, panel: [2, 1] },
|
|
],
|
|
documentation: [{ type: 1, text: null, x: 5, y: 6, width: 70, height: 80, color: null, font: null }],
|
|
};
|
|
|
|
/** The DHCP server as every IP stack's constructor leaves it. */
|
|
const JAVA_DHCP_DEFAULTS = {
|
|
aktiv: false,
|
|
untergrenze: '0.0.0.0',
|
|
obergrenze: '0.0.0.0',
|
|
gatewayip: '0.0.0.0',
|
|
dnsserverip: '0.0.0.0',
|
|
ownSettings: false,
|
|
staticAssignedAddresses: [],
|
|
};
|
|
|
|
/** A file as the oracle describes it: its content as UTF-16 length and SHA-256 of its UTF-8 bytes. */
|
|
function javaFile(name: string, type: string | null, content: string | null) {
|
|
return {
|
|
file: name,
|
|
type,
|
|
length: content === null ? null : content.length,
|
|
sha256: content === null ? null : createHash('sha256').update(content, 'utf8').digest('hex'),
|
|
children: [],
|
|
};
|
|
}
|
|
|
|
/** The files a router's constructor makes, as Java loaded them from the corpus. */
|
|
function routerTemplate(): unknown[] {
|
|
const router = Object.values(original)
|
|
.flatMap((file) => file.nodes ?? [])
|
|
.find((node) => node.class === 'Vermittlungsrechner');
|
|
return ((router!.system.fileSystem as { children: unknown[] }).children).slice(0, 1);
|
|
}
|
|
|
|
/** A router's firewall as its constructor leaves it. */
|
|
const JAVA_ROUTER_FIREWALL = { activated: false, defaultPolicy: 0, dropICMP: false, filterSYNSegmentsOnly: true, filterUdp: true, rules: [] };
|
|
|
|
describe('a topology beyond the corpus, as Java loads it', () => {
|
|
it('keeps what the corpus never sets', () => {
|
|
const name = 'synthetic/synthetic.fls';
|
|
const archive = writeFlsArchive(new TextEncoder().encode(writeTopologyXml(SYNTHETIC)));
|
|
if (process.env.UPDATE_WRITTEN === '1') {
|
|
mkdirSync(join(writtenRoot, 'synthetic'), { recursive: true });
|
|
writeFileSync(join(writtenRoot, name), archive);
|
|
}
|
|
const java = written[name];
|
|
expect(java?.sha256, 'written.java.json is not about this output: UPDATE_WRITTEN=1, then npm run oracle:java').toBe(
|
|
createHash('sha256').update(archive).digest('hex'),
|
|
);
|
|
const plainInterface = (octet: string) => ({ ip: `10.0.${octet}.1`, mask: '255.255.255.0', mac: `AA:BB:CC:DD:EE:1${octet}`, gateway: '', dns: '', wireless: false });
|
|
expect(topologyOf(java!)).toEqual({
|
|
success: true,
|
|
nodes: [
|
|
{
|
|
class: 'Rechner',
|
|
name: null,
|
|
position: [10, 20],
|
|
useIpAsName: false,
|
|
useMacAsName: true,
|
|
ports: [{ ip: '10.0.0.1', mask: '255.0.0.0', mac: 'AA:BB:CC:DD:EE:01', gateway: null, dns: '10.0.0.53', wireless: true }],
|
|
system: {
|
|
ssid: 'Lab',
|
|
manualRoutes: [['10.1.0.0', '255.255.0.0', '10.0.0.254', '10.0.0.1']],
|
|
dhcpClient: true,
|
|
dhcpServer: {
|
|
aktiv: true,
|
|
untergrenze: '10.0.0.100',
|
|
obergrenze: '10.0.0.199',
|
|
gatewayip: '10.0.0.254',
|
|
dnsserverip: '10.0.0.53',
|
|
ownSettings: true,
|
|
staticAssignedAddresses: ['AA:BB:CC:DD:EE:77 10.0.0.77'],
|
|
},
|
|
fileSystem: {
|
|
directory: '/',
|
|
children: [
|
|
{ directory: 'docs', children: [javaFile('a.txt', 'text', FILE_CONTENT), { directory: null, children: [] }] },
|
|
javaFile('untyped', null, null),
|
|
{ directory: 'webserver', children: [javaFile('index.html', 'html', '<p>own</p>')] },
|
|
{ directory: 'dns', children: [javaFile('hosts', null, 'a.de. A 3600 10.0.0.1\n')] },
|
|
// Made by the peer-to-peer application and the e-mail server, whose directories the files lack.
|
|
{ directory: 'peer2peer', children: [] },
|
|
{ directory: 'mailserver', children: [] },
|
|
],
|
|
},
|
|
// In the order of Java's key.
|
|
applications: [
|
|
{ key: 'filius.software.clientserver.ClientBaustein', class: 'filius.software.clientserver.ClientBaustein', onItsSystem: true, zielIPAdresse: '10.0.0.9', zielPort: 7777 },
|
|
{ key: 'filius.software.clientserver.ServerBaustein', class: 'filius.software.clientserver.ServerBaustein', onItsSystem: true, aktiv: true, port: 7777 },
|
|
{ key: 'filius.software.dateiaustausch.PeerToPeerAnwendung', class: 'filius.software.dateiaustausch.PeerToPeerAnwendung', onItsSystem: true, maxTeilnehmerZahl: 7 },
|
|
{ key: 'filius.software.dns.DNSServer', class: 'filius.software.dns.DNSServer', onItsSystem: true, aktiv: true, port: 5353, recursiveResolutionEnabled: true },
|
|
{
|
|
key: 'filius.software.email.EmailAnwendung',
|
|
class: 'filius.software.email.EmailAnwendung', onItsSystem: true,
|
|
received: [javaMail()],
|
|
sent: [javaMail({ versendet: true, neu: false })],
|
|
drafts: [javaMail({ betreff: null, text: null, dateReceived: null, empfaenger: [] })],
|
|
addressBook: [['Muster', 'Anna', null, 12, 20095, 'Hamburg', 'anna@schule.de', null]],
|
|
// No /konten.txt.
|
|
fileAccount: null,
|
|
},
|
|
{
|
|
key: 'filius.software.email.EmailServer',
|
|
class: 'filius.software.email.EmailServer', onItsSystem: true,
|
|
aktiv: true,
|
|
mailDomain: 'schule.de',
|
|
beanAccounts: [
|
|
{
|
|
benutzername: 'anna',
|
|
passwort: 'geheim',
|
|
nachname: 'Muster',
|
|
vorname: '',
|
|
emailAdresse: 'anna@schule.de',
|
|
pop3server: null,
|
|
pop3port: null,
|
|
smtpserver: null,
|
|
smtpport: null,
|
|
nachrichten: [javaMail()],
|
|
},
|
|
],
|
|
// No /mailserver/konten.txt.
|
|
fileAccounts: null,
|
|
},
|
|
{
|
|
key: 'filius.software.firewall.Firewall',
|
|
class: 'filius.software.firewall.Firewall', onItsSystem: true,
|
|
activated: false,
|
|
defaultPolicy: 1,
|
|
dropICMP: true,
|
|
filterSYNSegmentsOnly: false,
|
|
filterUdp: false,
|
|
rules: [['10.0.0.0', '255.0.0.0', '', '', 22, 6, 1]],
|
|
},
|
|
{ key: 'filius.software.lokal.FileExplorer', class: 'filius.software.lokal.FileExplorer', onItsSystem: true },
|
|
{ key: 'filius.software.lokal.ImageViewer', class: 'filius.software.lokal.ImageViewer', onItsSystem: true },
|
|
{ key: 'filius.software.lokal.Terminal', class: 'filius.software.lokal.Terminal', onItsSystem: true },
|
|
{ key: 'filius.software.lokal.TextEditor', class: 'filius.software.lokal.TextEditor', onItsSystem: true },
|
|
{ key: 'filius.software.www.WebBrowser', class: 'filius.software.www.WebBrowser', onItsSystem: true },
|
|
{ key: 'filius.software.www.WebServer', class: 'filius.software.www.WebServer', onItsSystem: true, aktiv: true, port: 8080, useVHost: true },
|
|
],
|
|
},
|
|
},
|
|
{
|
|
class: 'Switch',
|
|
name: 'S',
|
|
position: [100, 20],
|
|
useIpAsName: undefined,
|
|
useMacAsName: undefined,
|
|
ports: [{}, {}, {}],
|
|
system: { ssid: 'S-net', retentionTime: 1234 },
|
|
},
|
|
{
|
|
class: 'Vermittlungsrechner',
|
|
name: 'R',
|
|
position: [200, 20],
|
|
useIpAsName: undefined,
|
|
useMacAsName: undefined,
|
|
ports: ['1', '2', '3'].map(plainInterface),
|
|
system: {
|
|
ripEnabled: true,
|
|
fileSystem: { directory: 'root', children: [...routerTemplate(), { directory: 'www.conf', children: [] }] },
|
|
manualRoutes: [],
|
|
dhcpClient: false,
|
|
dhcpServer: JAVA_DHCP_DEFAULTS,
|
|
firewall: {
|
|
activated: true,
|
|
defaultPolicy: 1,
|
|
dropICMP: true,
|
|
filterSYNSegmentsOnly: false,
|
|
filterUdp: false,
|
|
rules: [
|
|
['10.0.1.0', '255.255.255.0', '', '', -1, -1, 1],
|
|
['', '', '10.0.2.5', '255.255.255.255', 80, 6, 0],
|
|
[null, '', '', '', 53, 17, 1],
|
|
['', '', '', '', -1, 1, 0],
|
|
],
|
|
},
|
|
},
|
|
},
|
|
{
|
|
class: 'Modem',
|
|
name: 'M',
|
|
position: [300, 20],
|
|
useIpAsName: undefined,
|
|
useMacAsName: undefined,
|
|
ports: [{}],
|
|
system: { modem: { mode: 1, port: 4242, ipAdresse: '192.168.1.5' } },
|
|
},
|
|
{
|
|
class: 'Gateway',
|
|
name: 'G',
|
|
position: [400, 20],
|
|
useIpAsName: undefined,
|
|
useMacAsName: undefined,
|
|
ports: ['4', '5'].map(plainInterface),
|
|
system: {
|
|
fileSystem: { directory: 'own', children: [javaFile('x', 'text', 'y')] },
|
|
manualRoutes: [],
|
|
dhcpClient: false,
|
|
dhcpServer: JAVA_DHCP_DEFAULTS,
|
|
staticNAT: [],
|
|
firewall: JAVA_ROUTER_FIREWALL,
|
|
},
|
|
},
|
|
],
|
|
cables: [
|
|
{ ends: [[0, 0], [1, 2]], wireless: false, panel: [0, 1] },
|
|
{ ends: [[2, 2], [1, 0]], wireless: true, panel: [2, 1] },
|
|
],
|
|
documentation: [{ type: 1, text: null, bounds: [5, 6, 70, 80], color: null, font: null }],
|
|
});
|
|
});
|
|
});
|