blob: 3acc9f9c329f667b8b7401b38b87e998cb8529d7 [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)
47 p_arr = p_arr[0..p-2]+p_arr[p+1..];
MG Mud User88f12472016-06-24 23:31:02 +020048
Zesstra3e9a6c92018-11-06 22:38:42 +010049 // Pfade absolutieren
50 // leeres Pfadarray fuehrt zur Rueckgabe von einem Array, was hinterher "/"
51 // ergibt, Arrays mit nur einem Element bekommen in jedem Fall ein Element
52 // "" an den Anfang, laengere Arrays kriegen falls noetig ein "".
53 switch(sizeof(p_arr))
54 {
55 case 0:
56 return ({"",""});
57 case 1:
MG Mud User88f12472016-06-24 23:31:02 +020058 p_arr = ({""}) + p_arr;
Zesstra3e9a6c92018-11-06 22:38:42 +010059 break;
60 default:
61 if (p_arr[0] != "")
62 p_arr = ({""}) + p_arr;
63 }
MG Mud User88f12472016-06-24 23:31:02 +020064
Zesstra3e9a6c92018-11-06 22:38:42 +010065 return p_arr;
66}
67
Zesstrab49624a2018-11-07 21:40:16 +010068// Pfadnormalisierung OHNE Ersetzungen von +, ~ und P_CURRENTDIR (war mal mit)
69// Eigentlich hier ziemlich unnuetz, aber nen Haufen Objekte im Mud ruft das.
Zesstra3e9a6c92018-11-06 22:38:42 +010070string _get_path(string path, string user) {
Zesstraccc58df2018-11-07 23:25:20 +010071 return implode(path_array(path),"/");
Zesstrab45f3b42018-11-07 21:54:07 +010072}
73
Zesstrab49624a2018-11-07 21:40:16 +010074// Diese Funktion wird vom Driver nur fuer den Editor ed gerufen, aber der
Zesstraccc58df2018-11-07 23:25:20 +010075// Rest vom MG ruft es teilweise auch.
Zesstrab45f3b42018-11-07 21:54:07 +010076string make_path_absolute(string path) {
Zesstraccc58df2018-11-07 23:25:20 +010077 return implode(path_array(path),"/");
MG Mud User88f12472016-06-24 23:31:02 +020078}
79
80static int project_access(string user, string project)
81{
82 mixed *lines;
83 string s;
84 mapping tmp;
85
86 if (!member(projects,project))
87 {
88 s=read_file(PROJECTDIR+"/"+project+"/ACCESS_RIGHTS");
89 if(!s||s=="")
90 return 0;
91 tmp=([]);
92 for (lines=explode(s,"\n")-({""});sizeof(lines);lines=lines[1..])
93 {
94 if (lines[0][0]=='*')
95 tmp[lines[0][1..]]=2;
96 else
97 tmp[lines[0]]=1;
98 }
99 projects[project]=({tmp,time()});
100 return tmp[user];
101 }
102 projects[project][1]=time();
103 return projects[project][0][user];
104}
105
106void OutdateProjectCache(string project)
107{
108 m_delete(projects,project);
109}
110
111static void _cleanup_projects() {
112 int i;
113 mixed *users;
114
115 for (users=m_indices(projects),i=sizeof(users)-1;i>=0;i--)
116 if((time()-projects[users[i]][1])>1800)
117 m_delete(projects,users[i]);
118}
119
120int access_rights(string *p_arr, string euid)
121{
Zesstrad872d182019-11-28 20:13:02 +0100122 int i = sizeof(p_arr) - 2;
MG Mud User88f12472016-06-24 23:31:02 +0200123
124 while ( i >= 0 &&
125 file_size( implode(p_arr[0..i], "/") + "/access_rights.c" ) < 0 )
126 i--;
127
128 if ( i < 0 )
129 return 0;
130
Zesstrad872d182019-11-28 20:13:02 +0100131 if ( !catch(i = ({int})call_other(
MG Mud User88f12472016-06-24 23:31:02 +0200132 implode(p_arr[0..i], "/") + "/access_rights",
133 "access_rights", euid,
134 implode(p_arr[i+1..], "/") ); publish) )
135 return i;
136
137 return 0;
138}
139
Zesstra078991b2013-01-26 11:56:45 +0100140// Hngl. Inkludieren aus /sys ist hier doof.
141#ifndef FSIZE_DIR
142#define FSIZE_DIR -2
143#endif
MG Mud User88f12472016-06-24 23:31:02 +0200144mixed valid_write(string path, string euid, string fun, object obj)
145{
146 int s,lvl;
147 string *strs;
148 int *date;
149
150 if (member(path,' ')!=-1) return 0;
151
152 // Unter LIBDATADIR (/data) sollen komplett identische Schreibrechte
Zesstra078991b2013-01-26 11:56:45 +0100153 // vergeben werden. Ausnahme ist jedoch fun=="mkdir": hier soll die
154 // Erstellung eines Verezeichnisses jedem erlaubt sein, wenn es das
155 // entsprechende Verzeichnis ausserhalb /data/ schon gibt.
MG Mud User88f12472016-06-24 23:31:02 +0200156 if (sizeof(path) > 6
Zesstraeb0ceb82018-02-28 21:31:07 +0100157 && path[0..5] == "/"LIBDATADIR"/")
158 {
Zesstra078991b2013-01-26 11:56:45 +0100159 if (fun=="mkdir")
Zesstraeb0ceb82018-02-28 21:31:07 +0100160 {
161 // wenn schon ausserhalb /data/ existent: erlauben
162 if (file_size(path[5..]) == FSIZE_DIR)
163 return 1;
164 // sonst fall-through und normale gucken, ob der Aufrufer ausserhalb
165 // /data/ denn duerfte.
166 }
MG Mud User88f12472016-06-24 23:31:02 +0200167 return valid_write(path[5..], euid, fun, obj) != 0;
Zesstra078991b2013-01-26 11:56:45 +0100168 }
MG Mud User88f12472016-06-24 23:31:02 +0200169
170 switch(fun) {
171 case "log_file":
Zesstraccc58df2018-11-07 23:25:20 +0100172 strs=path_array("/"+path);
MG Mud User88f12472016-06-24 23:31:02 +0200173 path = implode(strs, "/");
174 strs -= ({""}); // remove trailing and leading "/".
175 if (sizeof(strs)>1 && strs[0]=="log") return path;
176 return 0;
177 case "save_object":
Zesstraa43be352018-11-06 22:40:32 +0100178 if (!sizeof(path)) return 0;
Zesstraccc58df2018-11-07 23:25:20 +0100179 strs=path_array("/"+path);
MG Mud User88f12472016-06-24 23:31:02 +0200180 break;
181 case "ed_start":
Zesstraa43be352018-11-06 22:40:32 +0100182 if (sizeof(path))
Zesstraccc58df2018-11-07 23:25:20 +0100183 strs=path_array(path);
Zesstraa43be352018-11-06 22:40:32 +0100184 else
185 strs=({"players",euid,".err"});
MG Mud User88f12472016-06-24 23:31:02 +0200186 break;
187 default:
Zesstraccc58df2018-11-07 23:25:20 +0100188 strs=path_array(path);
MG Mud User88f12472016-06-24 23:31:02 +0200189 }
190
191 if (!euid || euid=="NOBODY" || euid=="ftp" || euid=="anonymous") return 0;
192
193 // Pfad soll ab jetzt auf jeden Fall absolut sein.
194 if (strs[0] != "")
195 path = "/" + implode(strs, "/");
196 else
197 path=implode(strs, "/");
198
199 // fuer die Rechtebestimmung "/" an Anfang und Ende entfernen
200 strs -= ({""});
201
202 //Root-Objekte und Master duerfen immer.
203 if (euid == ROOTID || obj==TO) return path;
204
205 lvl=query_wiz_level(euid);
206
207 //Toplevel: nur EM+
208 if ((s=sizeof(strs))<=1) return lvl>=ARCH_LVL;
209
210 switch(strs[0]) {
211 case TMPDIR:
212 return 1;
213
214 case STDDIR:
215 case SYSDIR:
216 case LIBOBJDIR:
217 case ETCDIR:
218 case LIBROOMDIR:
219 return lvl>=ARCH_LVL;
220
221 case LIBITEMDIR:
222 return lvl>=ELDER_LVL;
223
224 case SPELLBOOKDIR:
225 // wenn unterhalb eines unterverzeichnisses des Stils "gilde", dann ists
226 // einfach
227 if (sizeof(strs) > 2
228 && guild_master(euid, strs[1]))
229 return 1;
230
231 // sonst nur EMs bzw. access_rights.c fragen.
232 return ((lvl>=ARCH_LVL) || access_rights(strs,euid));
233
234 case GUILDDIR:
235 // wenn unterhalb eines unterverzeichnisses des Stils "filde.gilde",
236 // dann ists einfach
237 if (sizeof(strs) > 2) {
238 string *tmp = explode(strs[1],"files.");
239 if (sizeof(tmp) == 2) {
240 if (guild_master(euid, tmp[1]))
241 return 1;
242 // Objekte dort sollen auch schreiben duerfen.
243 if (euid == ("GUILD."+tmp[1]))
244 return 1;
245 }
246 }
247 // sonst nur EMs bzw. access_rights.c fragen.
248 return ((lvl>=ARCH_LVL) || access_rights(strs,euid));
249
250 case DOCDIR:
251 if ( s > 1 && (strs[1] == "balance") )
252 return ((lvl>=ARCH_LVL) || access_rights(strs,euid));
253 else
254 return ((lvl>=SPECIAL_LVL) || access_rights(strs,euid));
255
256 case FTPDIR:
257 if ( s > 1 && (strs[1] == "incoming" || strs[1] == "tmp" ||
258 s == 3 && strs[1] == "News" && strs[2] == euid+".news") )
259 return 1;
260
261 if (lvl>=ELDER_LVL)
262 return 1;
263
264 return 0;
265
266 case MAILDIR:
267 if (euid==MAILID || strs[1]=="spool") break;
268 return 0;
269
Zesstra8a3f8682017-01-30 23:04:20 +0100270 case "save":
MG Mud User88f12472016-06-24 23:31:02 +0200271 if (lvl>=ARCH_LVL) return 1;
272 if (s==3 && strs[1] == euid[0..0] &&
273 (strs[2]==euid+".o" || strs[2]==euid)) break;
274 return 0;
275
276 case LIBLOGDIR:
277 /* auf /log/ARCH/ haben wirklich nur EMs Zugriff */
278 if (strs[1]=="ARCH" && lvl<ARCH_LVL) return 0;
279
280 /* alles andere duerfen auch Weise... */
281 if (lvl>=ELDER_LVL) return 1;
282
283 /* Allgemeine logfiles in /log duerfen wirklich nur geschrieben werden */
284 if (s==2 && strs[1][0]>='A' && strs[1][0]<='Z' && fun != "write_file")
285 return 0;
286
287 /* Unterhalb von /log/syslog darf nur geschrieben werden */
288 if (s>1 && strs[1]=="syslog" && fun != "write_file")
289 return 0;
290
291 /* loggen ins eigene repfile immer erlauben */
292 if (s==3 && strs[1]=="report" &&
293 strs[2]==explode(euid, ".")[<1]+".rep") break;
294
295 /* in fremden Verzeichnissen hat niemand was zu loggen */
296 if (get_wiz_level(strs[1]) >= WIZARD_LVL &&
297 strs[1] != efun::explode(euid, ".")[<1])
298 return 0;
299 break;
300
301 case WIZARDDIR:
302 /* kein Zugriff auf Objekte mit hoeheren Rechten */
303 if (query_wiz_level(strs[1]) > lvl) return 0;
304
305 /* Magier selbst oder Weise duerfen hier schreiben */
306 if ((IS_WIZARD(euid) && euid==strs[1])||(lvl>=ELDER_LVL)) break;
307
308 /* Es steht jedoch frei, auch anderen Schreibrechte zu geben... */
309 return access_rights(strs,euid);
310
311 case DOMAINDIR:
312 /* neue Regionen duerfen nur Erzmagier anlegen */
313 if (s<2 && lvl<ARCH_LVL) return 0;
314
315 /* kein Zugriff auf Objekte mit hoeheren Rechten */
316 if (s>2 && query_wiz_level(creator_file(path)) > lvl)
317 return 0;
318
319 /* Auf Regionfiles von erzmagier haben nur EMs Zugriff */
320 if (creator_file(path)=="erzmagier" && lvl<ARCH_LVL) return 0;
321
322 /* innerhalb der Region haben RMs und Weise volle Schreibrechte */
323 if (lvl>=ELDER_LVL || domain_master(euid,strs[1])) break;
324
325 /* neue Verzeichnisse in der Region kann nur RM+ anlegen */
326 if (s<=3 && (fun=="mkdir" || fun=="rmdir")) return 0;
327
328 /* Magier auf ihre eigenen Files... */
329 if (s>2 && strs[2]==euid) break;
330
331 /* Files der Magier in der Region in ihre eigenen Verzeichnisse... */
332 if (s>2 && euid==sprintf("d.%s.%s", strs[1], strs[2])) break;
333
334 /* Files mit Regionsuid */
335 if (euid==strs[1]) break;
336
337 /* Es ist moeglich anderen Magiern Rechte bei sich einzuraeumen. */
338 if (access_rights(strs,euid)>0) break;
339
340 /* Auf das Verzeichniss 'alle' haben alle Regionsmitglieder Zugriff.
341 Ausser, wenn sie ueber access_rights.c explizit ausgeschlossen
342 werden (Returncode < 0). */
343 if (s>2 && strs[2]=="alle" && domain_member(euid, strs[1]) &&
344 access_rights(strs,euid)>=0) break;
345 return 0;
346
347 case PROJECTDIR:
348 /* Nur Erzmagier duerfen neue Projektverzeichnisse anlegen... */
349 if (s<3 && lvl<ARCH_LVL) return 0;
350
351 /* alles weitere duerfen auch Weise tun */
352 if (lvl>=ELDER_LVL) break;
353
354 /* in den Serviceverzeichnissen muss lediglich der Name stimmen */
355 if (s>3 && strs[1]=="service" && euid==strs[2]) break;
356
357 /* Objekte eines Projektes haben Schreibzugriffe auf ihr Projekt */
358 if (s>3 && (implode(strs[0..1], ".") == euid
359 || implode(strs[0..2], ".") == euid) ) return 1;
360
361 /* Schreibrechte koennen natuerlich auch vergeben werden... */
362 if (project_access(euid,strs[1])) break;
363 // Alternativ besteht neben dem ACCESS_RIGHTS auch noch die
364 // Moeglichkeit, per access_rights.c Rechte einzuraeumen.
365 if (access_rights(strs,euid)>0) break;
366
367 return 0;
368
369 default: return 0;
370 }
371 return path;
372}
373
374mixed valid_read(string path, string euid, string fun, object obj)
375{
376 int s, lev;
377 string *strs, suf;
378
379 if (member(path,' ')!=-1) return 0;
380
381 // Unter LIBDATADIR (/data) sollen komplett identische Leserechte
382 // vergeben werden.
383 if (sizeof(path) > 6
384 && path[0..5] == "/"LIBDATADIR"/")
385 return valid_read(path[5..], euid, fun, obj) != 0;
386
387 if (!euid) euid="-";
388
Zesstraccc58df2018-11-07 23:25:20 +0100389 strs=path_array(path);
Zesstraa43be352018-11-06 22:40:32 +0100390 // Pfade sind ab jetzt auf jeden Fall absolut.
391 path=implode(strs, "/");
MG Mud User88f12472016-06-24 23:31:02 +0200392
393 // fuer die Rechtebestimmung "/" an Anfang und Ende entfernen
394 strs -= ({""});
395
396 if (!sizeof(strs) || !sizeof(path) || euid == ROOTID || obj==TO) return path;
397
398 if ((s=sizeof(strs)) <= 1) return path;
399
400 lev=query_wiz_level(euid);
401
402 switch(strs[0]) {
403 case "core":
404 case "wahl":
405 return 0;
406
407 case NEWSDIR:
408 if (strs[1] == "archiv.pub") // oeffentliches archiv
409 return path;
410 else if (strs[1] == "archiv.magier" // Magier-Archiv
411 && lev >= WIZARD_LVL)
412 return path;
413
414 return 0; // kein Zugriff auf /news/ oder alles andere.
415
416 case "maps":
417 if (lev<=WIZARD_LVL) return 0;
418
419 case "":
420 case ETCDIR:
421 case STDDIR:
422 case SYSDIR:
423 case DOCDIR:
424 case LIBOBJDIR:
425 case LIBROOMDIR:
426 case LIBITEMDIR:
427 case FTPDIR:
428 return path;
429
430 case MAILDIR:
431 return (euid==MAILID);
432
433 case SECUREDIR:
434 if (strs[1]=="save") return 0;
435 if (path[<2..]==".o" || path[<5..]==".dump") return 0;
436 if (strs[1]!="ARCH" || lev>=ARCH_LVL) return path;
437
438 case LIBLOGDIR:
439 if ( strs[1] == "ARCH" && !IS_DEPUTY(euid) )
440 return 0;
441
442 if ( strs[1] == "ARCH" && lev < ARCH_LVL && s == 3 &&
443 strs[2] != "*" && strs[2][0..2] != "bb." &&
444 member( deputy_files, strs[2] ) < 0 )
445 return 0;
446
447 if ( lev > WIZARD_LVL )
448 return path;
449
450 if ( s == 2 && (strs[1] == "report" || strs[1] == "error") )
451 return path; // fuer 'cd'
452
453 // /log sollte jeder auflisten koennen
454 if ( s == 2 && strs[1]=="*" && fun=="get_dir")
455 return path;
456
457 // unter /log/report/, /log/error und /log/warning/ duerfen alle lesen
458 if ( s==3 &&
459 (strs[1] == "report" || strs[1] == "error"
460 || strs[1] =="warning"))
461 return path;
462
463 // /log/<Magiername> darf von <Magiername> natuerlich auch
464 // gelesen werden
465 if ( s >= 2 && strs[1] == euid )
466 return path;
467
468 return 0;
469
470 case "backup":
Zesstra8a3f8682017-01-30 23:04:20 +0100471 case "save":
MG Mud User88f12472016-06-24 23:31:02 +0200472 if (lev>WIZARD_LVL) return path;
473
474 /* Objekte in /p/* haben bisher leider wizlevel 0 */
475 //if (lev==0) return path;
476
477 if (fun=="file_size") return path;
478
479 // das eigene Savefile darf man natuerlich immer. ;-)
480 if (s==3 && (strs[2]==euid+".o" || strs[2]==euid))
481 return path;
482 return 0;
483
484 case PROJECTDIR:
485 /* Pruefen ob ein File existiert darf jeder... */
486 if (fun=="file_size") return path;
487
488 /* Die Service-Verzeichnisse darf jeder lesen */
489 if (s>3 && strs[1]=="service") return path;
490
491 //Weise duerfen in /p/ schreiben, also auch lesen. (Zesstra, 04.11.06)
492 if (lev>=ELDER_LVL) return path;
493
494 /* wer hier schreiben darf, darf natuerlich auf jeden Fall lesen */
495 //Anmerkung v. Zesstra: das prueft nur, ob jemand in ACCESS_RIGHTS
496 //steht, nicht ob jemand (ggf. aus anderen Gruenden schreiben darf)
497 if (project_access(euid,strs[1])) return path;
498 //Alternativ kann man explizite Schreibrechte auch via access_rights.c
499 //vergeben. (und damit natuerlich auch Leserechte)
500 if (access_rights(strs,euid)>0) return path;
501
502 /* Objekte eines Projektes haben Lesezugriff auf ihr Projekt */
503 if (s>3 && (implode(strs[0..1], ".") == euid
504 || implode(strs[0..2], ".") == euid) ) return path;
505
506 /* Fall-Through */
507
508 case GUILDDIR:
509 /* "secure"-Verzeichnisse darf nur lesen, wer da auch schreiben darf */
510 if ( s > 3 && strs[<2] == "secure" && member( insecure, strs[1] ) < 0
511 && lev < ARCH_LVL && !access_rights(strs, euid) )
512 return 0;
513
514 /* Pruefen ob ein File existiert darf jeder... */
515 if (fun=="file_size") return path;
516
517 /* Fall-Through */
518
519 case SPELLBOOKDIR:
520 // Gildenpbjekte koennen hier lesen
521 if (lev==0 && euid[0..4]=="GUILD") return path;
522
523 // Mit Level <= 20 darf man hier nichts lesen
524 if ( lev<=WIZARD_LVL && sizeof(regexp( ({strs[<1]}), "\\.[och]" )) )
525 return 0;
526
527 return path;
528
529 case WIZARDDIR:
530 if (s==2) return path;
531 /* das eigene Verzeichniss darf man natuerlich immer lesen... */
532 if (strs[1]==euid && lev>=WIZARD_LVL) return path;
533
534 /* Pruefen ob ein File existiert darf jeder... */
535 if (fun=="file_size") return path;
536
537 /* fremde Verzeichnisse mit <= Level 20 noch nicht */
538 if (lev<=WIZARD_LVL) return 0;
539
540 /* wo man schreiben darf, darf man natuerlich auch lesen... */
541 if (lev>=ELDER_LVL) return path;
542
543 // kein Zugriff auf archivierten Code (wo z.B. secure/ drin sein
544 // koennen)
545 if (member(({"bz2","gz","zip"}), explode(strs[<1],".")[<1]) > -1)
546 return 0;
547
548 /* Files ohne Code sind nicht weiter interessant... */
549 if ( !sizeof(regexp( ({strs[<1]}), "\\.[och]" )) )
550 return path;
551
552 /* folgende Funktionen sind natuerlich voellig uninteressant */
553 if (member(({"get_dir", "restore_object"}), fun)!=-1)
554 return path;
555
556 /* Zugriff erlaubt, aber mitloggen */
557 write_file( READ_FILE, sprintf("%O %s %s: %s\n", fun, ctime()[4..],
558 euid, path) );
559 return path;
560
561 case DOMAINDIR:
562 /* Mit Level 15 darf man hier _nichts_ lesen */
563 if ( fun!="file_size" && lev<WIZARD_LVL &&
564 sizeof(regexp( ({strs[<1]}), "\\.[och]" )) ) return 0;
565
566 /* den Verzeichnisbaum von /d/ darf man natuerlich sonst lesen */
567 if (s<=2) return path;
568
569 /* eigenen Code darf man natuerlich auch lesen */
570 if (euid==strs[2] || euid==sprintf("d.%s.%s", strs[1], strs[2]))
571 return path;
572
573 /* Deputies haben ein gemeinsames Verzeichnis unter /d/erzmagier */
574 if (strs[1]=="erzmagier" && strs[2]=="polizei" && IS_DEPUTY(euid))
575 return path;
576
577 /* d/erzmagier darf man nur als Erzmagier lesen */
578 if (strs[1]=="erzmagier" && lev<ARCH_LVL) return 0;
579
580 /* einige Regionen haben std-verzeichnisse, die darf man natuerlich
581 auch mit Level 20 bereits komplett lesen! */
582 if (strs[2]=="std") return path;
583
584 /* "secure"-Verzeichnisse darf nur lesen, wer da auch schreiben darf */
585 if ( s > 4 && strs[<2] == "secure" && member( insecure, strs[2] ) < 0 ){
586 if ( lev < ELDER_LVL && !domain_master(euid, strs[1])
587 && !access_rights(strs, euid) )
588 return 0;
589 else
590 return path;
591 }
592
593 /* Dokus, Infos und .readme darf man immer lesen... */
594 if ( fun=="file_size" || !sizeof(regexp( ({strs[<1]}), "\\.[och]" )) )
595 return path;
596
597 /* Mit Level 20 darf man noch keinen fremden Code lesen! */
598 if (lev<=WIZARD_LVL) return 0;
599
600 /* Weise duerfen natuerlich alles weitere lesen */
601 if (lev>=ELDER_LVL) return path;
602
603 /* Regionsmagier in ihren Regionen natuerlich auch */
604 if (lev>=LORD_LVL && domain_master(euid, strs[1])) return path;
605
606 /* folgende Funktionen sind natuerlich voellig uninteressant */
607 if (member(({"get_dir", "restore_object"}), fun)!=-1)
608 return path;
609
610 /* Zugriff erlaubt, aber mitloggen */
611 write_file( READ_FILE, sprintf("%O %s %s: %s\n", fun, ctime()[4..],
612 euid, path) );
613 return path;
614 }
615 if (lev<ARCH_LVL) return 0;
616 return path;
617}
618