blob: efc3c1fbae9eed759a484c00be5adda7f7f6fa22 [file] [log] [blame]
/*!
// MorgenGrauen Mudlib
//
// secure/memory.c -- zum Speichern von Daten ueber die gesamte Mud-Uptime
//
// Memory speichert seine Daten als Pointer in der extra-wizinfo. Andere
// Programme koennen Ihre Daten im Memory ablegen. Die Daten bleiben dadurch
// auch ueber ein Update/Reload der Blueprint erhalten.
//
// Die Daten werden auf Klassenebene behandelt. Jeder Clone eines Programms
// (Blueprint) darf auf die gespeicherten Daten des Programms schreibend und
// lesend zugreifen. Andere Programme haben keinen Zugriff auf diese Daten.
//
// Nur Objekte in /secure/memory_lib bzw. /secure/memory_nolib eingetragen
// sind, haben Rechte den Memory zu nutzen.
//
// Die Idee, sensible Daten in der extra_wizinfo abzuspeichern entstammt
// /secure/memory.c aus der Wunderland Mudlib von Holger@Wunderland
*/
#include <config.h>
#include <wizlevels.h>
#include <files.h>
#pragma strict_types
#pragma no_clone
#pragma no_shadow
#pragma no_inherit
#pragma verbose_errors
#pragma combine_strings
#pragma pedantic
//#pragma range_check
#pragma warn_deprecated
/* Global variable declaration */
/*! \brief Liste mit Programmen, die den Memory nutzen duerfen
Die Variable wird entweder im create() oder durch manuellen Aufruf
von RereadProgramLists() aus /secure/memory_lib und /secure/memory_nolib
befuellt.
*/
string *known_programs;
/* Function declaration - public interface */
void create();
// Payload Interface
int Save (string key, mixed data);
mixed Load (string key);
int Remove(string key);
int HaveRights();
// Administrative Interface
varargs int RereadProgramLists(int silent);
// Debugging Interface
varargs void ShowData(string user, string key);
/* Function definition */
/*! Objekt initialisieren */
void create() {
seteuid(getuid(this_object()));
// Wizinfo-Pointer holen
mixed *info = get_extra_wizinfo(0);
if(!pointerp(info))
raise_error("WIZINFO nicht lesbar. secure/simul_efun muss neu "
"geladen werden.\n");
mapping memory = info[MEMORY_BUFF];
// Mein Feld der Wizinfo bei Bedarf initialisieren
if(!mappingp(memory))
info[MEMORY_BUFF]=([]);
RereadProgramLists(1);
}
/*!
Wenn das aufrufende Programm fuer die Speichernutzung zugelassen ist,
wird hier der Hash zurueckgegeben unter dem seine Daten abgespeichert
sind. Der Hash ist derzeit der Filename des Blueprint.
*/
private string get_caller_hash() {
if (member(known_programs, program_name(previous_object())[..<3]) != -1)
return program_name(previous_object())[..<3];
else
return 0;
}
/*!
Die Hilfsfunktion liest eine Liste mit Dateinamen und gibt die Programme
als Array of Strings zurueck. Alle Zeilen die nicht mit einem Slash
anfangen, werden dabei ignoriert.
\param file Die auszulesende Datei.
*/
private mixed read_list(string file)
{
mixed data;
if (!stringp(file) || file_size(file) == FSIZE_NOFILE )
return ({});
// Daten laden
data = explode(read_file(file)||"", "\n");
// Alle Zeilen die nicht mit / beginnen entfernen ...
data=regexp(data,"^/.+");
// ".c" und eventuelle Leerzeichen in jeder Zeile werden entfernt
data= map(data,
function string (string x) {return regreplace(x,"(.c)* *$","",1);});
return data;
}
/*!
Wenn die Liste mit Programmen geaendert wurde, kann sie hier per Hand
neu eingelesen werden.
\param silent Varargs Flag, um Bildschirmausgabe zu unterdruecken
*/
varargs int RereadProgramLists(int silent)
{
// Objekte laden, die zur Mudlib gehoeren
known_programs = read_list("/secure/memory_lib");
// Objekte laden, die nicht zur Mudlib gehoeren
known_programs+=read_list("/secure/memory_nolib");
if(!silent) printf ("%O\n", known_programs);
return sizeof(known_programs);
}
/*! Zeiger auf den Speicher holen */
private mapping get_memory_pointer(){
mixed *info = get_extra_wizinfo(0);
// Die Fehlermeldungen sind etwas ausfuehrlicher, um dem Debugger
// einen Hinweis auf Reparaturmoeglichkeiten zu geben
if(!pointerp(info))
raise_error("Wizinfo nicht ladbar. Entweder ich hab keine Rechte "
"oder das Mud hat ein echtes Problem!\n");
if(!mappingp(info[MEMORY_BUFF]))
raise_error("Ich finde meine Daten in der Wizinfo nicht. Ein EM kann "
"versuchen, mich neu zu laden, aber was die alten Daten "
"betrifft, frei nach Catty: Keine Arme, keine Kekse!\n");
// Da info[MEMORY_BUFF] immer ein Mapping ist (siehe Create), wird hier ein
// Pointer uebergeben. Dadurch werden Details zum Aufbau der extra_wizinfo
// nur in dieser Funktion benoetigt.
return info[MEMORY_BUFF];
}
/*!
Pruefen, ob previous_object() Nutzungsrechte fuer den Memory hat.
\return Gibt 1 zurueck, wenn der Aufrufende berechtigt ist, das
Objekt zu nutzen, sonst 0
*/
int HaveRights(){
return stringp(get_caller_hash());
}
/*!
Daten im Memory ablegen
\param key ID unter der die Daten gespeichert werden
\param var Zu speicherndes Datum
*/
int Save(string key, mixed var) {
string who;
mapping memory;
// Hash des Aufrufers holen. Hat der keinen, ist er nicht befugt,
// den Memory zu nutzen.
if(!stringp(who=get_caller_hash())) return 0;
// Wenn kein Key uebergeben wird, kann auch nichts gespeichert werden.
if(!stringp(key)) return 0;
// (hoffentlich) globalen memory_pointer holen
memory = get_memory_pointer();
// Wenn keine Daten da sind, muss man auch nichts anlegen. Rueckgabewert
// ist dennoch 1, weil Load bei unbekannten Keys auch 0 liefert, die
// Null wird also korrekt gespeichert, irgendwie. Das muss aber nach dem
// get_memory_pointer() passieren, da sonst das Korrekte Funktionieren von
// Load nicht sichergestellt ist.
if(var==0) return 1;
// Erster Aufruf durch PO? Dann muss sein Speicherbereich initialisiert
// werden
if(!member(memory,who))
memory[who]=([]);
// Endlich! Daten koennen gespeichert werden.
memory[who][key]=var;
return 1;
}
/*!
Daten ausgeben/referenzieren
\param key Id unter der die Daten gespeichert sind.
*/
mixed Load(string key) {
string who;
mapping memory;
// Hash des Aufrufers holen. Hat der keinen, ist er nicht befugt,
// den Memory zu nutzen.
if(!stringp(who=get_caller_hash())) return 0;
// Wenn kein Key uebergeben wird, kann auch nichts gespeichert werden.
if(!stringp(key)) return 0;
// (hoffentlich) globalen memory_pointer holen
memory = get_memory_pointer();
// Das Objekt hat noch nie Save() aufgerufen.
if(!member(memory,who))
return 0;
// Unter diesem Key ist noch nichts gespeichert.
if(!member(memory[who],key))
return 0;
// Gespeicherten Wert zurueckgeben
return memory[who][key];
}
/*!
Ein Eintrag oder alle Eintraege werden geloescht
\param key Id unter der die Daten gespeichert sind.
Wird kein Key uebergeben, werden alle Daten des Objekts
geloescht.
*/
varargs int Remove(string key) {
string who;
mapping memory;
// Hash des Aufrufers holen. Hat der keinen, ist er nicht befugt,
// den Memory zu nutzen.
if(!stringp(who=get_caller_hash())) return 0;
// (hoffentlich) globalen memory_pointer holen
memory = get_memory_pointer();
// Das Objekt hat noch nie Save() aufgerufen.
if(!member(memory,who)) return 0;
// Wenn kein Key uebergeben wird, wird alles zum Objekt gehoerende geloescht.
if(stringp(key)){
// Unter diesem Key ist nichts gespeichert.
if(!member(memory[who],key)) return 0;
// Wert unter Key fuer das File loeschen
m_delete(memory[who], key);
} else {
// Alles fuer das File loeschen
m_delete(memory, who);
}
return 1;
}
varargs void ShowData(string user, string key)
{
// Bekannte Objekte
if (!ELDER_SECURITY )
printf("I'm fine. Thanks for asking.\n");
else {
printf("known_programs:\n%O\n\n", known_programs);
// EM duerfen sich auch noch zuscrollen lassen, wenn sie wollen
if (ARCH_SECURITY && user)
{
mapping data = get_memory_pointer();
if (!member(data,user))
printf("memory: Keine Daten fuer %s vorhanden.\n",user);
else if (user && key)
printf("memory: Daten fuer User %s, Key %s:\n%O\n",user, key,
data[user][key]);
else
printf("memory: Daten fuer User %s:\n%O\n",user,data[user]);
}
else
{
mapping memory;
memory = get_memory_pointer();
// Andere bekommen eine anonymisierte Version
printf("memory: (Nur Feldnamen, keine Daten)\n");
foreach (string program, mapping data: memory ) {
if ( mappingp(data) && sizeof(data) ){
printf(break_string(
implode(m_indices(data),";\n"), 78,
sprintf(" %-50s: ",program)),1);
}
else
printf(" %-50s: - leer -\n", program);
}
}
}
return;
}