Rekursive Entfernung der
Maskierungs-Backslashes in $data
- flat_open_lock($filepath,$lockmode) => Öffnet $filename und nutzt als
Sperrmethode $lockmode
Einmalige Funktionen:
=====================
- flat_file_create($filepath) => Erstellt die Datei $filepath
- flat_file_alter => Ändert die Dateien, wenn z.B. ein
Feld dazukommt
Arbeitsfunktionen:
==================
- flat_rec_select => holt eine Recordliste aus
einem File
- flat_rec_make_list => Erzeugt die HTML Ausgabe für die
Anzeige mit Blätterfunktion
- flat_rec_make_detail => Erzeugt die HTML Ausgabe für
einen angeforderten Datenksatz
- flat_rec_insert => Schreibt einen neuen Datensatz in
aktuell.dat
- flat_rec_update => Erneuert Datensätze in $filepath
oder fügt sie hinzu, wenn die ID noch
nicht vorhanden war.
- flat_rec_delete($filepath,$_recordList) => Löscht die Datensätze in $filename
- flat_rec_copy ??? => Kopiert eine bestimmte Menge an
Datensätzen, wird zur Archivierung genutzt
- flat_rec_search($string) => Sucht je nach Auswahl im Archiv oder
aktuell.dat nach String
Sämtliche Arbeitsfunktionen nutzen folgenden Fehlercode:
--------------------------------------------------------
0 = kein Fehler
1 bis 10 = Low-Level-Fehler
1
2 File not found
3 Datei existiert schon
4 Keine Daten vorhanden, File ist leer
5 Berechtigungsfehler auf Low-Level-Ebene
6
7
8 Fehler beim Schreibvorgang
10 max. zulässige Dateigröße überschritten
11 bis 50 = Datenfehler
11 Dateiformat passt nicht
12 Noch alte fehlerhafte Datensätze in ['denied']
13 Nicht alle Datensätze konnten verarbeitet werden
14 Keine Datensätze vorhanden, Format aber passend
51 bis 100 = Berechtigungsfehler der Userverwaltung
*/
#--------------------------------------------------------------------
# includes und Konstanten
#--------------------------------------------------------------------
define ('FLAT_MAXFILESIZE',1000000);
#--------------------------------------------------------------------
function get_microtime()
{
list($usec, $sec) = explode(" ",microtime());
return ((float)$usec + (float)$sec);
}
#--------------------------------------------------------------------
function get_time_s()
{
list($usec, $sec) = explode(" ",microtime());
$time_s = date("YmdHis").substr($usec,1,7);
return $time_s;
}
#--------------------------------------------------------------------
function strip($data)
{
if (!get_magic_quotes_gpc())
{
return $data;
}
if (is_array($data))
{
foreach($data as $key => $val)
{
$data[$key] = strip($val);
}
}
else
{
$data = stripslashes($data);
}
return $data;
}
#--------------------------------------------------------------------
function flat_open_lock($filepath,$lockmode)
{
# Lockdatei öffnen oder anlegen
for ($x=0;$x<5;$x++)
{
if($lh = @fopen($filepath,"a+")) break;
usleep(8000); ## 8ms warten bis zum nächsten Versuch
}
if (!$lh) return false;
# Lockversuch
for ($x=0;$x<5;$x++)
{
if (@flock($lh,$lockmode + LOCK_NB)) return $lh;
usleep(8000); ## 8ms warten bis zum nächsten Versuch
}
fclose($lh);
return false;
}
#--------------------------------------------------------------------
function flat_file_create($filepath)
{
clearstatcache(); ## Statusbuffer rücksetzen
if(file_exists($filepath)) return 3; ## Datei existiert schon
$fp = flat_open_lock($filepath,LOCK_EX);
if($fp)
{ ## wenn File > 0 war es schon da
if (filesize($filepath) > 0) ## man muss das hier nochmal bzw
## eigentlich erst hier testen,
{ ## weil zwischen Handle-Beschaffung
## und Lock Zeit vergeht
fclose($fp);
return 3; ## Datei existiert schon
}
$time_s = get_time_s();
$time_u = time();
$_file = array();
$_file['meta'] = array();
$_file['data'] = array();
$_file['meta']['created'] = $time_u; ## erstellt am
$_file['meta']['lastupdate'] = $time_s; ## letztes Write
$_file['meta']['lastid'] = 0;
$_file['meta']['amount'] = 0;
$_file_packed = serialize($_file);
fseek($fp,0);
fwrite($fp,$_file_packed,strlen($_file_packed));
fclose($fp);
return 0; ##Code für kein Fehler
}
else return 5; ##Code für Datei nicht geöffnet
}
#--------------------------------------------------------------------
# Funktion ändert das Dateiformat oder die Bezeichernunter
# Migration der vorhandenen Daten
#--------------------------------------------------------------------
function flat_file_alter()
{
}
#--------------------------------------------------------------------
# Zusammenstellung der für die Listendarstellung benötigten Daten
# als Array von Datensätzen
#--------------------------------------------------------------------
function flat_get_rec_list($filepath, # Pfad zur Datei
$rec_id, # Satznummer ab dem
$reccount, # Anzahl der zu zeigenden Zeilen
$_userdata=false, # Rechte des Users
$_rights=false) # geforderte Rechte
{
}
#--------------------------------------------------------------------
# Erzeugung eines HTML-Strings mit der Liste von Datensätzen
# und allen Bedienelementen, die dem User zustehen
#--------------------------------------------------------------------
function flat_make_rec_list($rec_list, $session=true)
{
}
#--------------------------------------------------------------------
function flat_get_rec()
{
}
#--------------------------------------------------------------------
function flat_make_rec_detail()
{
}
#--------------------------------------------------------------------
# Die Funktion übernimmt einen oder mehrere Datensätze in
# $_recdata['data'] und fügt sie in die Tabelle ein.
# Es wird jedem Datensatz eine neue ID vergeben.
# in $_recdata['rec_inserted'][]['new_id'] werden die
# erfolgreich vergebenen IDs zurückgegeben.
#--------------------------------------------------------------------
function flat_rec_insert($filepath,&$_recdata)
{
//status-Buffer rücksetzen
clearstatcache();
//Datei öffnen und locken, bei Fehler abrechen
$fp = flat_open_lock($filepath,LOCK_EX);
if (!$fp) return 5; ## Datei konnte nicht gesperrt werden
// maximale Dateigröße prüfen
$filesize = filesize($filepath);
if ($filesize > FLAT_MAXFILESIZE)
{
fclose($fp);
return 10; ## max. zulässige Dateigröße überschritten
}
//Datei entpacken
fseek($fp,0,SEEK_SET);
$_file_packed = fread($fp,$filesize);
$_file = unserialize($_file_packed);
//Zeitstempel erzeugen und merken
$time_s = get_time_s();
$time_u = time();
//$_file anlegen, falls nicht vorhanden
if(empty($_file))
{
$_file = array();
$_file['meta'] = array();
$_file['data'] = array();
$_file['meta']['created'] = $time_u;
$_file['meta']['lastupdate'] = $time_s;
$_file['meta']['lastid'] = 0;
$_file['meta']['amount'] = 0;
}
else
{
//Dateiformat überprüfen
if (!isset($_file['meta']['created']) or
!isset($_file['meta']['lastupdate']) or
!isset($_file['meta']['lastid']) or
!isset($_file['meta']['amount']) or
!is_array($_file['data']))
{
fclose($fp);
return 11; ## Dateiformat passt nicht
}
if (!empty($_recdata['denied']) or !empty($_recdata['meta']))
{
fclose($fp); ## noch fehlerhafte Datensätze im Array
return 12; ## oder noch Ergebnisdaten vorhanden
}
$_recdata['meta'] = array(); ## es könnten ja noch leere Strings sein
$_recdata['denied'] = array();
}
$_recdata['meta']['rec_inserted'] = 0; ## Anzahl der fehlerfrei updated Records
$_recdata['meta']['rec_denied'] = 0; ## Anzahl der abgelehnten Records
foreach($_recdata['data'] as $key => $_record)
{
if(!empty($_record))
{
$_recdata['meta']['rec_inserted'] ++; ## fehlerfrei eingefügten DS zählen
$_file['meta']['lastid'] ++;
$_file['meta']['amount'] ++;
$new_key = $_file['meta']['lastid'];
$_file['data'][$new_key] = $_record; ## Daten übertragen
$_file['data'][$new_key]['lastupdate'] = $time_s; ## Aktualisierungsdatum eintragen
$_file['data'][$new_key]['created'] = $time_u; ## Erstelldatum eintragen
unset($_recdata['data'][$key]); ## Record aus Auftragsliste löschen
$_recdata['rec_inserted'][$key]['new_id'] = $new_key; ## Erteilter Schlüssel
}
else
{
$_recdata['denied'][$key] = $_record; ## abgelehnter Datensatz
$_recdata['meta']['rec_denied'] ++; ## "abgelehnt" zählen
}
}
// wenn Datensätze eingefügt wurden
if ($_recdata['meta']['rec_inserted'] > 0)
{
// letzte Veränderung eintragen
$_file['meta']['lastupdate'] = $time_s;
//Datei verpacken
$_file_packed = serialize($_file);
//und abspeichern
fseek($fp,0);
ftruncate($fp,0);
$writeok = @fwrite($fp,$_file_packed,strlen($_file_packed));
}
@fclose($fp);
//Rückgabewert der Funktion
if (!$writeok)
{
return 8; # Fehler beim Schreiben der Daten;
}
if (count($_recdata['denied'])==0)
{
return 0; # kein Fehler aufgetreten, alle Sätze verarbeitet.
}
else
{
return 13; # nicht alle Sätze konnten verarbeitet werden
}
}
#--------------------------------------------------------------------
# Die Funktion beschafft alle Sätze, die dem Benutzer gemäß Rechten
# zur Verfügung stehen
#
#--------------------------------------------------------------------
function flat_rec_select($filepath,&$_recdata,$_userdata=false,$_rights=false)
{
//status-Buffer rücksetzen
clearstatcache();
//Datei öffnen und locken, bei Fehler abrechen
$fp = flat_open_lock($filepath,LOCK_SH);
if (!$fp) return 5; ## Datei konnte nicht gesperrt werden
// maximale Dateigröße prüfen
$filesize = filesize($filepath);
if ($filesize > FLAT_MAXFILESIZE + 5000)
{
fclose($fp);
return 10; ## max. zulässige Dateigröße überschritten
}
//Datei entpacken
fseek($fp,0,SEEK_SET);
$_file_packed = fread($fp,$filesize);
fclose($fp);
$_file = unserialize($_file_packed);
//abbrechen, falls $_file leer ist
if(empty($_file) or ($filesize == 0))
{
return 4;
}
else
{
//Dateiformat überprüfen
if (!isset($_file['meta']['created']) or
!isset($_file['meta']['lastupdate']) or
!isset($_file['meta']['lastid']) or
!isset($_file['meta']['amount']) or
!is_array($_file['data']))
{
return 11; ## Dateiformat passt nicht
}
$_recdata = array();
$_recdata['meta'] = $_file['meta']; ## Metadaten übertragen
$_recdata['meta']['rec_denied'] = 0; ## Anzahl der verbotenen Records
$_recdata['meta']['rec_selected'] = 0; ## Anzahl der gelieferten Records
foreach($_file['data'] as $key => $_record)
{
if(isset($_record['rights']) and (false)) ## Einschränkende rechte vorhanden
{
#### hier Baustelle ####
$_recdata['meta']['rec_denied'] ++; ## mangelnde Userrechte
########################
}
else
{
$_recdata['meta']['rec_selected'] ++; ## erlaubter Datensatz
$_recdata['data'][$key] = $_record; ## Daten übertragen
}
}
ksort($_recdata['data']); ## nach IDs sortieren
}
//Rückgabewert der Funktion
if ($_recdata['meta']['rec_denied'] == 0) ## alle Sätze erlaubt
{
return 0; # kein Fehler aufgetreten, alle Sätze verarbeitet.
}
else
{
return 13; # nicht alle Sätze konnten verarbeitet werden
}
}
#--------------------------------------------------------------------
function flat_rec_update($filepath,&$_recdata)
{
//status-Buffer rücksetzen
clearstatcache();
//Datei öffnen und locken, bei Fehler abrechen
$fp = flat_open_lock($filepath,LOCK_EX);
if (!$fp) return 5; ## Datei konnte nicht gesperrt werden
// maximale Dateigröße prüfen
$filesize = filesize($filepath);
if ($filesize > FLAT_MAXFILESIZE)
{
fclose($fp);
return 10; ## max. zulässige Dateigröße überschritten
}
//Datei entpacken
fseek($fp,0,SEEK_SET);
$_file_packed = fread($fp,$filesize);
$_file = unserialize($_file_packed);
//Zeitstempel erzeugen und merken
$time_s = get_time_s();
$time_u = time();
//$_file anlegen, falls nicht vorhanden
if(empty($_file))
{
$_file = array();
$_file['meta'] = array();
$_file['data'] = array();
$_file['meta']['created'] = $time_u;
$_file['meta']['lastupdate'] = $time_s;
$_file['meta']['lastid'] = 0;
$_file['meta']['amount'] = 0;
}
else
{
//Dateiformat überprüfen
if (!isset($_file['meta']['created']) or
!isset($_file['meta']['lastupdate']) or
!isset($_file['meta']['lastid']) or
!isset($_file['meta']['amount']) or
!is_array($_file['data']))
{
fclose($fp);
return 11; ## Dateiformat passt nicht
}
if (!empty($_recdata['denied']) or !empty($_recdata['meta']))
{
fclose($fp); ## noch fehlerhafte Datensätze im Array
return 12; ## oder noch Ergebnisdaten vorhanden
}
$_recdata['meta'] = array(); ## es könnten ja noch leere Strings sein
$_recdata['denied'] = array();
}
$_recdata['meta']['rec_updated'] = 0; ## Anzahl der fehlerfrei updated Records
$_recdata['meta']['rec_denied'] = 0; ## Anzahl der abgelehnten Records
foreach($_recdata['data'] as $key => $_record)
{
if(isset($_file['data'][$key])) ## Datensatz ist vorhanden
{
if ($_file['data'][$key]['lastupdate'] == $_record['lastupdate'])
{
$_recdata['meta']['rec_updated'] ++; ## fehlerfrei updated zählen
$_file['data'][$key] = $_record; ## Daten übertragen
$_file['data'][$key]['lastupdate'] = $time_s; ## Aktualisierungsdatum eintragen
unset($_recdata['data'][$key]); ## Record aus Auftragsliste löschen
}
else
{
$_recdata['denied'][$key] = $_file['data'][$key]; ## Daten aus dem File holen
$_recdata['meta']['rec_denied'] ++; ## "abgelehnt" zählen
}
}
else ## Datensatz aus der Auftragsliste ist noch nicht im File
{
if ($key > $_file['meta']['lastid']) ## wenn die ID aus der Auftragsliste
{ ## größer als die größte ID im File
$_file['meta']['lastid'] = $key; ## ist, lastID erhöhen
}
if (trim($_record['lastupdate']) == "") ## record hat keinen Meinstamp
{
$_record['lastupdate'] = $time_s; ## Aktualisierungsdatum eintragen
}
$_file['data'][$key] = $_record; ## Satz hinzufügen
$_file['meta']['amount'] ++; ## datensatz im File zählen
$_recdata['meta']['rec_updated'] ++; ## erfolgreichen Auftrag zählen
unset($_recdata['data'][$key]); ## Record aus Auftragsliste löschen
}
}
//wenn Datensätze verändert oder eingefügt wurden
if ($_recdata['meta']['rec_updated'] >0)
{
// letzte Veränderung eintragen
$_file['meta']['lastupdate'] = $time_s;
//Datei verpacken
$_file_packed = serialize($_file);
//und abspeichern
fseek($fp,0);
ftruncate($fp,0);
$writeok = @fwrite($fp,$_file_packed,strlen($_file_packed));
}
@fclose($fp);
//Rückgabewert der Funktion
if (!$writeok) return 8; # Fehler beim Schreiben;
if (count($_recdata['denied'])==0)
{
return 0; # kein Fehler aufgetreten, alle Sätze verarbeitet.
}
else
{
return 13; # nicht alle Sätze konnten verarbeitet werden
}
}
#--------------------------------------------------------------------
function flat_rec_delete($filepath,&$_recdata)
{
//status-Buffer rücksetzen
clearstatcache();
//Datei öffnen und locken, bei Fehler abrechen
$fp = flat_open_lock($filepath,LOCK_EX);
if (!$fp) return 5; ## Datei konnte nicht gesperrt werden
// maximale Dateigröße prüfen
$filesize = filesize($filepath);
// maximale Dateigröße zuzüglich Sicherheitszuschlag für LESEN
if ($filesize > FLAT_MAXFILESIZE + 5000)
{
fclose($fp);
return 10; ## max. zulässige Dateigröße überschritten
}
//Datei entpacken
fseek($fp,0,SEEK_SET);
$_file_packed = fread($fp,$filesize);
$_file = unserialize($_file_packed);
//Zeitstempel erzeugen.
$time_s = get_time_s();
//Prüfen, ob $_file Daten enthält
if(empty($_file))
{
return 4; ## Keine Daten vorhanden
}
else
{
//Dateiformat überprüfen
if (!isset($_file['meta']['created']) or
!isset($_file['meta']['lastupdate']) or
!isset($_file['meta']['lastid']) or
!isset($_file['meta']['amount']) or
!is_array($_file['data']))
{
fclose($fp);
return 11; ## Dateiformat passt nicht
}
if (!empty($_recdata['denied']) or !empty($_recdata['meta']))
{
fclose($fp);
return 12; ## noch fehlerhafte Datensätze im Array
} ## oder noch falsche Ergbnisdaten
$_recdata['meta'] = array();
$_recdata['denied'] = array();
}
$_recdata['meta']['rec_deleted'] = 0; ## Anzahl der fehlerfrei gelöschten Records
$_recdata['meta']['rec_denied'] = 0; ## Anzahl der abgelehnten Records
foreach($_recdata['data'] as $key => $_record)
{
if(isset($_file['data'][$key])) ## Datensatz ist vorhanden
{
if ($_file['data'][$key]['lastupdate'] == $_record['lastupdate'])
{
$_recdata['meta']['rec_deleted'] ++; ## fehlerfrei updated zählen
unset($_file['data'][$key]); ## Daten löschen
unset($_recdata['data'][$key]); ## Record aus Auftragsliste löschen
$_file['meta']['amount']--; ## Satzanzahl verringern
}
else
{
$_recdata['denied'][$key] = $_file['data'][$key]; ## Daten aus dem File holen
$_recdata['meta']['rec_denied'] ++; ## "abgelehnt" zählen
}
}
else ## Datensatz aus der Auftragsliste ist nicht im File
{
unset($_recdata['data'][$key]); ## Record aus Auftragsliste löschen
}
}
// Wenn datensätze gelöscht wurden
if ($_recdata['meta']['rec_deleted'] >0)
{
// letzte Veränderung eintragen
$_file['meta']['lastupdate'] = $time_s;
//Datei verpacken
$_file_packed = serialize($_file);
//und abspeichern
fseek($fp,0);
ftruncate($fp,0);
$writeok = @fwrite($fp,$_file_packed,strlen($_file_packed));
}
@fclose($fp);
//Rückgabewert der Funktion
if (!$writeok) return 8; ## Fehler beim Schreiben;
if (count($_recdata['denied'])==0)
{
return 0; # kein Fehler aufgetreten, alle Sätze gelöscht wurden.
}
else
{
return 13; # nicht alle Sätze konnten verarbeitet werden
}
}
#--------------------------------------------------------------------
function flat_rec_copy()
{
}
#--------------------------------------------------------------------
function flat_rec_search()
{
}
#--------------------------------------------------------------------
function flat_file_backup($filepath,$backuppath=false,$compress=9)
{
//status-Buffer rücksetzen
clearstatcache();
//Datei öffnen und locken, bei Fehler abrechen
$fp = flat_open_lock($filepath,LOCK_EX);
if (!$fp) return 5; ## Datei konnte nicht gesperrt werden
$filesize = filesize($filepath);
// maximal zulässige Filegröße + Sicherheit zum Öffnen
if ($filesize > FLAT_MAXFILESIZE+5000)
{
fclose($fp);
return 10; ## max. zulässige Dateigröße überschritten
}
//Datei einlesen
fseek($fp,0,SEEK_SET);
$_file_packed = fread($fp,$filesize);
fclose($fp);
if(empty($backuppath))
{
$backuppath = $filepath . date(".Y_m_d");
}
// wahlweise Komprimierung durchführen
$compress = intval($compress);
if ($compress > 0)
{
if ($compress > 9) $compress = 9; ## größte Kompression
$backuppath .= '.gz';
$_file_packed = gzencode($_file_packed,$compress); ## gZIP erstellen
}
if(empty($backuppath) and $compress == 0)
{
$backuppath .= '.abk';
}
$fp = flat_open_lock($backuppath,LOCK_EX);
if (!$fp) return 5; ## Datei konnte nicht gesperrt werden
// prüfen, ob Ausgabefile schon Daten enthielt.
$filesize = filesize($backuppath);
if ($filesize > 0)
{
fclose($fp);
return 3; ## File existiert schon
}
fwrite($fp,$_file_packed,strlen($_file_packed));
fclose($fp);
return 0; ## Kein Fehler aufgetreten
}
#====================================================================
# main
#====================================================================
$_upd_buf = array();
$_upd_buf['meta'] = array();
$_upd_buf['data'] = array();
$dateiname = "news.dat";
$ausgabe="bearbeitet: ";
$start = get_microtime();
list($usec, $sec) = explode(" ",microtime());
$time_s = date("YmdHis").substr($usec,1,7);
$time_u = time();
$_upd_buf = array();
## Update testen ----------------------------
if (isset($_POST['cmd']['update']))
{
$_upd_buf['data'][$id]['created'] = $time_u;
$_upd_buf['data'][$id]['lastupdate'] = $time_s;
$_upd_buf['data'][$id]['vorname'] = "Rudi";
$_upd_buf['data'][$id]['nachname'] = 'Ratlos';
$_upd_buf['data'][$id]['titel'] = 'sein dümmster Spruch';
$_upd_buf['data'][$id]['text'] = "Nun lass uns nochmal sehen
was so passiert, hier muss nun mal
etwas mehr Text rein. Ich lass mir 'was einfallen.
Hier sit ghelich der Bär los. Rudi kommt";
$ok = flat_rec_update($dateiname,$_upd_buf);
}
## Insert testen ---------------------------
elseif(isset($_POST['cmd']['insert']))
{
$id = 1;
$_upd_buf['data'][$id]['created'] = $time_u; # muss mnicht angegeben werden
$_upd_buf['data'][$id]['lastupdate'] = $time_s; # muss nicht angegeben werden
$_upd_buf['data'][$id]['vorname'] = "Ralf";
$_upd_buf['data'][$id]['nachname'] = 'Jägermeister';
$_upd_buf['data'][$id]['titel'] = 'keiner schmeckt kalt eiskalt besser';
$_upd_buf['data'][$id]['text'] = "Diesen blöden Spruch wollen wir aber hier
gar nicht mehr hören. Sowas passiert hier nun mal. Etwas mehr Text rein,
und es ist gut. Hier ist gleich der Elch los. Ralf kommt";
$id = 2;
$_upd_buf['data'][$id]['vorname'] = "Willi";
$_upd_buf['data'][$id]['nachname'] = 'Wunderlich';
$_upd_buf['data'][$id]['titel'] = 'keiner schreit besser';
$_upd_buf['data'][$id]['text'] = "Diesen Spruch können wir hier
nicht hören.";
$id = 3;
$_upd_buf['data'][$id] = array();
$ok = flat_rec_insert($dateiname,$_upd_buf);
}
## Delete testen ----------------------------
elseif(isset($_POST['cmd']['delete']))
{
$_upd_buf['data'][$id]['lastupdate'] = '20040620211459.817986';
$ok = flat_rec_delete($dateiname,$_upd_buf);
$ausgabe.="$id=$ok | ";
}
## Select testen ----------------------------
elseif(isset($_POST['cmd']['select']))
{
$ok = flat_rec_select($dateiname,$_upd_buf);
}
## Backup testen ----------------------------
elseif(isset($_POST['cmd']['backup']))
{
$backup = flat_file_backup($dateiname);
}
$ende = get_microtime();
$zeit = $ende-$start;
clearstatcache();
$filesize = filesize($dateiname);
#####################################################################
# output
#####################################################################
?>
Speichen in Flatfiles | Update-Funktion
Dateioperation:
Benötigte Zeit:
Dateigröße:
Backup-Code:
zum Löschen oder Bearbeiten eines Datensatzes muss dieser erst gelesen werden
un den File_Buffer geladen werden. Dier hier gezeigten Funktionen bedürfen
dazu also noch sogenannter Wrapper, die die Daten bereitstellen, Fehler
behandeln und die Kommunikatioon mit dem Browser vornehmen.