blob: 8cdbb8c133a9dec1024cb0dd9927bb886a9a8615 [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001// MorgenGrauen MUDlib
2//
3// master/misc.c -- Diverses: (T)Banish, Projektverwaltung, Levelaufstieg, ...
4//
5// $Id: misc.c 9467 2016-02-19 19:48:24Z Zesstra $
6
7#pragma strict_types,rtt_checks
8
9#include "/sys/functionlist.h"
10#include "/sys/lpctypes.h"
11#include "/sys/object_info.h"
12#include "/sys/interactive_info.h"
Bugfix05c09d72017-02-14 21:26:20 +010013#include "/sys/files.h"
MG Mud User88f12472016-06-24 23:31:02 +020014
15#include "/secure/master.h"
16#include "/mail/post.h"
17#include "/sys/thing/language.h"
18#include "/sys/thing/description.h"
Zesstra86607bb2017-06-17 19:02:40 +020019#include "/sys/configuration.h"
MG Mud User88f12472016-06-24 23:31:02 +020020
21// Fuer CIDR-Notatio im sbanish
22#include "/secure/master/cidr.c"
23
24static mixed *banished;
25static mapping tbanished, sbanished;
26static string *deputies;
27
28// TODO: muss ggf. Fakeobjekt erzeugen+uebergeben, wenn sender kein object
29protected void send_channel_msg(string channel,mixed sendername,string msg)
30{
31 object sender;
32 if (objectp(sendername))
33 sender=sendername;
34 else
35 {
36 // wenn kein Objekt uebergeben, erstmal schauen, ob ein Spielerobject
37 // existiert... Wenn ja, das nehmen.
38 sender = call_sefun("find_player", sendername)
39 || call_sefun("find_netdead", sendername);
40 if (!objectp(sender))
41 {
42 // sonst faken wir eins. *seufz*
43 sender=clone_object("/p/daemon/namefake");
44 sender->SetProp(P_NAME, sendername);
45 sender->SetProp(P_ARTICLE,0);
46 // Dieses Objekt zerstoert sich nach 3s automatisch.
47 }
48 }
49 CHMASTER->send(channel, sender, msg);
50}
51
52static string *explode_files(string file) {
53 string data;
54 mixed *exploded;
55 int i;
56
57 data=read_file(file);
58 if (!data || !stringp(data) || data == "") return ({});
59 exploded = efun::explode(data,"\n");
60 for (i=sizeof(exploded);i--;)
61 if (!stringp(exploded[i]) || exploded[i]=="" || exploded[i][0]=='#')
62 exploded[i]=0;
63 exploded-=({0});
64 printf("%-30s: %3d Objekt%s\n",file,i=sizeof(exploded),(i==1?"":"e"));
65 return exploded;
66}
67
68void UpdateTBanish();
69
70mixed QueryBanished(string str){
71 int i;
72
73 if (!str) return 0;
74 if (!pointerp(banished)) return 0;
75 for (i=sizeof(banished)-1;i>=0;i--)
76 if (sizeof(regexp(({str}),"^"+banished[i][0]+"$")))
77 {
78 if (!banished[i][1] || banished[i][1]=="")
79 return "Dieser Name ist gesperrt.";
80 else
81 return banished[i][1];
82 }
83 return 0;
84}
85
86mixed QueryTBanished(string str) {
87 int i;
88
89 if (!str || !mappingp(tbanished) || !(i=tbanished[str]))
90 return 0;
91
92 if (i == -1 || i > time())
93 return sprintf("Es gibt schon einen Spieler diesen Namens.\n"
94 +"Allerdings kann er/sie erst am %s wieder ins Mud kommen.\n",
95 (i == -1 ? "St. Nimmerleinstag" :
96 call_sefun("dtime",i)[0..16]));
97
98// Ansonsten: die Zeit ist abgelaufen, Spieler darf wieder...
99 m_delete(tbanished, str);
100 UpdateTBanish();
101 return 0;
102}
103
104void ReloadBanishFile(){
105 int i, t;
106 string s1, s2, *s;
107
108 banished = efun::explode( read_file("/secure/BANISH") || "", "\n" );
109 banished = banished - ({""});
110 for ( i = sizeof(banished); i--; ){
111 s = efun::explode( banished[i], " " );
112 s1 = s[0];
113 s2 = implode( s[1..], " " );
114 banished[i] = ({ s1, s2 });
115 }
116
117 if ( !mappingp(tbanished) ){
118 tbanished = ([]);
119
120 s = efun::explode( read_file("/secure/TBANISH") || "", "\n" );
121 s -= ({""});
122
123 for ( i = sizeof(s); i--; ){
124 sscanf( s[i], "%s:%d", s1, t );
125 tbanished += ([ s1 : t ]);
126 }
127 }
128
129 if ( !mappingp(sbanished) ){
130 sbanished = m_allocate(3, 2);
131
132 s = efun::explode( read_file("/secure/SITEBANISH") || "", "\n" );
133 s -= ({""});
134
135 for ( i = sizeof(s); i--; ) {
136 int int_ip;
137 sscanf( s[i], "%s:%d:%s", s1, t, s2 );
138 int_ip = IPv4_addr2int(s1);
139 m_add(sbanished, int_ip, t, s2);
140 }
141 }
142}
143
144int IsDeputy(mixed name)
145{
146 if ( IS_ARCH(name) )
147 return 1;
148
149 if ( objectp(name) )
150 name = getuid(name);
151
152 if ( member( deputies || ({}), name ) >= 0 )
153 return 1;
154
155 return 0;
156}
157
158
159varargs void BanishName( string name, string reason, int force )
160{
161 string *names;
162 int i;
163
164 if ( PO != TO && call_sefun("secure_level") < LORD_LVL
165 && !IsDeputy( call_sefun("secure_euid") ) )
166 return;
167
168 if ( !stringp(name) || !sizeof(name) )
169 return;
170
171 name = lower_case(name);
172
173 if ( !reason || !stringp(reason) )
174 reason = "";
175
176 if ( QueryBanished(name) && lower_case(reason) != "loeschen" ){
177 write("Der Name ist schon gebannt.\n");
178 return;
179 }
180
Zesstra85576452017-01-30 15:43:21 +0100181 if ( !force && find_userinfo(name))
182 {
MG Mud User88f12472016-06-24 23:31:02 +0200183 write("Es existiert bereits ein Spieler dieses Namens.\n");
184 return;
185 }
186
187/* if (!("/secure/login"->valid_name(name))) return;*/
188 if ( lower_case(reason) != "loeschen" ){
189 names = ({ name + " " + reason });
190
191 for ( i = sizeof(banished); i--; )
192 names += ({ banished[i][0] + " " + banished[i][1] });
193 }
194 else{
195 names = ({});
196
197 for ( i = sizeof(banished); i--; )
198 if ( banished[i][0] != name )
199 names += ({ banished[i][0] + " " + banished[i][1] });
200 }
201
202 names = sort_array( names, #'> );
203 rm("/secure/BANISH");
204 write_file( "/secure/BANISH", implode(names, "\n") );
205 write( "Okay, '"+capitalize(name)+"' ist jetzt "+
206 (lower_case(reason) == "loeschen" ? "nicht mehr " : "")+"gebanisht.\n" );
207 ReloadBanishFile();
208}
209
210void UpdateTBanish()
211{
212 int i;
213 string *names;
214
215 for (i=sizeof(names = sort_array(m_indices(tbanished), #'</*'*/))-1;i>=0;i--)
216 names[i] = sprintf("%s:%d", names[i], tbanished[names[i]]);
217
218 rm("/secure/TBANISH");
219 write_file("/secure/TBANISH", implode(names, "\n"));
220}
221
222void UpdateSBanish()
223{
224 int i;
225 mapping lines = m_allocate(sizeof(sbanished),0);
226
227 foreach(int ip, int tstamp, string user : sbanished) {
228 m_add(lines, sprintf("%s:%d:%s",
229 IPv4_int2addr(ip), tstamp, user));
230 }
231
232 write_file( "/secure/SITEBANISH",
233 implode( sort_array (m_indices(lines), #'<), "\n" ), 1);
234}
235
236int TBanishName(string name, int days)
237{
238 int t;
239
240 if ( (getuid(TI) != name) &&
241 !IsDeputy( call_sefun("secure_euid") ) )
242 return 0;
243
244 if (days && QueryTBanished(name)){
245 write("Der Name ist schon gebannt.\n");
246 return 0;
247 }
248
Zesstra85576452017-01-30 15:43:21 +0100249 if (!find_userinfo(name))
250 {
MG Mud User88f12472016-06-24 23:31:02 +0200251 write("Es existiert kein Spieler dieses Namens!\n");
252 return 0;
253 }
254
255 if (!days && member(tbanished, name))
256 m_delete(tbanished, name);
257 else {
258 if (!mappingp(tbanished))
259 tbanished = ([]);
260 if (days <= -1)
261 t = -1;
262 else
263 t = (time()/86400)*86400 + days*86400;
264 tbanished += ([ name : t ]);
265 }
266
267 UpdateTBanish();
268 return 1;
269}
270
271
272mixed QuerySBanished( string ip )
273{
274 int save_me, site;
275 string banished_meldung =
276 "\nSorry, von Deiner Adresse kamen ein paar Idioten, die "
277 "ausschliesslich\nAerger machen wollten. Deshalb haben wir "
278 "die Moeglichkeit,\neinfach neue Charaktere "
279 "anzulegen, kurzzeitig fuer diese Adresse gesperrt.\n\n"
280 "Falls Du bei uns spielen moechtest, schicke bitte eine Email "
281 "an\n\n mud@mg.mud.de\n\n"
282 "mit der Bitte, einen Charakter fuer Dich anzulegen.\n" ;
283
284 if ( !ip || !stringp(ip) || !mappingp(sbanished) || !sizeof(sbanished) )
285 return 0;
286
287 foreach(site, int tstamp: sbanished) {
288 if ( tstamp > 0 && tstamp < time() ) {
289 m_delete( sbanished, site );
290 save_me=1;
291 }
292 }
293 if (save_me)
294 UpdateSBanish();
295
296 if ( !sizeof(sbanished) )
297 return 0;
298
299 site = IPv4_addr2int(ip);
300 if (!site)
301 return 0;
302 // direkt drin?
303 if (member(sbanished, site))
304 return banished_meldung;
305 // oder Netz dieser IP gesperrt?
306 foreach(int locked_site : sbanished) {
307 if ((locked_site & site) == locked_site)
308 return banished_meldung;
309 }
310
311 return 0;
312}
313
314
315private int _sbanished_by( int key, string name )
316{
317 return sbanished[key, 1] == name;
318}
319
320
321mixed SiteBanish( string ip, int days )
322{
323 string *s, tmp, euid;
324 int t, level;
325
326 euid = call_sefun("secure_euid");
327 level = call_sefun("secure_level");
328
329 // Unter L26 gibt's gar nix.
330 if ( level <= DOMAINMEMBER_LVL )
331 return -1;
332
333 // Die Liste der gesperrten IPs anschauen darf jeder ab L26.
334 if ( !ip && !days )
335 return copy(sbanished);
336
337
338 if ( !stringp(ip) || !intp(days) )
339 return 0;
340
341 if ( days && QuerySBanished(ip) ){
342 write( "Diese Adresse ist schon gebannt.\n" );
343 return 0;
344 }
345
346 if ( !days ) {
347 int int_ip = IPv4_addr2int(ip);
348
349 if( member(sbanished, int_ip) ){
350 // Fremde Sitebanishs duerfen nur Deputies loeschen.
351 if ( sbanished[int_ip, 1] != euid && !IsDeputy(euid) )
352 return -1;
353
354 call_sefun("log_file", "ARCH/SBANISH",
355 sprintf( "%s: %s hebt die Sperrung der Adresse %s von %s "
356 + "auf.\n",
357 ctime(time()), capitalize(euid), ip,
358 capitalize(sbanished[int_ip, 1]) ) );
359
360 m_delete( sbanished, int_ip );
361 }
362 else
363 return 0;
364 }
365 else {
366 // Alles, was nicht Deputy ist, darf nur fuer einen Tag sbanishen.
367 if ( days != 1 && !IsDeputy(euid) )
368 return -1;
369
370 // Nur Deputies duerfen mehr als 10 Sperrungen vornehmen.
371 if ( sizeof(filter_indices(sbanished, #'_sbanished_by, euid)) >= 10
372 && !IsDeputy(euid) )
373 return -2;
374
375 int int_ip = IPv4_addr2int(ip);
376
377 if(!int_ip) {
378 write( "Ungueltige Adresse!\n" );
379 return 0;
380 }
381
382 // L26 duerfen exakt eine IP sperren, RMs ganze Class C-Subnetze
383 // und Deputies auch Class B-Subnetze.
384 int nsize=IPv4_net_size(ip);
385 if ( nsize > 1 && level < LORD_LVL
386 || nsize > 255 && !IsDeputy(euid) )
387 return -1;
388
389 if ( !mappingp(sbanished) )
390 sbanished = m_allocate(1, 2);
391
392 if ( days < 0 )
393 t = -1;
394 else
395 t = (time() / 86400) * 86400 + days * 86400;
396
397 m_add(sbanished, int_ip, t, euid);
398
399 call_sefun("log_file", "ARCH/SBANISH",
400 sprintf( "%s: %s sperrt die Adresse %s %s.\n",
401 ctime(time()), capitalize(euid),
402 ip,
403 days > 0 ? (days > 1 ? "fuer " + days + " Tage"
404 : "fuer einen Tag")
405 : "bis zum St. Nimmerleinstag" ) );
406 }
407
408 UpdateSBanish();
409 return 1;
410}
411
412static void CheckDeputyRights()
413{
414 object ob;
415 mixed *ginfo;
416
417 // Lese- und Schreibberechtigungen fuer die Rubrik 'polizei' setzen
418 call_other( "/secure/news", "???" );
419 ob = find_object("secure/news");
420 ginfo = ((mixed)ob->GetGroup("polizei"))[5..6];
421 ob->RemoveAllowed( "polizei", 0, ginfo[0], ginfo[1] );
422 ob->AddAllowed( "polizei", 0, deputies, deputies );
423 LoadDeputyFileList();
424}
425
426int ReloadDeputyFile()
427{
428 deputies = efun::explode( read_file("/secure/DEPUTIES") || "", "\n" );
429 deputies -= ({""});
430 deputies = map( deputies, #'lower_case/*'*/ );
431 call_out( "CheckDeputyRights", 2 );
432 return(1);
433}
434
435
436static int create_home(string owner, int level)
437{
438 string def_castle;
439 string dest, castle, wizard;
440 object player;
441 string *domains;
442 int i;
443
444 player = call_sefun("find_player",owner);
445 if (!player)
446 return -5;
447 domains=get_domain_homes(owner);
448 if (!sizeof(domains) && level >= DOMAINMEMBER_LVL)
449 {
450 tell_object(player,"Du gehoerst noch keiner Region an !\n");
451 return -6;
452 }
453 tell_object(player,"Du bist Mitarbeiter der folgenden Regionen:\n");
454 for (i=0;i<sizeof(domains);i++)
455 {
456 if (i) tell_object(player,", ");
457 tell_object(player,domains[i]);
458 }
459 tell_object(player,".\n");
460 update_wiz_level(owner, level);
461 wizard = "/players/" + owner;
462 castle = "/players/" + owner + "/workroom.c";
463 if (file_size(wizard) == -1) {
464 tell_object(player, "Verzeichnis " + wizard + " angelegt\n");
465 mkdir(wizard);
466 }
467 dest = object_name(environment(player));
468 def_castle = read_file("/std/def_workroom.c");
469 if (file_size(castle) > 0) {
470 tell_object(player, "Du HATTEST ja schon ein Arbeitszimmer !\n");
471 } else {
472 if (write_file(castle, def_castle))
473 {
474 tell_object(player, "Arbeitszimmer " + castle + " erzeugt.\n");
475 // Arbeitszimmer als Home setzen
476 player->SetProp(P_START_HOME,castle[0..<3]);
477 }
478 else
479 tell_object(player, "Arbeitszimmer konnte nicht erzeugt werden !\n");
480 }
481 return 1;
482}
483
484// Sendet dem befoerderten Magier eine Hilfemail zu.
485protected void SendWizardHelpMail(string name, int level) {
486
487 object pl=call_sefun("find_player",name);
488 if (!objectp(pl)) return;
489
490 string file=sprintf("%sinfo_ml%d", WIZ_HELP_MAIL_DIR, level);
491 // wenn kein Hilfetext fuer den Level da ist: raus
492 if (file_size(file) <= 0)
493 return;
494
495 string subject = read_file(file,1,1);
496 string text = call_sefun("replace_personal",
497 read_file(file,2), ({pl}));
498
499 mixed mail = ({"Merlin", "<Master>", name, 0, 0, subject,
500 call_sefun("dtime",time()),
501 MUDNAME+time(), text });
502 MAILDEMON->DeliverMail(mail, 0);
503}
504
505int allowed_advance_wizlevel(mixed ob)
506{
507 string what;
508
509 if (objectp(ob) && geteuid(ob)==ROOTID) return 1;
510
511 if (!stringp(ob))
512 what=efun::explode(object_name(ob),"#")[0];
513 else
514 what=ob;
515
516 if (what=="/secure/merlin") return 1;
517
518 return 0;
519}
520
521int advance_wizlevel(string name, int level)
522{
523 int answer;
524 mixed *user;
525
526 if (!allowed_advance_wizlevel(PO))
527 return -1;
528
529 if (level>80) return -2;
530
531 if (!find_userinfo(name)) return -3;
532
533 user=get_full_userinfo(name);
534
535 if (user[USER_LEVEL+1]>level) return -4;
536
537 if (user[USER_LEVEL+1]==level) return 1;
538
539 if (level>=10 && level<20)
540 {
541 update_wiz_level(name, level);
542 SendWizardHelpMail(name, level);
543 return 1;
544 }
545 if (level>=20 && user[USER_LEVEL+1]<21)
546 {
547 answer = create_home(name, level);
548 if ( answer > 0 ) {
549 answer = update_wiz_level(name, level);
550 SendWizardHelpMail(name, level);
551 }
552 return answer;
553 }
554
555 update_wiz_level(name, level);
556 SendWizardHelpMail(name, level);
557
558 return 1;
559}
560
561void restart_heart_beat(object heart_beat)
562{
563 if (heart_beat) heart_beat->_restart_beat();
564}
565
566int renew_player_object(mixed who)
567{
568 object newob;
569 object *obs, *obs2;
570 mixed err;
571 string ob_name;
572 object *armours, weapon;
573 object tp;
574 int i,active,j;
575
576 if (stringp(who))
577 {
578 who=call_sefun("find_player",who);
579 if (!who)
580 {
581 who=call_sefun("find_netdead",who);
582 if (!who)
583 return -1;
584 }
585 }
586 if (!objectp(who))
587 return -2;
588 if (!object_info(who, OI_ONCE_INTERACTIVE))
589 return -3;
590 if (who->QueryGuest())
591 {
592 printf("Can't renew guests!\n");
593 return -6;
594 }
595 active=interactive(who);
596 printf("OK, renewing %O\n",who);
Zesstra86607bb2017-06-17 19:02:40 +0200597 efun::configure_object(this_object(), OC_EUID, geteuid(who));
MG Mud User88f12472016-06-24 23:31:02 +0200598 err=catch(newob=clone_object(query_player_object(getuid(who))); publish);
Zesstra86607bb2017-06-17 19:02:40 +0200599 efun::configure_object(this_object(), OC_EUID, getuid(TO));
MG Mud User88f12472016-06-24 23:31:02 +0200600 if (err)
601 {
602 printf("%O\n",err);
603 return -4;
604 }
605 if (!newob)
606 return -5;
607 /* Ok, the object is here now ... lets go for it ... */
608 who->save_me(0);
609 /* SSL ip weiterreichen */
610 if( call_sefun("query_ip_number", who) != efun::interactive_info(who,II_IP_NUMBER) )
611 {
612 newob->set_realip( call_sefun("query_ip_number",who) );
613 }
zesstraf06f57a2016-07-06 20:36:05 +0200614 efun::configure_object(who, OC_COMMANDS_ENABLED, 0);
MG Mud User88f12472016-06-24 23:31:02 +0200615 efun::set_this_player(0);
616 armours=(object *)who->QueryProp(P_ARMOURS);
617 weapon=(object)who->QueryProp(P_WEAPON);
618
619 if ( previous_object() && object_name(previous_object()) == "/secure/merlin" )
620 send_channel_msg("Debug",
621 previous_object(),
622 sprintf("RENEWING: %O %O\n",newob,who));
623 else
624 send_channel_msg("Entwicklung",
625 previous_object(),
626 sprintf("RENEWING: %O %O\n",newob,who));
627
628 ob_name=explode(object_name(newob),"#")[0];
629 if (sizeof(ob_name)>11 && ob_name[0..11]=="/std/shells/")
630 ob_name=ob_name[11..];
631 ob_name=ob_name+":"+getuid((object)who);
632 if (active)
633 exec(newob,who);
634 if (active && (interactive(who)||!interactive(newob)))
635 {
636 send_channel_msg("Debug",previous_object(),
637 "ERROR: still active !\n");
638 newob->remove();
639 return 0;
640 }
641// newob->start_player(capitalize(getuid(who)),who->_query_my_ip());
642 funcall(
643 bind_lambda(
644 unbound_lambda( ({'x, 'y}),
645 ({#'call_other/*'*/,
646 newob,
647 "start_player",
648 'x, 'y
649 })
650 ), who
651 ),
652 capitalize(getuid(who)), who->_query_my_ip() );
653
654 newob->move(environment(who),M_TPORT|M_NOCHECK|M_NO_SHOW|M_SILENT
655 |M_NO_ATTACK);
656 obs=all_inventory(who);
657 foreach(object tob: all_inventory(who)) {
658 if (!tob->QueryProp(P_AUTOLOADOBJ))
659 {
660 // kein Autoloader...
661 foreach(object ob: deep_inventory(tob))
662 {
663 // aber enthaltene Autoloader entsorgen...
664 if (ob->QueryProp(P_AUTOLOADOBJ))
665 {
666 catch(ob->remove();publish);
667 if (ob) destruct(ob);
668 }
669 }
670 // objekt ohne die AL bewegen.
671 catch(tob->move(newob,M_NOCHECK);publish);
672 }
673 else {
674 // Inhalt von Autoloadern retten.
675 // neue instanz des ALs im neuen Objekt.
676 object new_al_instance = present_clone(tob, newob);
677 foreach(object ob: deep_inventory(tob)) {
678 if (ob->QueryProp(P_AUTOLOADOBJ)) {
679 // autoloader in Autoloadern zerstoeren...
680 catch(ob->remove(1);publish);
681 if (ob) destruct(ob);
682 }
683 // alle nicht autoloader in die AL-Instanz im neuen Objekt oder
684 // notfalls ins Inv.
685 else {
686 if (objectp(new_al_instance))
687 catch(ob->move(new_al_instance, M_NOCHECK);publish);
688 else
689 catch(ob->move(newob, M_NOCHECK);publish);
690 }
691 }
692 // Autoloader zerstoeren. Wird nicht vom Spielerobjekt im remove()
693 // gemacht, wenn nicht NODROP.
694 catch(tob->remove(1);publish);
695 if (tob) destruct(tob);
696 }
697 }
698 who->remove();
699 if ( objectp(who) )
700 destruct(who);
701 rename_object(newob,ob_name);
702 newob->__reload_explore();
703 tp=this_player();
704 efun::set_this_player(newob);
705 if (objectp(weapon))
706 weapon->DoWield();
707 if (pointerp(armours))
708 for (i=sizeof(armours)-1;i>=0;i--)
709 if (objectp(armours[i]))
710 armours[i]->do_wear("alles");
711 efun::set_this_player(tp);
712 //Rueckgabewert noetig, weil Funktion vom Typ 'int'
713 return(1);
714}
715
716mixed __query_variable(object ob, string var)
717{
718 if (!PO || !IS_ARCH(geteuid(PO)) || !this_interactive() ||
719 !IS_ARCH(this_interactive()) || getuid(ob)==ROOTID )
720 {
721 write("Du bist kein EM oder Gott!\n");
722 return 0;
723 }
724 if (efun::object_info(ob, OI_ONCE_INTERACTIVE) && (PO!=ob) &&
725 (var=="history" || var=="hist2"))
726 send_channel_msg("Snoop", previous_object(),
727 sprintf("%s -> %s (history).",
728 capitalize(getuid(PO)),capitalize(getuid(ob))));
729
730 call_sefun("log_file", "ARCH/QV",
731 sprintf("%s: %O inquires var %s in %O\n",
732 ctime(time()),this_interactive(),var,ob) );
733 mixed res = variable_list(ob, RETURN_FUNCTION_NAME|RETURN_FUNCTION_FLAGS|
734 RETURN_FUNCTION_TYPE|RETURN_VARIABLE_VALUE);
735 int index = member(res,var);
736 if (index > -1)
737 {
738 return ({res[index],res[index+1],res[index+2],res[index+3]});
739 }
740 return 0;
741}
742
Bugfix05c09d72017-02-14 21:26:20 +0100743protected void CreateDataDirectories()
744{
745 if(file_size("/"LIBDATADIR)==FSIZE_NOFILE)
746 {
747 mkdir("/"LIBDATADIR);
748 }
749
750 if(file_size(SAVEPATH)==FSIZE_NOFILE)
751 {
752 mkdir(SAVEPATH);
753 // Die Ordner von a bis z erstellen
754 foreach(int n : 'a'..'z')
755 {
756 mkdir(sprintf(SAVEPATH+"%c",n));
757 }
758 }
759
760 if(file_size(SECURESAVEPATH)==FSIZE_NOFILE)
761 {
762 mkdir("/"LIBDATADIR"/"SECUREDIR);
763 mkdir(SECURESAVEPATH);
764 // Die Ordner von a bis z erstellen
765 foreach(int n : 'a'..'z')
766 {
767 mkdir(sprintf(SECURESAVEPATH+"%c",n));
768 }
769 }
770}