blob: 6623808bc4557ba3b0d2f43044ec7eb71b8bfb1f [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001static mapping projects=([]);
2static string *insecure,*deputy_files;
3
4int ReloadInsecureFile()
5{
6 insecure = efun::explode( read_file("/secure/INSECURE") || "", "\n" );
7 insecure -= ({""});
8 insecure = map( insecure, #'lower_case/*'*/ );
9 return(1);
10}
11
12void LoadDeputyFileList()
13{
14 // Leseberechtigungen fuer /log/ARCH/* setzen
15 deputy_files = efun::explode( read_file("/log/ARCH/DEPUTY_FILELIST") || "",
16 "\n" ) - ({""});
17 return;
18}
19
Zesstra3e9a6c92018-11-06 22:38:42 +010020// Normalisiert den Pfad und liefert ein Array mit Pfadelementen.
21// expand bestimmt, ob im Pfad +, ~ oder P_CURRENTDIR expandiert werden oder
22// nicht.
Zesstraccc58df2018-11-07 23:25:20 +010023string *path_array(string path) {
MG Mud User88f12472016-06-24 23:31:02 +020024
Zesstra3e9a6c92018-11-06 22:38:42 +010025 if (!sizeof(path))
MG Mud User88f12472016-06-24 23:31:02 +020026 return ({"",""}); // additional "" to yield "/" later.
27
Zesstra3e9a6c92018-11-06 22:38:42 +010028 // remove multiple '/'erstn gv
29 path = regreplace(path, "/+", "/", 1);
30
31 // /../ irgendwo im Pfad behandeln, das und vorheriges Element
32 // rausschneiden.
Zesstraf7905352018-11-05 22:46:16 +010033 // Einschraenkungen der RegExp:
MG Mud User88f12472016-06-24 23:31:02 +020034 // /a/b/../../d wuerde nur durch Wiederholung aufgeloest.
35 // /../d wird nicht richtig aufgeloest.
36 //regreplace("/d/inseln/toeter/room/hoehle/../wald/bla.c","(.*)\/[^/]+/\.\.
37 // /(.*)", "\\1\/\\2", RE_GLOBAL)
Zesstraf7905352018-11-05 22:46:16 +010038
Zesstra3e9a6c92018-11-06 22:38:42 +010039 string *p_arr = explode(path, "/") - ({"."});
40
41 // /../ irgendwo im Pfad behandeln, das und vorheriges Element
42 // rausschneiden.
MG Mud User88f12472016-06-24 23:31:02 +020043 // dies sieht schlimmer aus als es ist (member ist O(n)), solange das Array
44 // nicht gross wird.
45 int p;
Zesstra3e9a6c92018-11-06 22:38:42 +010046 while((p=member(p_arr, "..")) != -1)
Bugfix6afe0ae2019-12-04 17:15:00 +010047 {
48 if(sizeof(p_arr)-1>p)
49 {
Zesstra3e9a6c92018-11-06 22:38:42 +010050 p_arr = p_arr[0..p-2]+p_arr[p+1..];
Bugfix6afe0ae2019-12-04 17:15:00 +010051 }
52 else
53 {
54 // Hier ist keine weitere Abfrage noetig, da bei einem niedrigeren
55 // zweiten Index ein leeres Array zurueckgegeben wird.
56 p_arr = p_arr[0..p-2];
57 }
58 }
MG Mud User88f12472016-06-24 23:31:02 +020059
Zesstra3e9a6c92018-11-06 22:38:42 +010060 // Pfade absolutieren
61 // leeres Pfadarray fuehrt zur Rueckgabe von einem Array, was hinterher "/"
62 // ergibt, Arrays mit nur einem Element bekommen in jedem Fall ein Element
63 // "" an den Anfang, laengere Arrays kriegen falls noetig ein "".
64 switch(sizeof(p_arr))
65 {
66 case 0:
67 return ({"",""});
68 case 1:
MG Mud User88f12472016-06-24 23:31:02 +020069 p_arr = ({""}) + p_arr;
Zesstra3e9a6c92018-11-06 22:38:42 +010070 break;
71 default:
72 if (p_arr[0] != "")
73 p_arr = ({""}) + p_arr;
74 }
MG Mud User88f12472016-06-24 23:31:02 +020075
Zesstra3e9a6c92018-11-06 22:38:42 +010076 return p_arr;
77}
78
Zesstrab49624a2018-11-07 21:40:16 +010079// Pfadnormalisierung OHNE Ersetzungen von +, ~ und P_CURRENTDIR (war mal mit)
80// Eigentlich hier ziemlich unnuetz, aber nen Haufen Objekte im Mud ruft das.
Zesstra3e9a6c92018-11-06 22:38:42 +010081string _get_path(string path, string user) {
Zesstraccc58df2018-11-07 23:25:20 +010082 return implode(path_array(path),"/");
Zesstrab45f3b42018-11-07 21:54:07 +010083}
84
Zesstrab49624a2018-11-07 21:40:16 +010085// Diese Funktion wird vom Driver nur fuer den Editor ed gerufen, aber der
Zesstraccc58df2018-11-07 23:25:20 +010086// Rest vom MG ruft es teilweise auch.
Zesstrab45f3b42018-11-07 21:54:07 +010087string make_path_absolute(string path) {
Zesstraccc58df2018-11-07 23:25:20 +010088 return implode(path_array(path),"/");
MG Mud User88f12472016-06-24 23:31:02 +020089}
90
91static int project_access(string user, string project)
92{
MG Mud User88f12472016-06-24 23:31:02 +020093 if (!member(projects,project))
94 {
Zesstra32202602019-11-28 22:03:31 +010095 string s=read_file(PROJECTDIR+"/"+project+"/ACCESS_RIGHTS");
MG Mud User88f12472016-06-24 23:31:02 +020096 if(!s||s=="")
97 return 0;
Zesstra32202602019-11-28 22:03:31 +010098 mapping tmp=([]);
99 foreach(string line: explode(s,"\n")-({""}))
MG Mud User88f12472016-06-24 23:31:02 +0200100 {
Zesstra32202602019-11-28 22:03:31 +0100101 if (line[0]=='*')
102 tmp[line[1..]]=2;
MG Mud User88f12472016-06-24 23:31:02 +0200103 else
Zesstra32202602019-11-28 22:03:31 +0100104 tmp[line]=1;
MG Mud User88f12472016-06-24 23:31:02 +0200105 }
106 projects[project]=({tmp,time()});
107 return tmp[user];
108 }
109 projects[project][1]=time();
110 return projects[project][0][user];
111}
112
113void OutdateProjectCache(string project)
114{
115 m_delete(projects,project);
116}
117
118static void _cleanup_projects() {
119 int i;
120 mixed *users;
121
122 for (users=m_indices(projects),i=sizeof(users)-1;i>=0;i--)
123 if((time()-projects[users[i]][1])>1800)
124 m_delete(projects,users[i]);
125}
126
127int access_rights(string *p_arr, string euid)
128{
Zesstrad872d182019-11-28 20:13:02 +0100129 int i = sizeof(p_arr) - 2;
MG Mud User88f12472016-06-24 23:31:02 +0200130
131 while ( i >= 0 &&
132 file_size( implode(p_arr[0..i], "/") + "/access_rights.c" ) < 0 )
133 i--;
134
135 if ( i < 0 )
136 return 0;
137
Zesstrad872d182019-11-28 20:13:02 +0100138 if ( !catch(i = ({int})call_other(
MG Mud User88f12472016-06-24 23:31:02 +0200139 implode(p_arr[0..i], "/") + "/access_rights",
140 "access_rights", euid,
141 implode(p_arr[i+1..], "/") ); publish) )
142 return i;
143
144 return 0;
145}
146
Zesstra078991b2013-01-26 11:56:45 +0100147// Hngl. Inkludieren aus /sys ist hier doof.
148#ifndef FSIZE_DIR
149#define FSIZE_DIR -2
150#endif
MG Mud User88f12472016-06-24 23:31:02 +0200151mixed valid_write(string path, string euid, string fun, object obj)
152{
153 int s,lvl;
154 string *strs;
155 int *date;
156
157 if (member(path,' ')!=-1) return 0;
158
159 // Unter LIBDATADIR (/data) sollen komplett identische Schreibrechte
Zesstra078991b2013-01-26 11:56:45 +0100160 // vergeben werden. Ausnahme ist jedoch fun=="mkdir": hier soll die
161 // Erstellung eines Verezeichnisses jedem erlaubt sein, wenn es das
162 // entsprechende Verzeichnis ausserhalb /data/ schon gibt.
MG Mud User88f12472016-06-24 23:31:02 +0200163 if (sizeof(path) > 6
Zesstraeb0ceb82018-02-28 21:31:07 +0100164 && path[0..5] == "/"LIBDATADIR"/")
165 {
Zesstra078991b2013-01-26 11:56:45 +0100166 if (fun=="mkdir")
Zesstraeb0ceb82018-02-28 21:31:07 +0100167 {
168 // wenn schon ausserhalb /data/ existent: erlauben
169 if (file_size(path[5..]) == FSIZE_DIR)
170 return 1;
171 // sonst fall-through und normale gucken, ob der Aufrufer ausserhalb
172 // /data/ denn duerfte.
173 }
MG Mud User88f12472016-06-24 23:31:02 +0200174 return valid_write(path[5..], euid, fun, obj) != 0;
Zesstra078991b2013-01-26 11:56:45 +0100175 }
MG Mud User88f12472016-06-24 23:31:02 +0200176
177 switch(fun) {
178 case "log_file":
Zesstraccc58df2018-11-07 23:25:20 +0100179 strs=path_array("/"+path);
MG Mud User88f12472016-06-24 23:31:02 +0200180 path = implode(strs, "/");
181 strs -= ({""}); // remove trailing and leading "/".
182 if (sizeof(strs)>1 && strs[0]=="log") return path;
183 return 0;
184 case "save_object":
Zesstraa43be352018-11-06 22:40:32 +0100185 if (!sizeof(path)) return 0;
Zesstraccc58df2018-11-07 23:25:20 +0100186 strs=path_array("/"+path);
MG Mud User88f12472016-06-24 23:31:02 +0200187 break;
188 case "ed_start":
Zesstraa43be352018-11-06 22:40:32 +0100189 if (sizeof(path))
Zesstraccc58df2018-11-07 23:25:20 +0100190 strs=path_array(path);
Zesstraa43be352018-11-06 22:40:32 +0100191 else
192 strs=({"players",euid,".err"});
MG Mud User88f12472016-06-24 23:31:02 +0200193 break;
194 default:
Zesstraccc58df2018-11-07 23:25:20 +0100195 strs=path_array(path);
MG Mud User88f12472016-06-24 23:31:02 +0200196 }
197
198 if (!euid || euid=="NOBODY" || euid=="ftp" || euid=="anonymous") return 0;
199
200 // Pfad soll ab jetzt auf jeden Fall absolut sein.
201 if (strs[0] != "")
202 path = "/" + implode(strs, "/");
203 else
204 path=implode(strs, "/");
205
206 // fuer die Rechtebestimmung "/" an Anfang und Ende entfernen
207 strs -= ({""});
208
209 //Root-Objekte und Master duerfen immer.
210 if (euid == ROOTID || obj==TO) return path;
211
212 lvl=query_wiz_level(euid);
213
214 //Toplevel: nur EM+
215 if ((s=sizeof(strs))<=1) return lvl>=ARCH_LVL;
216
217 switch(strs[0]) {
218 case TMPDIR:
219 return 1;
220
221 case STDDIR:
222 case SYSDIR:
223 case LIBOBJDIR:
224 case ETCDIR:
225 case LIBROOMDIR:
226 return lvl>=ARCH_LVL;
227
228 case LIBITEMDIR:
229 return lvl>=ELDER_LVL;
230
231 case SPELLBOOKDIR:
232 // wenn unterhalb eines unterverzeichnisses des Stils "gilde", dann ists
233 // einfach
234 if (sizeof(strs) > 2
235 && guild_master(euid, strs[1]))
236 return 1;
237
238 // sonst nur EMs bzw. access_rights.c fragen.
239 return ((lvl>=ARCH_LVL) || access_rights(strs,euid));
240
241 case GUILDDIR:
242 // wenn unterhalb eines unterverzeichnisses des Stils "filde.gilde",
243 // dann ists einfach
244 if (sizeof(strs) > 2) {
245 string *tmp = explode(strs[1],"files.");
246 if (sizeof(tmp) == 2) {
247 if (guild_master(euid, tmp[1]))
248 return 1;
249 // Objekte dort sollen auch schreiben duerfen.
250 if (euid == ("GUILD."+tmp[1]))
251 return 1;
252 }
253 }
254 // sonst nur EMs bzw. access_rights.c fragen.
255 return ((lvl>=ARCH_LVL) || access_rights(strs,euid));
256
257 case DOCDIR:
258 if ( s > 1 && (strs[1] == "balance") )
259 return ((lvl>=ARCH_LVL) || access_rights(strs,euid));
260 else
261 return ((lvl>=SPECIAL_LVL) || access_rights(strs,euid));
262
263 case FTPDIR:
264 if ( s > 1 && (strs[1] == "incoming" || strs[1] == "tmp" ||
265 s == 3 && strs[1] == "News" && strs[2] == euid+".news") )
266 return 1;
267
268 if (lvl>=ELDER_LVL)
269 return 1;
270
271 return 0;
272
273 case MAILDIR:
274 if (euid==MAILID || strs[1]=="spool") break;
275 return 0;
276
Zesstra8a3f8682017-01-30 23:04:20 +0100277 case "save":
MG Mud User88f12472016-06-24 23:31:02 +0200278 if (lvl>=ARCH_LVL) return 1;
279 if (s==3 && strs[1] == euid[0..0] &&
280 (strs[2]==euid+".o" || strs[2]==euid)) break;
281 return 0;
282
283 case LIBLOGDIR:
284 /* auf /log/ARCH/ haben wirklich nur EMs Zugriff */
285 if (strs[1]=="ARCH" && lvl<ARCH_LVL) return 0;
286
287 /* alles andere duerfen auch Weise... */
288 if (lvl>=ELDER_LVL) return 1;
289
290 /* Allgemeine logfiles in /log duerfen wirklich nur geschrieben werden */
291 if (s==2 && strs[1][0]>='A' && strs[1][0]<='Z' && fun != "write_file")
292 return 0;
293
294 /* Unterhalb von /log/syslog darf nur geschrieben werden */
295 if (s>1 && strs[1]=="syslog" && fun != "write_file")
296 return 0;
297
298 /* loggen ins eigene repfile immer erlauben */
299 if (s==3 && strs[1]=="report" &&
300 strs[2]==explode(euid, ".")[<1]+".rep") break;
301
302 /* in fremden Verzeichnissen hat niemand was zu loggen */
303 if (get_wiz_level(strs[1]) >= WIZARD_LVL &&
304 strs[1] != efun::explode(euid, ".")[<1])
305 return 0;
306 break;
307
308 case WIZARDDIR:
309 /* kein Zugriff auf Objekte mit hoeheren Rechten */
310 if (query_wiz_level(strs[1]) > lvl) return 0;
311
312 /* Magier selbst oder Weise duerfen hier schreiben */
313 if ((IS_WIZARD(euid) && euid==strs[1])||(lvl>=ELDER_LVL)) break;
314
315 /* Es steht jedoch frei, auch anderen Schreibrechte zu geben... */
316 return access_rights(strs,euid);
317
318 case DOMAINDIR:
319 /* neue Regionen duerfen nur Erzmagier anlegen */
320 if (s<2 && lvl<ARCH_LVL) return 0;
321
322 /* kein Zugriff auf Objekte mit hoeheren Rechten */
323 if (s>2 && query_wiz_level(creator_file(path)) > lvl)
324 return 0;
325
326 /* Auf Regionfiles von erzmagier haben nur EMs Zugriff */
327 if (creator_file(path)=="erzmagier" && lvl<ARCH_LVL) return 0;
328
329 /* innerhalb der Region haben RMs und Weise volle Schreibrechte */
330 if (lvl>=ELDER_LVL || domain_master(euid,strs[1])) break;
331
332 /* neue Verzeichnisse in der Region kann nur RM+ anlegen */
333 if (s<=3 && (fun=="mkdir" || fun=="rmdir")) return 0;
334
335 /* Magier auf ihre eigenen Files... */
336 if (s>2 && strs[2]==euid) break;
337
338 /* Files der Magier in der Region in ihre eigenen Verzeichnisse... */
339 if (s>2 && euid==sprintf("d.%s.%s", strs[1], strs[2])) break;
340
341 /* Files mit Regionsuid */
342 if (euid==strs[1]) break;
343
344 /* Es ist moeglich anderen Magiern Rechte bei sich einzuraeumen. */
345 if (access_rights(strs,euid)>0) break;
346
347 /* Auf das Verzeichniss 'alle' haben alle Regionsmitglieder Zugriff.
348 Ausser, wenn sie ueber access_rights.c explizit ausgeschlossen
349 werden (Returncode < 0). */
350 if (s>2 && strs[2]=="alle" && domain_member(euid, strs[1]) &&
351 access_rights(strs,euid)>=0) break;
352 return 0;
353
354 case PROJECTDIR:
355 /* Nur Erzmagier duerfen neue Projektverzeichnisse anlegen... */
356 if (s<3 && lvl<ARCH_LVL) return 0;
357
358 /* alles weitere duerfen auch Weise tun */
359 if (lvl>=ELDER_LVL) break;
360
361 /* in den Serviceverzeichnissen muss lediglich der Name stimmen */
362 if (s>3 && strs[1]=="service" && euid==strs[2]) break;
363
364 /* Objekte eines Projektes haben Schreibzugriffe auf ihr Projekt */
365 if (s>3 && (implode(strs[0..1], ".") == euid
366 || implode(strs[0..2], ".") == euid) ) return 1;
367
368 /* Schreibrechte koennen natuerlich auch vergeben werden... */
369 if (project_access(euid,strs[1])) break;
370 // Alternativ besteht neben dem ACCESS_RIGHTS auch noch die
371 // Moeglichkeit, per access_rights.c Rechte einzuraeumen.
372 if (access_rights(strs,euid)>0) break;
373
374 return 0;
375
376 default: return 0;
377 }
378 return path;
379}
380
381mixed valid_read(string path, string euid, string fun, object obj)
382{
383 int s, lev;
384 string *strs, suf;
385
386 if (member(path,' ')!=-1) return 0;
387
388 // Unter LIBDATADIR (/data) sollen komplett identische Leserechte
389 // vergeben werden.
390 if (sizeof(path) > 6
391 && path[0..5] == "/"LIBDATADIR"/")
392 return valid_read(path[5..], euid, fun, obj) != 0;
393
394 if (!euid) euid="-";
395
Zesstraccc58df2018-11-07 23:25:20 +0100396 strs=path_array(path);
Zesstraa43be352018-11-06 22:40:32 +0100397 // Pfade sind ab jetzt auf jeden Fall absolut.
398 path=implode(strs, "/");
MG Mud User88f12472016-06-24 23:31:02 +0200399
400 // fuer die Rechtebestimmung "/" an Anfang und Ende entfernen
401 strs -= ({""});
402
403 if (!sizeof(strs) || !sizeof(path) || euid == ROOTID || obj==TO) return path;
404
405 if ((s=sizeof(strs)) <= 1) return path;
406
407 lev=query_wiz_level(euid);
408
409 switch(strs[0]) {
410 case "core":
411 case "wahl":
412 return 0;
413
414 case NEWSDIR:
415 if (strs[1] == "archiv.pub") // oeffentliches archiv
416 return path;
417 else if (strs[1] == "archiv.magier" // Magier-Archiv
418 && lev >= WIZARD_LVL)
419 return path;
420
421 return 0; // kein Zugriff auf /news/ oder alles andere.
422
423 case "maps":
424 if (lev<=WIZARD_LVL) return 0;
425
426 case "":
427 case ETCDIR:
428 case STDDIR:
429 case SYSDIR:
430 case DOCDIR:
431 case LIBOBJDIR:
432 case LIBROOMDIR:
433 case LIBITEMDIR:
434 case FTPDIR:
435 return path;
436
437 case MAILDIR:
438 return (euid==MAILID);
439
440 case SECUREDIR:
441 if (strs[1]=="save") return 0;
442 if (path[<2..]==".o" || path[<5..]==".dump") return 0;
443 if (strs[1]!="ARCH" || lev>=ARCH_LVL) return path;
444
445 case LIBLOGDIR:
446 if ( strs[1] == "ARCH" && !IS_DEPUTY(euid) )
447 return 0;
448
449 if ( strs[1] == "ARCH" && lev < ARCH_LVL && s == 3 &&
450 strs[2] != "*" && strs[2][0..2] != "bb." &&
451 member( deputy_files, strs[2] ) < 0 )
452 return 0;
453
454 if ( lev > WIZARD_LVL )
455 return path;
456
457 if ( s == 2 && (strs[1] == "report" || strs[1] == "error") )
458 return path; // fuer 'cd'
459
460 // /log sollte jeder auflisten koennen
461 if ( s == 2 && strs[1]=="*" && fun=="get_dir")
462 return path;
463
464 // unter /log/report/, /log/error und /log/warning/ duerfen alle lesen
465 if ( s==3 &&
466 (strs[1] == "report" || strs[1] == "error"
467 || strs[1] =="warning"))
468 return path;
469
470 // /log/<Magiername> darf von <Magiername> natuerlich auch
471 // gelesen werden
472 if ( s >= 2 && strs[1] == euid )
473 return path;
474
475 return 0;
476
477 case "backup":
Zesstra8a3f8682017-01-30 23:04:20 +0100478 case "save":
MG Mud User88f12472016-06-24 23:31:02 +0200479 if (lev>WIZARD_LVL) return path;
480
481 /* Objekte in /p/* haben bisher leider wizlevel 0 */
482 //if (lev==0) return path;
483
484 if (fun=="file_size") return path;
485
486 // das eigene Savefile darf man natuerlich immer. ;-)
487 if (s==3 && (strs[2]==euid+".o" || strs[2]==euid))
488 return path;
489 return 0;
490
491 case PROJECTDIR:
492 /* Pruefen ob ein File existiert darf jeder... */
493 if (fun=="file_size") return path;
494
495 /* Die Service-Verzeichnisse darf jeder lesen */
496 if (s>3 && strs[1]=="service") return path;
497
498 //Weise duerfen in /p/ schreiben, also auch lesen. (Zesstra, 04.11.06)
499 if (lev>=ELDER_LVL) return path;
500
501 /* wer hier schreiben darf, darf natuerlich auf jeden Fall lesen */
502 //Anmerkung v. Zesstra: das prueft nur, ob jemand in ACCESS_RIGHTS
503 //steht, nicht ob jemand (ggf. aus anderen Gruenden schreiben darf)
504 if (project_access(euid,strs[1])) return path;
505 //Alternativ kann man explizite Schreibrechte auch via access_rights.c
506 //vergeben. (und damit natuerlich auch Leserechte)
507 if (access_rights(strs,euid)>0) return path;
508
509 /* Objekte eines Projektes haben Lesezugriff auf ihr Projekt */
510 if (s>3 && (implode(strs[0..1], ".") == euid
511 || implode(strs[0..2], ".") == euid) ) return path;
512
513 /* Fall-Through */
514
515 case GUILDDIR:
516 /* "secure"-Verzeichnisse darf nur lesen, wer da auch schreiben darf */
517 if ( s > 3 && strs[<2] == "secure" && member( insecure, strs[1] ) < 0
518 && lev < ARCH_LVL && !access_rights(strs, euid) )
519 return 0;
520
521 /* Pruefen ob ein File existiert darf jeder... */
522 if (fun=="file_size") return path;
523
524 /* Fall-Through */
525
526 case SPELLBOOKDIR:
527 // Gildenpbjekte koennen hier lesen
528 if (lev==0 && euid[0..4]=="GUILD") return path;
529
530 // Mit Level <= 20 darf man hier nichts lesen
531 if ( lev<=WIZARD_LVL && sizeof(regexp( ({strs[<1]}), "\\.[och]" )) )
532 return 0;
533
534 return path;
535
536 case WIZARDDIR:
537 if (s==2) return path;
538 /* das eigene Verzeichniss darf man natuerlich immer lesen... */
539 if (strs[1]==euid && lev>=WIZARD_LVL) return path;
540
541 /* Pruefen ob ein File existiert darf jeder... */
542 if (fun=="file_size") return path;
543
544 /* fremde Verzeichnisse mit <= Level 20 noch nicht */
545 if (lev<=WIZARD_LVL) return 0;
546
547 /* wo man schreiben darf, darf man natuerlich auch lesen... */
548 if (lev>=ELDER_LVL) return path;
549
550 // kein Zugriff auf archivierten Code (wo z.B. secure/ drin sein
551 // koennen)
552 if (member(({"bz2","gz","zip"}), explode(strs[<1],".")[<1]) > -1)
553 return 0;
554
555 /* Files ohne Code sind nicht weiter interessant... */
556 if ( !sizeof(regexp( ({strs[<1]}), "\\.[och]" )) )
557 return path;
558
559 /* folgende Funktionen sind natuerlich voellig uninteressant */
560 if (member(({"get_dir", "restore_object"}), fun)!=-1)
561 return path;
562
563 /* Zugriff erlaubt, aber mitloggen */
564 write_file( READ_FILE, sprintf("%O %s %s: %s\n", fun, ctime()[4..],
565 euid, path) );
566 return path;
567
568 case DOMAINDIR:
569 /* Mit Level 15 darf man hier _nichts_ lesen */
570 if ( fun!="file_size" && lev<WIZARD_LVL &&
571 sizeof(regexp( ({strs[<1]}), "\\.[och]" )) ) return 0;
572
573 /* den Verzeichnisbaum von /d/ darf man natuerlich sonst lesen */
574 if (s<=2) return path;
575
576 /* eigenen Code darf man natuerlich auch lesen */
577 if (euid==strs[2] || euid==sprintf("d.%s.%s", strs[1], strs[2]))
578 return path;
579
580 /* Deputies haben ein gemeinsames Verzeichnis unter /d/erzmagier */
581 if (strs[1]=="erzmagier" && strs[2]=="polizei" && IS_DEPUTY(euid))
582 return path;
583
584 /* d/erzmagier darf man nur als Erzmagier lesen */
585 if (strs[1]=="erzmagier" && lev<ARCH_LVL) return 0;
586
587 /* einige Regionen haben std-verzeichnisse, die darf man natuerlich
588 auch mit Level 20 bereits komplett lesen! */
589 if (strs[2]=="std") return path;
590
591 /* "secure"-Verzeichnisse darf nur lesen, wer da auch schreiben darf */
592 if ( s > 4 && strs[<2] == "secure" && member( insecure, strs[2] ) < 0 ){
593 if ( lev < ELDER_LVL && !domain_master(euid, strs[1])
594 && !access_rights(strs, euid) )
595 return 0;
596 else
597 return path;
598 }
599
600 /* Dokus, Infos und .readme darf man immer lesen... */
601 if ( fun=="file_size" || !sizeof(regexp( ({strs[<1]}), "\\.[och]" )) )
602 return path;
603
604 /* Mit Level 20 darf man noch keinen fremden Code lesen! */
605 if (lev<=WIZARD_LVL) return 0;
606
607 /* Weise duerfen natuerlich alles weitere lesen */
608 if (lev>=ELDER_LVL) return path;
609
610 /* Regionsmagier in ihren Regionen natuerlich auch */
611 if (lev>=LORD_LVL && domain_master(euid, strs[1])) return path;
612
613 /* folgende Funktionen sind natuerlich voellig uninteressant */
614 if (member(({"get_dir", "restore_object"}), fun)!=-1)
615 return path;
616
617 /* Zugriff erlaubt, aber mitloggen */
618 write_file( READ_FILE, sprintf("%O %s %s: %s\n", fun, ctime()[4..],
619 euid, path) );
620 return path;
621 }
622 if (lev<ARCH_LVL) return 0;
623 return path;
624}
625