1. Systemübersicht
Widget Storm ist eine modulare Widget-Plattform für das Web, aktiv seit 2008. Widgets sind eigenständige Webkomponenten aus drei Schichten (PHP, CSS, JavaScript), die verschlüsselt auf dem Server gespeichert und über HTTP-Endpunkte ausgeliefert werden.
| Eigenschaft | Wert |
|---|---|
| Version | 4.0.0 |
| Sprache | PHP 8.3 |
| Datenbank | MySQL / MariaDB |
| Verschlüsselung | RIJNDAEL-256 (Legacy), AES-256-CBC (Modern) |
| Standard-Autor | WidgetStormSystem |
| Ausführungskontexte | Lokal (wgclient.php), Remote (wgcall.php), Client-seitig (wghandler.php) |
2. Widget-Struktur
Jedes Widget besteht aus exakt drei Dateien. Alle drei Schichten haben Zugriff auf
die gleichen Parameter ($wgparams) und die Instanz-ID ($wgguid).
| Schicht | Datei | Content-Type | Beschreibung |
|---|---|---|---|
| PHP | widget_name.php | text/html | Serverseitige Logik und HTML-Ausgabe |
| CSS | widget_name.css | text/css | Styling mit optionaler PHP-Bridge |
| JS | widget_name.js | text/javascript | Client-seitige Interaktion |
Verfügbare Variablen im Widget-Code
| Variable | Typ | Beschreibung |
|---|---|---|
| $wgparams | object|array|string | Widget-Parameter (geparst aus JSON, Semikolon-Liste oder String) |
| $widgetparams | object|array|string | Alias für $wgparams |
| $wgguid | string | Eindeutige Instanz-ID für CSS/JS-Scoping |
PHP-Schicht — Beispiel
<?php
if(isset($widgetparams->uid)) $wgguid = $widgetparams->uid;
else $wgguid = "";
if(isset($wgparams)){
$text = isset($wgparams->text) ? $wgparams->text : "Standard-Text";
?>
<div id="mein_widget<?= $wgguid;?>" class="mein-widget">
<p><?= $text;?></p>
</div>
<?php
}
?>
Ausgabemodi
| Modus | Ausgabe |
|---|---|
| php | Nur HTML (evalBei Widget-Storm führt eval() ausschließlich Widget-Code aus, der von authentifizierten Autoren in der Datenbank hinterlegt wurde — nicht von Benutzereingaben. Es ist die technische Grundlage der PHP-in-CSS Bridge und der dynamischen Widget-Komposition. Kein User-Input erreicht eval().-Ergebnis) |
| css | Nur CSS (evalDie CSS-Schicht wird durch eval() gerendert, um die PHP-in-CSS Bridge zu aktivieren. Der Code stammt ausschließlich aus der Datenbank — erstellt von authentifizierten Widget-Autoren. Dynamische Selektoren und instanzspezifisches Styling wären ohne diesen Mechanismus nicht möglich.-Ergebnis) |
| js | Nur JavaScript (evalAuch die JS-Schicht nutzt eval() für eingebettete PHP-Variablen (UID-Scoping, Parameter). Wie bei allen Widget-Schichten: der ausgeführte Code ist autorengeprüft und datenbankgespeichert, nicht nutzergeneriert.-Ergebnis) |
| (leer) | <style>CSS</style> PHP <script>JS</script> |
3. Parameter-System
Parameter werden über wgparams an Widgets übergeben.
Das System unterstützt drei Formate:
JSON (empfohlen)
{"text":"Hallo Welt","color":"#ff0000","items":[1,2,3]}
Wird zu einem stdClass-Objekt geparst. Zugriff via $wgparams->text.
Semikolon-getrennt
Wert1;Wert2;Wert3
Wird zu einem Array geparst. Zugriff via $wgparams[0], $wgparams[1], etc.
Einfacher String
Ein beliebiger Text
Wird unverändert als String durchgereicht.
URL-Encoding für HTTP-Requests
wgparams={"text":"Hallo","uid":"abc123"}
// In PHP für URL-Parameter:
$packurl = http_build_query(['wgparams' => $paramsArray]);
4. PHP-in-CSS/JS Bridge
CSS- und JS-Dateien können eingebetteten PHP-Code enthalten. Da PHP-Tags in CSS/JS syntaktisch ungültig sind, werden sie in Kommentare verpackt. Das System konvertiert diese automatisch vor der Ausführung.
Konvertierungsregeln
| Im Quellcode | Wird zu |
|---|---|
| /*<?php | <?php |
| /*<?= | <?= |
| ?>*/ | ?> |
CSS-Beispiel
/*<?php
if(isset($wgparams->uid)) $wgguid = $wgparams->uid;
else $wgguid = "";
?>*/
div#mein_widget/*<?= $wgguid;?>*/ {
background: rgba(170,210,210,0.08);
border: 1px solid rgba(170,210,210,0.2);
padding: 1em;
border-radius: 0.4em;
}
JS-Beispiel
/*<?php
if(isset($wgparams->uid)) $wgguid = $wgparams->uid;
else $wgguid = "";
?>*/
jQuery(document).ready(function(){
jQuery("#mein_widget/*<?= $wgguid;?>*/").on("click", function(){
jQuery(this).toggleClass("active");
});
});
5. Verschachtelung & Marker
Widgets können andere Widgets laden. Dies geschieht über Marker im PHP-Code, die vom Server rekursiv aufgelöst werden.
Marker-Syntax
##wgstart##widgetname::autor::parameter##wgend##
| Segment | Beschreibung |
|---|---|
| widgetname | Name des einzubettenden Widgets |
| autor | Autor des Widgets |
| parameter | Parameter als JSON oder Semikolon-Liste |
Auflösungsprozess
- Server findet alle
##wgstart##...##wgend##Marker im PHP-Code - Extrahiert Name, Autor und Parameter aus dem Marker
- Löst das verschachtelte Widget rekursiv auf
- CSS und JS des verschachtelten Widgets werden an das Eltern-Widget angehängt
- PHP wird Base64-kodiert und über
intern_script_wall()ausgeführt
UID-Scoping & Platzhalter
| Platzhalter | Ersetzung | Verwendung |
|---|---|---|
| ##self## | widgetname + md5($wgguid) | Eindeutiger Selektor pro Instanz |
| ##wgself## | widgetname + md5($wgguid) | Alias für ##self## |
| ##selfreplace## | ##self## | Escape: literales ##self## im Output |
6. Verfügbarkeitsstufen
| Stufe | Zugriff | Billing |
|---|---|---|
| open | Alle registrierten Nutzer | Kostenlos |
| authenticated | Autor + Nutzer mit expliziter Berechtigung | Optional |
| payment | Autor + Nutzer mit aktivem Billing | Erforderlich |
Entwickler legen die Verfügbarkeit beim Upload fest (Parameter wgrmode).
Die Stufe bestimmt, wer das Widget über seinen wgclient abrufen kann —
und ob eine Abrechnung erforderlich ist.
Zugriffskontrolle
1. Widget.availability == 'open' → Zugriff gewährt
2. Widget.author == RequestUser → Zugriff gewährt (Autor)
3. Berechtigungsprüfung → Prüfung in interner Berechtigungstabelle
- Globale Berechtigung → Gilt für alle Nutzer
- Spezifische Berechtigung → Gilt für einzelne Nutzer
Sicherheit auf Widget-Ebene
Widgets können eigene Sicherheitsmechanismen mitbringen — unabhängig vom
Hostsystem. Das Widget wg_demo_todo demonstriert dieses Prinzip:
AES-256-verschlüsselte Persistenz, schlüsselbasierte Authentifizierung mit
Brute-Force-Schutz und automatische Preflight-Checks für Abhängigkeiten und
Berechtigungen. Weitere Details finden Sie auf der
Widget-Übersicht.
7. HTTP-Endpunkte
wgclient.php — Widget-Auslieferung (lokal)
Dient als HTTP-Endpunkt und als PHP-Include für serverseitige Einbindung.
| Parameter | Pflicht | Beschreibung |
|---|---|---|
| wgname | Ja | Widget-Name |
| wgauthor | Nein | Widget-Autor (Standard: WidgetStormSystem) |
| wgmode | Nein | Ausgabemodus: php, css, js oder leer (alle) |
| wgparams | Nein | Widget-Parameter (JSON, Semikolon-Liste oder String) |
| wgguid | Nein | Instanz-ID für Scoping |
wgcall.php — Remote Widget-Auslieferung
Endpunkt für externe Server. Erfordert Authentifizierung und verschlüsselt die Antwort.
| Parameter | Pflicht | Beschreibung |
|---|---|---|
| wgname | Ja | Widget-Name (alphanumerisch + Unterstrich + Bindestrich) |
| wgauthor | Ja | Widget-Autor |
| wgmode | Ja | Erlaubte Werte: php, css, js, go, c, md |
| requestuser | Ja | Benutzername |
| requestkey | Ja | Authentifizierungsschlüssel (MD5-Hash) |
| wgparams | Nein | Widget-Parameter |
| wgguid | Nein | Instanz-ID |
| wgfirst | Nein | true = keine Verschachtelungsauflösung |
wgregistration.php — Widget-Upload
Endpunkt zum Hochladen neuer oder aktualisierter Widgets.
| Parameter | Beschreibung |
|---|---|
| wgrname | Widget-Name |
| wgrparam | Schicht: php, css, js |
| wgrcode | Verschlüsselter Widget-Code |
| wgrmode | Verfügbarkeit: authenticated, open, payment |
| wgrrequestuser | Benutzername |
| wgrrequestkey | Authentifizierungsschlüssel |
wgbuilds/ (Batch-Modus) werden entsprechend nur
Widgets verarbeitet, die dem eigenen Autoren-Konto zugeordnet sind.
wgclientcreator.php — Client-Download
Generiert eine personalisierte wgclient.php mit eingebetteten Zugangsdaten.
Erfordert aktive Session (Login über Station). Bei jedem Download wird ein neuer
requestkey generiert (Key-Rotation via md5(username + uniqid())).
wghandlercreator.php — Handler-Download
Generiert eine portable wghandler.php Klasse mit eingebetteter
RIJNDAEL-256 Implementierung (pure PHP via phpseclib3, kompatibel mit PHP 8+),
lokalem Widget-Caching und Unterstützung für verschachtelte Widgets.
8. Widget-Einbindung
Lokale Einbindung (gleicher Server)
<!-- CSS im <head> -->
<link rel="stylesheet"
href="wgclient.php?wgname=basic&wgauthor=WidgetStormSystem&wgmode=css&wgparams=..."
type="text/css">
<!-- JavaScript vor </body> -->
<script src="wgclient.php?wgname=basic&wgauthor=WidgetStormSystem&wgmode=js&wgparams=..."></script>
<!-- PHP im <body> -->
<?php
require_once 'wgclient.php';
$wg->get('basic', 'WidgetStormSystem', $params, 'php');
?>
Remote-Einbindung (externer Server)
<?php
// wgclient.php und wghandler.php auf eigenem Server platzieren
require_once 'wgclient.php';
// Zugangsdaten sind in wgclient.php eingebettet
$wg->get('basic', 'WidgetStormSystem', $params, 'php');
?>
Ausführungsmodi (wgexecutionmode)
Der Entwickler steuert über den wgexecutionmode, ob ein Widget
lokal aus dem CodeVault gerendert wird
oder live vom Widget-Storm-Server abgerufen werden soll.
Der Standard-Modus nutzt den lokalen Cache — das bedeutet
keine Netzwerk-Latenz und maximale Ladegeschwindigkeit.
| Modus | Verhalten | Einsatz |
|---|---|---|
| (Standard) | Lokaler CodeVault — Widgets aus dem Cache laden | Produktion: schnellste Auslieferung, keine Server-Abhängigkeit |
| live | Remote Fetch — Widget live vom Server laden und ausführen | Entwicklung: immer aktuelle Version, keine lokale Datei nötig |
| uploadwidgets | Batch-Upload — lokale Widgets in wgbuilds/ hochladen | Deployment: alle eigenen Widgets aus dem lokalen Verzeichnis synchronisieren |
9. Verschlüsselung
Die Kommunikation zwischen Client und Server ist verschlüsselt.
Das System unterstützt zwei Verschlüsselungsversionen pro Benutzer:
RIJNDAEL-256 (das ursprüngliche Verfahren seit 2008) und
AES-256-CBC (der moderne Standard für neue Nutzer).
Beide koexistieren über einen zentralen EncryptionNegotiator,
der automatisch die passende Version pro Benutzer wählt.
| Version | Algorithmus | Modus | Status |
|---|---|---|---|
| v1_rijndael | RIJNDAEL-256 | ECB | Legacy (seit 2008) |
| v2_aes | AES-256-CBC | CBC mit zufälligem IV | Standard für neue Nutzer |
Beide Richtungen (Server → Client und Client → Server) sind auf Anwendungsebene verschlüsselt. Jeder Nutzer hat einen individuellen Schlüssel, der bei jedem Client-Download rotiert wird.
mcrypt-Extension der Standard-Weg für Kryptografie war und
openssl_encrypt() noch nicht verfügbar war. Die Entscheidung war dem
damaligen Stand der Technik entsprechend. Seit der Modernisierung auf PHP 8.3
wird phpseclib3 als Drop-in-Ersatz für die entfernte mcrypt-Extension verwendet.
Ausführliche Hintergründe dazu finden Sie in den
FAQ.
10. Rate Limiting
| Endpunkt | Limit | Fenster | HTTP-Status bei Überschreitung |
|---|---|---|---|
| wgcall.php | 120 Anfragen | 60 Sekunden | 429 Too Many Requests |
| wgregistration.php | 30 Uploads | 60 Sekunden | 429 Too Many Requests |
Tracking erfolgt pro IP-Adresse und Endpunkt. Zustandsdateien in /tmp/ws-ratelimit/.
11. CodeVault
Der CodeVault ist das Herzstück der Widget-Auslieferung. Er speichert Widget-Code als lokale Dateien auf dem Client-Server — das bedeutet direkten Dateisystem-Zugriff statt Netzwerk-Roundtrips. Widgets werden so schnell geladen wie jede andere lokale PHP-Datei, ohne Abhängigkeit vom zentralen Widget-Storm-Server.
Zweck & Vorteile
| Eigenschaft | Beschreibung |
|---|---|
| Geschwindigkeit | Lokale Datei-Reads statt HTTP-Anfragen — Ladezeiten im Mikrosekundenbereich |
| Unabhängigkeit | Widgets funktionieren auch wenn der Widget-Storm-Server nicht erreichbar ist |
| Redundanz | Doppelte Speicherung: Datenbank (Server) + Dateisystem (Client) |
| Autoren-Isolation | Jeder Autor hat sein eigenes Unterverzeichnis — kein Überschreiben fremder Widgets möglich |
Verzeichnisstruktur
wgbuilds/
├─ {Autor}/
│ ├─ {widget_name}.php
│ ├─ {widget_name}.css
│ └─ {widget_name}.js
└─ WidgetStormSystem/
├─ basic.php
├─ basic.css
├─ basic.js
├─ wg_nav.php
└─ ...
Die Verzeichnisstruktur ist nach Autoren organisiert.
Beim Batch-Upload (uploadwidgets-Modus) scannt der wghandler
das wgbuilds/ Verzeichnis und lädt geänderte Dateien
automatisch auf den Server hoch — dabei werden nur eigene Widgets
verarbeitet. Widgets anderer Autoren bleiben unberührt.
Rendering aus dem CodeVault
Im Standard-Modus liest der wgclient den Widget-Code direkt aus wgbuilds/
und führt ihn lokal aus (evalDer CodeVault-Code wird via eval() im Server-Kontext ausgeführt. Die Dateien stammen aus dem authentifizierten Download oder eigenem Upload — sie sind identisch mit dem Datenbank-Original. Kein externer Input fließt in die Ausführung ein.).
Der Live-Modus umgeht den CodeVault und fragt den Widget-Storm-Server direkt ab —
nützlich während der Entwicklung, aber langsamer als der lokale Cache.