blob: efc3c1fbae9eed759a484c00be5adda7f7f6fa22 [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() {
MG Mud User88f12472016-06-24 23:31:02 +020061 seteuid(getuid(this_object()));
62
63 // Wizinfo-Pointer holen
Zesstra0d1bd1d2019-11-23 10:19:15 +010064 mixed *info = get_extra_wizinfo(0);
65 if(!pointerp(info))
66 raise_error("WIZINFO nicht lesbar. secure/simul_efun muss neu "
67 "geladen werden.\n");
MG Mud User88f12472016-06-24 23:31:02 +020068
Zesstra0d1bd1d2019-11-23 10:19:15 +010069 mapping memory = info[MEMORY_BUFF];
MG Mud User88f12472016-06-24 23:31:02 +020070 // Mein Feld der Wizinfo bei Bedarf initialisieren
Zesstra0d1bd1d2019-11-23 10:19:15 +010071 if(!mappingp(memory))
MG Mud User88f12472016-06-24 23:31:02 +020072 info[MEMORY_BUFF]=([]);
73
74 RereadProgramLists(1);
75}
76
77/*!
78 Wenn das aufrufende Programm fuer die Speichernutzung zugelassen ist,
79 wird hier der Hash zurueckgegeben unter dem seine Daten abgespeichert
80 sind. Der Hash ist derzeit der Filename des Blueprint.
81*/
82private string get_caller_hash() {
83 if (member(known_programs, program_name(previous_object())[..<3]) != -1)
84 return program_name(previous_object())[..<3];
85 else
86 return 0;
87}
88
89/*!
90 Die Hilfsfunktion liest eine Liste mit Dateinamen und gibt die Programme
91 als Array of Strings zurueck. Alle Zeilen die nicht mit einem Slash
92 anfangen, werden dabei ignoriert.
93 \param file Die auszulesende Datei.
94*/
95private mixed read_list(string file)
96{
97 mixed data;
98 if (!stringp(file) || file_size(file) == FSIZE_NOFILE )
99 return ({});
100
101 // Daten laden
102 data = explode(read_file(file)||"", "\n");
103
104 // Alle Zeilen die nicht mit / beginnen entfernen ...
105 data=regexp(data,"^/.+");
106
107 // ".c" und eventuelle Leerzeichen in jeder Zeile werden entfernt
108 data= map(data,
109 function string (string x) {return regreplace(x,"(.c)* *$","",1);});
110 return data;
111}
112
113/*!
114 Wenn die Liste mit Programmen geaendert wurde, kann sie hier per Hand
115 neu eingelesen werden.
116 \param silent Varargs Flag, um Bildschirmausgabe zu unterdruecken
117*/
118varargs int RereadProgramLists(int silent)
119{
120 // Objekte laden, die zur Mudlib gehoeren
121 known_programs = read_list("/secure/memory_lib");
122
123 // Objekte laden, die nicht zur Mudlib gehoeren
124 known_programs+=read_list("/secure/memory_nolib");
125
126 if(!silent) printf ("%O\n", known_programs);
127
128 return sizeof(known_programs);
129}
130
131/*! Zeiger auf den Speicher holen */
132private mapping get_memory_pointer(){
Zesstra0d1bd1d2019-11-23 10:19:15 +0100133 mixed *info = get_extra_wizinfo(0);
MG Mud User88f12472016-06-24 23:31:02 +0200134
135 // Die Fehlermeldungen sind etwas ausfuehrlicher, um dem Debugger
136 // einen Hinweis auf Reparaturmoeglichkeiten zu geben
Zesstra0d1bd1d2019-11-23 10:19:15 +0100137 if(!pointerp(info))
MG Mud User88f12472016-06-24 23:31:02 +0200138 raise_error("Wizinfo nicht ladbar. Entweder ich hab keine Rechte "
139 "oder das Mud hat ein echtes Problem!\n");
140
141 if(!mappingp(info[MEMORY_BUFF]))
142 raise_error("Ich finde meine Daten in der Wizinfo nicht. Ein EM kann "
143 "versuchen, mich neu zu laden, aber was die alten Daten "
144 "betrifft, frei nach Catty: Keine Arme, keine Kekse!\n");
145 // Da info[MEMORY_BUFF] immer ein Mapping ist (siehe Create), wird hier ein
146 // Pointer uebergeben. Dadurch werden Details zum Aufbau der extra_wizinfo
147 // nur in dieser Funktion benoetigt.
Zesstra0d1bd1d2019-11-23 10:19:15 +0100148 return info[MEMORY_BUFF];
MG Mud User88f12472016-06-24 23:31:02 +0200149}
150
151/*!
152 Pruefen, ob previous_object() Nutzungsrechte fuer den Memory hat.
153 \return Gibt 1 zurueck, wenn der Aufrufende berechtigt ist, das
154 Objekt zu nutzen, sonst 0
155*/
156int HaveRights(){
157 return stringp(get_caller_hash());
158}
159
160/*!
161 Daten im Memory ablegen
162 \param key ID unter der die Daten gespeichert werden
163 \param var Zu speicherndes Datum
164*/
165int Save(string key, mixed var) {
166 string who;
167 mapping memory;
168
169 // Hash des Aufrufers holen. Hat der keinen, ist er nicht befugt,
170 // den Memory zu nutzen.
171 if(!stringp(who=get_caller_hash())) return 0;
172
173 // Wenn kein Key uebergeben wird, kann auch nichts gespeichert werden.
174 if(!stringp(key)) return 0;
175
176 // (hoffentlich) globalen memory_pointer holen
177 memory = get_memory_pointer();
178
179 // Wenn keine Daten da sind, muss man auch nichts anlegen. Rueckgabewert
180 // ist dennoch 1, weil Load bei unbekannten Keys auch 0 liefert, die
181 // Null wird also korrekt gespeichert, irgendwie. Das muss aber nach dem
182 // get_memory_pointer() passieren, da sonst das Korrekte Funktionieren von
183 // Load nicht sichergestellt ist.
184 if(var==0) return 1;
185
186 // Erster Aufruf durch PO? Dann muss sein Speicherbereich initialisiert
187 // werden
188 if(!member(memory,who))
189 memory[who]=([]);
190
191 // Endlich! Daten koennen gespeichert werden.
192 memory[who][key]=var;
193
194 return 1;
195}
196
197/*!
198 Daten ausgeben/referenzieren
199 \param key Id unter der die Daten gespeichert sind.
200*/
201mixed Load(string key) {
202 string who;
203 mapping memory;
204
205 // Hash des Aufrufers holen. Hat der keinen, ist er nicht befugt,
206 // den Memory zu nutzen.
207 if(!stringp(who=get_caller_hash())) return 0;
208
209 // Wenn kein Key uebergeben wird, kann auch nichts gespeichert werden.
210 if(!stringp(key)) return 0;
211
212 // (hoffentlich) globalen memory_pointer holen
213 memory = get_memory_pointer();
214
215 // Das Objekt hat noch nie Save() aufgerufen.
216 if(!member(memory,who))
217 return 0;
218
219 // Unter diesem Key ist noch nichts gespeichert.
220 if(!member(memory[who],key))
221 return 0;
222
223 // Gespeicherten Wert zurueckgeben
224 return memory[who][key];
225}
226
227/*!
228 Ein Eintrag oder alle Eintraege werden geloescht
229 \param key Id unter der die Daten gespeichert sind.
230 Wird kein Key uebergeben, werden alle Daten des Objekts
231 geloescht.
232*/
233varargs int Remove(string key) {
234 string who;
235 mapping memory;
236
237 // Hash des Aufrufers holen. Hat der keinen, ist er nicht befugt,
238 // den Memory zu nutzen.
239 if(!stringp(who=get_caller_hash())) return 0;
240
241 // (hoffentlich) globalen memory_pointer holen
242 memory = get_memory_pointer();
243
244 // Das Objekt hat noch nie Save() aufgerufen.
245 if(!member(memory,who)) return 0;
246
247 // Wenn kein Key uebergeben wird, wird alles zum Objekt gehoerende geloescht.
248 if(stringp(key)){
249 // Unter diesem Key ist nichts gespeichert.
250 if(!member(memory[who],key)) return 0;
251
252 // Wert unter Key fuer das File loeschen
253 m_delete(memory[who], key);
254
255 } else {
256 // Alles fuer das File loeschen
257 m_delete(memory, who);
258 }
259
260 return 1;
261}
262
263varargs void ShowData(string user, string key)
264{
265 // Bekannte Objekte
266 if (!ELDER_SECURITY )
267 printf("I'm fine. Thanks for asking.\n");
268 else {
269 printf("known_programs:\n%O\n\n", known_programs);
270 // EM duerfen sich auch noch zuscrollen lassen, wenn sie wollen
271 if (ARCH_SECURITY && user)
272 {
273 mapping data = get_memory_pointer();
274 if (!member(data,user))
275 printf("memory: Keine Daten fuer %s vorhanden.\n",user);
276 else if (user && key)
277 printf("memory: Daten fuer User %s, Key %s:\n%O\n",user, key,
278 data[user][key]);
279 else
280 printf("memory: Daten fuer User %s:\n%O\n",user,data[user]);
281 }
282 else
283 {
284 mapping memory;
285 memory = get_memory_pointer();
286 // Andere bekommen eine anonymisierte Version
287 printf("memory: (Nur Feldnamen, keine Daten)\n");
288 foreach (string program, mapping data: memory ) {
289 if ( mappingp(data) && sizeof(data) ){
290 printf(break_string(
291 implode(m_indices(data),";\n"), 78,
292 sprintf(" %-50s: ",program)),1);
293 }
294 else
295 printf(" %-50s: - leer -\n", program);
296 }
297 }
298 }
299 return;
300}
301