blob: 797ad1c818e9d6f9198ee35ef0f023a0b1b8acfd [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001/*!
2// MorgenGrauen Mudlib
3//
4// secure/memory.c -- zum Speichern von Daten ueber die gesamte Mud-Uptime
5//
6// Memory speichert seine Daten als Pointer in der extra-wizinfo. Andere
7// Programme koennen Ihre Daten im Memory ablegen. Die Daten bleiben dadurch
8// auch ueber ein Update/Reload der Blueprint erhalten.
9//
10// Die Daten werden auf Klassenebene behandelt. Jeder Clone eines Programms
11// (Blueprint) darf auf die gespeicherten Daten des Programms schreibend und
12// lesend zugreifen. Andere Programme haben keinen Zugriff auf diese Daten.
13//
14// Nur Objekte in /secure/memory_lib bzw. /secure/memory_nolib eingetragen
15// sind, haben Rechte den Memory zu nutzen.
16//
17// Die Idee, sensible Daten in der extra_wizinfo abzuspeichern entstammt
18// /secure/memory.c aus der Wunderland Mudlib von Holger@Wunderland
19*/
20#include <config.h>
21#include <wizlevels.h>
22#include <files.h>
23
24#pragma strict_types
25#pragma no_clone
26#pragma no_shadow
27#pragma no_inherit
28#pragma verbose_errors
29#pragma combine_strings
30#pragma pedantic
31//#pragma range_check
32#pragma warn_deprecated
33
34
35/* Global variable declaration */
36/*! \brief Liste mit Programmen, die den Memory nutzen duerfen
37 Die Variable wird entweder im create() oder durch manuellen Aufruf
38 von RereadProgramLists() aus /secure/memory_lib und /secure/memory_nolib
39 befuellt.
40 */
41string *known_programs;
42
43/* Function declaration - public interface */
44void create();
45
46// Payload Interface
47int Save (string key, mixed data);
48mixed Load (string key);
49int Remove(string key);
50int HaveRights();
51
52// Administrative Interface
53varargs int RereadProgramLists(int silent);
54
55// Debugging Interface
56varargs void ShowData(string user, string key);
57
58/* Function definition */
59/*! Objekt initialisieren */
60void create() {
61 mapping info;
62 seteuid(getuid(this_object()));
63
64 // Wizinfo-Pointer holen
65 if(!pointerp(info=get_extra_wizinfo(0)))
66 raise_error("WIZINFO nicht lesbar. secure/simul_efun muss neu geladen werden.!\n");
67
68 // Mein Feld der Wizinfo bei Bedarf initialisieren
69 if(!mappingp(info[MEMORY_BUFF]))
70 info[MEMORY_BUFF]=([]);
71
72 RereadProgramLists(1);
73}
74
75/*!
76 Wenn das aufrufende Programm fuer die Speichernutzung zugelassen ist,
77 wird hier der Hash zurueckgegeben unter dem seine Daten abgespeichert
78 sind. Der Hash ist derzeit der Filename des Blueprint.
79*/
80private string get_caller_hash() {
81 if (member(known_programs, program_name(previous_object())[..<3]) != -1)
82 return program_name(previous_object())[..<3];
83 else
84 return 0;
85}
86
87/*!
88 Die Hilfsfunktion liest eine Liste mit Dateinamen und gibt die Programme
89 als Array of Strings zurueck. Alle Zeilen die nicht mit einem Slash
90 anfangen, werden dabei ignoriert.
91 \param file Die auszulesende Datei.
92*/
93private mixed read_list(string file)
94{
95 mixed data;
96 if (!stringp(file) || file_size(file) == FSIZE_NOFILE )
97 return ({});
98
99 // Daten laden
100 data = explode(read_file(file)||"", "\n");
101
102 // Alle Zeilen die nicht mit / beginnen entfernen ...
103 data=regexp(data,"^/.+");
104
105 // ".c" und eventuelle Leerzeichen in jeder Zeile werden entfernt
106 data= map(data,
107 function string (string x) {return regreplace(x,"(.c)* *$","",1);});
108 return data;
109}
110
111/*!
112 Wenn die Liste mit Programmen geaendert wurde, kann sie hier per Hand
113 neu eingelesen werden.
114 \param silent Varargs Flag, um Bildschirmausgabe zu unterdruecken
115*/
116varargs int RereadProgramLists(int silent)
117{
118 // Objekte laden, die zur Mudlib gehoeren
119 known_programs = read_list("/secure/memory_lib");
120
121 // Objekte laden, die nicht zur Mudlib gehoeren
122 known_programs+=read_list("/secure/memory_nolib");
123
124 if(!silent) printf ("%O\n", known_programs);
125
126 return sizeof(known_programs);
127}
128
129/*! Zeiger auf den Speicher holen */
130private mapping get_memory_pointer(){
131 mixed info;
132
133 // Die Fehlermeldungen sind etwas ausfuehrlicher, um dem Debugger
134 // einen Hinweis auf Reparaturmoeglichkeiten zu geben
135 if(!pointerp(info=get_extra_wizinfo(0)))
136 raise_error("Wizinfo nicht ladbar. Entweder ich hab keine Rechte "
137 "oder das Mud hat ein echtes Problem!\n");
138
139 if(!mappingp(info[MEMORY_BUFF]))
140 raise_error("Ich finde meine Daten in der Wizinfo nicht. Ein EM kann "
141 "versuchen, mich neu zu laden, aber was die alten Daten "
142 "betrifft, frei nach Catty: Keine Arme, keine Kekse!\n");
143 // Da info[MEMORY_BUFF] immer ein Mapping ist (siehe Create), wird hier ein
144 // Pointer uebergeben. Dadurch werden Details zum Aufbau der extra_wizinfo
145 // nur in dieser Funktion benoetigt.
146 return info[MEMORY_BUFF];
147}
148
149/*!
150 Pruefen, ob previous_object() Nutzungsrechte fuer den Memory hat.
151 \return Gibt 1 zurueck, wenn der Aufrufende berechtigt ist, das
152 Objekt zu nutzen, sonst 0
153*/
154int HaveRights(){
155 return stringp(get_caller_hash());
156}
157
158/*!
159 Daten im Memory ablegen
160 \param key ID unter der die Daten gespeichert werden
161 \param var Zu speicherndes Datum
162*/
163int Save(string key, mixed var) {
164 string who;
165 mapping memory;
166
167 // Hash des Aufrufers holen. Hat der keinen, ist er nicht befugt,
168 // den Memory zu nutzen.
169 if(!stringp(who=get_caller_hash())) return 0;
170
171 // Wenn kein Key uebergeben wird, kann auch nichts gespeichert werden.
172 if(!stringp(key)) return 0;
173
174 // (hoffentlich) globalen memory_pointer holen
175 memory = get_memory_pointer();
176
177 // Wenn keine Daten da sind, muss man auch nichts anlegen. Rueckgabewert
178 // ist dennoch 1, weil Load bei unbekannten Keys auch 0 liefert, die
179 // Null wird also korrekt gespeichert, irgendwie. Das muss aber nach dem
180 // get_memory_pointer() passieren, da sonst das Korrekte Funktionieren von
181 // Load nicht sichergestellt ist.
182 if(var==0) return 1;
183
184 // Erster Aufruf durch PO? Dann muss sein Speicherbereich initialisiert
185 // werden
186 if(!member(memory,who))
187 memory[who]=([]);
188
189 // Endlich! Daten koennen gespeichert werden.
190 memory[who][key]=var;
191
192 return 1;
193}
194
195/*!
196 Daten ausgeben/referenzieren
197 \param key Id unter der die Daten gespeichert sind.
198*/
199mixed Load(string key) {
200 string who;
201 mapping memory;
202
203 // Hash des Aufrufers holen. Hat der keinen, ist er nicht befugt,
204 // den Memory zu nutzen.
205 if(!stringp(who=get_caller_hash())) return 0;
206
207 // Wenn kein Key uebergeben wird, kann auch nichts gespeichert werden.
208 if(!stringp(key)) return 0;
209
210 // (hoffentlich) globalen memory_pointer holen
211 memory = get_memory_pointer();
212
213 // Das Objekt hat noch nie Save() aufgerufen.
214 if(!member(memory,who))
215 return 0;
216
217 // Unter diesem Key ist noch nichts gespeichert.
218 if(!member(memory[who],key))
219 return 0;
220
221 // Gespeicherten Wert zurueckgeben
222 return memory[who][key];
223}
224
225/*!
226 Ein Eintrag oder alle Eintraege werden geloescht
227 \param key Id unter der die Daten gespeichert sind.
228 Wird kein Key uebergeben, werden alle Daten des Objekts
229 geloescht.
230*/
231varargs int Remove(string key) {
232 string who;
233 mapping memory;
234
235 // Hash des Aufrufers holen. Hat der keinen, ist er nicht befugt,
236 // den Memory zu nutzen.
237 if(!stringp(who=get_caller_hash())) return 0;
238
239 // (hoffentlich) globalen memory_pointer holen
240 memory = get_memory_pointer();
241
242 // Das Objekt hat noch nie Save() aufgerufen.
243 if(!member(memory,who)) return 0;
244
245 // Wenn kein Key uebergeben wird, wird alles zum Objekt gehoerende geloescht.
246 if(stringp(key)){
247 // Unter diesem Key ist nichts gespeichert.
248 if(!member(memory[who],key)) return 0;
249
250 // Wert unter Key fuer das File loeschen
251 m_delete(memory[who], key);
252
253 } else {
254 // Alles fuer das File loeschen
255 m_delete(memory, who);
256 }
257
258 return 1;
259}
260
261varargs void ShowData(string user, string key)
262{
263 // Bekannte Objekte
264 if (!ELDER_SECURITY )
265 printf("I'm fine. Thanks for asking.\n");
266 else {
267 printf("known_programs:\n%O\n\n", known_programs);
268 // EM duerfen sich auch noch zuscrollen lassen, wenn sie wollen
269 if (ARCH_SECURITY && user)
270 {
271 mapping data = get_memory_pointer();
272 if (!member(data,user))
273 printf("memory: Keine Daten fuer %s vorhanden.\n",user);
274 else if (user && key)
275 printf("memory: Daten fuer User %s, Key %s:\n%O\n",user, key,
276 data[user][key]);
277 else
278 printf("memory: Daten fuer User %s:\n%O\n",user,data[user]);
279 }
280 else
281 {
282 mapping memory;
283 memory = get_memory_pointer();
284 // Andere bekommen eine anonymisierte Version
285 printf("memory: (Nur Feldnamen, keine Daten)\n");
286 foreach (string program, mapping data: memory ) {
287 if ( mappingp(data) && sizeof(data) ){
288 printf(break_string(
289 implode(m_indices(data),";\n"), 78,
290 sprintf(" %-50s: ",program)),1);
291 }
292 else
293 printf(" %-50s: - leer -\n", program);
294 }
295 }
296 }
297 return;
298}
299