blob: 5bde2b2506c65b0a589ce19c14b6aa93ba22a84f [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001// MorgenGrauen MUDlib
2//
3// player/commands.c -- alias, history and player command handling
4//
5// $Id: command.c 9576 2016-06-18 15:00:01Z Zesstra $
6#pragma strong_types
7#pragma save_types
8//#pragma range_check
9#pragma no_clone
MG Mud User88f12472016-06-24 23:31:02 +020010
11#define NEED_PROTOTYPES
12#include <player/command.h>
13#include <player/comm.h>
14#include <thing/properties.h>
15#include <living/moving.h>
16#include <player.h>
17#undef NEED_PROTOTYPES
18
19#include <properties.h>
20#include <language.h>
21#include <new_skills.h>
22#include <config.h>
23#include <defines.h>
24#include <wizlevels.h>
25#include <logging.h>
26#include <strings.h>
27
28#define CBLOG(x) log_file(SHELLLOG("DISABLECOMMANDS"),x,200000)
Zesstrafb4cc3d2019-05-06 21:16:30 +020029#define FALIASDB "/secure/zweities"
MG Mud User88f12472016-06-24 23:31:02 +020030
31#define HIST_SIZE 40
32#define EPMASTER "/secure/explorationmaster"
33
Zesstrafb4cc3d2019-05-06 21:16:30 +020034// Im Char gespeicherte Aliase
MG Mud User88f12472016-06-24 23:31:02 +020035private mapping aliases;
Zesstrafb4cc3d2019-05-06 21:16:30 +020036// Vereinigte Liste aktiver Aliase aus im Char gespeicherten und
37// Familienaliases. Wird nicht gespeichert, sondern bei Login erzeugt!
38private nosave mapping active_aliases = ([]);
39
MG Mud User88f12472016-06-24 23:31:02 +020040private string *commands;
41private int hist_size, show_processing, histmin;
42private string default_notify_fail;
43private nosave string *history, *unparsed_args, unmodified;
44private nosave int hist_now;
45private nosave object last_command_env;
46private nosave int cmds_per_time, last_chg, max_commands, *cmd_types;
47// Datenstruktur: ({Setzer, Ablaufzeit, String/Closure})
48private nosave mixed disablecommands;
49private nosave object* syntaxdb;
50
51nomask void __set_bb(int flag);
52
53static varargs int __auswerten(string str, string intern);
54varargs int SoulComm(string str, string _verb);
55varargs mixed More(string str, int fflag, string returnto);
MG Mud User88f12472016-06-24 23:31:02 +020056static void reallocate_histbuf();
57
58private void AddHistory(string str)
59{
60 if (!stringp(str) || str=="" || str[0]=='&' || str[0]=='^' ||
61 str=="hist")
62 return;
63 if (!hist_size) return;
64 if (!pointerp(history) || sizeof(history)!=hist_size)
65 reallocate_histbuf();
66 if (sizeof(str)>=histmin && history[(hist_size+hist_now-1)%hist_size]!=str)
67 history[(hist_now++)%hist_size]=str;
68}
69
70static void create()
71{
72 last_chg=0;
73 histmin=hist_now=0;
74 Set(P_LOCALCMDS,({}));
75 Set(P_LOCALCMDS,PROTECTED,F_MODE_AS);
76 Set("_syntaxdb", SECURED|SAVE, F_MODE_AS);
77
78 show_processing=1;
79 unparsed_args=({0,0,0});
80 hist_size=HIST_SIZE;
81}
82
83static int replacedisplay(string str)
84{
85 if (!str || str=="" || !sscanf(str,"%d",show_processing))
86 printf("Unzulaessige Eingabe!\n%s 0|1|2\n",query_verb());
87 printf("Ersetzungsanzeige auf Level %d.\nLevel 0: Nichts anzeigen\n"+
88 "Level 1: Nur History-Ersetzungen anzeigen\n"+
89 "Level 2: History- und Alias-Ersetzungen anzeigen\n",show_processing);
90 if (show_processing>2&&!IS_WIZARD(ME)) show_processing=2;
91 return 1;
92}
93
94static int histmin(string str)
95{
96 int len;
97
98 if (!str||!sscanf(str,"%d",len)||len<0)
99 {
100 write("Benutzung: histmin ZAHL\nLegt die Mindestlaenge fest, die eine \
101Befehlszeile haben muss, um in den\nHistory-Puffer zu gelangen. Derzeit \
102eingestellt auf "+(string)histmin+" Zeichen.\n");
103 return 1;
104 }
105 histmin=len;
106 write("Mindestlaenge auf "+(string)len+" eingestellt.\n");
107 return 1;
108}
109
110static void reallocate_histbuf()
111{
112 int i;
113
114 history=allocate(hist_size);
115 hist_now=0;
116 for (i=0;i<hist_size;i++)
117 if (!stringp(history[i]))
118 history[i]="\n\n";
119}
120
121static int histlen(string str)
122{
123 int d;
124 if (!str||!sscanf(str,"%d",d)||d<0||d>40)
125 {
126 write("Benutzung: histlen ZAHL\nZAHL muss zwischen 0 und 40 liegen.\n");
127 printf("Deine History-Buffer-Laenge liegt bei %d Befehlen.\n",hist_size);
128 return 1;
129 }
130 hist_size=d;
131 printf("Deine History-Buffer-Laenge liegt jetzt bei %d Befehlen.\n",
132 hist_size);
133 reallocate_histbuf();
134 return 1;
135}
136
Zesstra3fe70c62019-05-28 22:46:19 +0200137// Wenn keine bestimmten Aliasnamen angegeben sind, werden alle
138// Familienaliase geholt und mit den Charaliasen vereinigt.
139// Sonst werden nur bestimmte ermittelt und der Liste der aktiven
140// Aliase ersetzt/ergaenzt.
141// Wenn <verbose>, dann wird eine Meldung ausgegeben.
142private void merge_family_aliases(string *to_update, int verbose)
Zesstrafb4cc3d2019-05-06 21:16:30 +0200143{
Zesstra3fe70c62019-05-28 22:46:19 +0200144 mapping family;
145 if (!to_update)
146 {
147 // Char- und Familienaliase addieren und als neues aktives Set
148 // speichern.
149 // Die Aliase des Char haben Prioritaet und ueberdecken die der Familie.
150 family = FALIASDB->QueryFamilyAlias();
151 active_aliases = family + aliases;
152 }
153 else
154 {
155 // Die uebergebene Liste neuholen (alle davon vorhandenen) und
156 // im aktiven Set aktualisieren/eintragen.
157 family = m_allocate(sizeof(to_update));
158 foreach(string key: &to_update)
159 {
160 family += FALIASDB->QueryFamilyAlias(key);
161 }
162 active_aliases = active_aliases + family;
163 }
164 if (verbose && sizeof(family))
165 {
166 write(break_string((
167 "Es wurden folgende Familienaliase aktiviert: "
168 +CountUp(m_indices(family)) + ".\n"),75));
169 }
Zesstrafb4cc3d2019-05-06 21:16:30 +0200170}
171
MG Mud User88f12472016-06-24 23:31:02 +0200172static void initialize()
173{
Zesstrafb4cc3d2019-05-06 21:16:30 +0200174 if (!pointerp(history)||sizeof(history)!=hist_size)
175 reallocate_histbuf();
176 add_action("__auswerten","",1);
MG Mud User88f12472016-06-24 23:31:02 +0200177 max_commands = EPMASTER->QueryCommands();
178 cmd_types = EPMASTER->QueryCmdTypes() || ({});
179
180 if ( !mappingp(aliases) )
181 aliases = ([]);
182
Zesstra3fe70c62019-05-28 22:46:19 +0200183 merge_family_aliases(0,0);
Zesstrafb4cc3d2019-05-06 21:16:30 +0200184
MG Mud User88f12472016-06-24 23:31:02 +0200185 if ( !pointerp(commands) )
186 commands = ({});
187
188 if (QueryProp("_syntaxdb"))
189 syntaxdb = ({find_object("/secure/syntaxdb")});
190/* else if (QueryProp(P_TESTPLAYER))
191 {
192 SetProp("_syntaxdb", 1);
193 call_out(#'_notify, 2,
194 "\nDa Du als Testspieler markiert bist, wurde bei Dir "
195 "die Syntaxsammlung eingeschaltet. Du kannst dies "
196 "wieder ausschalten. (hilfe syntaxsammlung) "
197 "Es waere schoen, wenn Du es beim Testen von "
198 "Gebieten einschaltest.", 0);
199 }*/
200}
201
202static mixed _set_default_notify_fail(string s)
203{
204 if (stringp(s)&&s!="")
205 {
206 if (s[<1]!='\n') s+="\n";
207 return default_notify_fail=s;
208 }
209 else if (!s||s=="")
210 return (default_notify_fail=0);
211}
212
213static mixed _query_default_notify_fail()
214{
215 return default_notify_fail;
216}
217
218static int set_errormessage(string s)
219{
220 if (!(s=_unparsed_args()))
221 {
222 _set_default_notify_fail(0);
223 write("Standard-Fehlermeldung auf \"Wie bitte?\" gesetzt.\n");
224 } else
225 {
226 write(break_string(sprintf("Standard-Fehlermeldung auf %s gesetzt.\n",
227 s),78));
228 _set_default_notify_fail(s);
229 }
230 return 1;
231}
232
233void reconnect()
234{
Zesstrafb4cc3d2019-05-06 21:16:30 +0200235 if (!mappingp(aliases))
236 aliases=([]);
237
Zesstra3fe70c62019-05-28 22:46:19 +0200238 merge_family_aliases(0,0);
MG Mud User88f12472016-06-24 23:31:02 +0200239
240 if ( !pointerp(commands) )
241 commands = ({});
242
243 max_commands = EPMASTER->QueryCommands();
244 cmd_types = EPMASTER->QueryCmdTypes() || ({});
245}
246
247static int show_hist()
248{
249 int i;
250 string comm;
251
252 tell_object( ME, "Die History-Liste enthaelt folgende Kommandos:\n" );
253
254 for( i = 0; i < hist_size; i++ )
255 if ((comm=history[(hist_now+i)% hist_size])!= "\n\n")
256 tell_object( ME, " &"+(hist_now+i-hist_size)+"/-"+ (hist_size-i-1)
257 +"\t= "+comm+"\n");
258 return 1;
259}
260
Zesstrafb4cc3d2019-05-06 21:16:30 +0200261static string present_alias(<string|int>* ali)
MG Mud User88f12472016-06-24 23:31:02 +0200262{
Zesstrafb4cc3d2019-05-06 21:16:30 +0200263 int j;
264 <string|int> k;
MG Mud User88f12472016-06-24 23:31:02 +0200265 string s,s2;
266
267 for (s="",j=sizeof(ali)-1;j>=0;j--)
268 if (intp(ali[j]))
269 if ((k=ali[j])<0)
Zesstrafb4cc3d2019-05-06 21:16:30 +0200270 s="$"+(k==-1?"":(string)-k)+"*"+s;
MG Mud User88f12472016-06-24 23:31:02 +0200271 else
Zesstrafb4cc3d2019-05-06 21:16:30 +0200272 s="$"+(string)k+s;
MG Mud User88f12472016-06-24 23:31:02 +0200273 else
274 {
275 s2=implode(explode(ali[j],"\\"),"\\\\");
276 s=implode(explode(s2,"$"),"\\$")+s;
277 }
278 return s;
279}
280
281#define ALIFORMAT ({" %s\t= %s", "alias %s %s"})[display_as_aliascommand]
Zesstrafb4cc3d2019-05-06 21:16:30 +0200282#define FALIFORMAT ({" %s\t= %s", "alias -f %s %s"})[display_as_aliascommand]
MG Mud User88f12472016-06-24 23:31:02 +0200283// Ich weiss, den Variablennamen im define zu haben ist unfein, aber das
284// macht es im Code dann angenehm uebersichtlich. -HrT
285
Zesstrafb4cc3d2019-05-06 21:16:30 +0200286static int query_aliases(int display_as_aliascommand, int familymode)
MG Mud User88f12472016-06-24 23:31:02 +0200287{
Zesstrafb4cc3d2019-05-06 21:16:30 +0200288 mapping selected_aliases;
MG Mud User88f12472016-06-24 23:31:02 +0200289
Zesstrafb4cc3d2019-05-06 21:16:30 +0200290 if (familymode)
291 selected_aliases=FALIASDB->QueryFamilyAlias();
292 else
293 selected_aliases = aliases;
294
Bugfix0c5133d2019-05-28 10:38:44 +0200295 string *alis = sort_array(m_indices(selected_aliases),#'>);
Zesstrafb4cc3d2019-05-06 21:16:30 +0200296
297 if(sizeof(alis))
MG Mud User88f12472016-06-24 23:31:02 +0200298 {
Zesstrafb4cc3d2019-05-06 21:16:30 +0200299 foreach(string a : &alis)
300 a = sprintf( (familymode ? FALIFORMAT : ALIFORMAT),
301 a, present_alias(selected_aliases[a]) );
302 More("Du hast folgende "
303 + (familymode ? "Familien-" : "")
Bugfix080e3ff2019-05-28 10:06:47 +0200304 + "Aliase definiert:\n" + CountUp(alis, "\n", "\n"));
MG Mud User88f12472016-06-24 23:31:02 +0200305 }
306 else
Zesstrafb4cc3d2019-05-06 21:16:30 +0200307 write("Du hast keine "
308 +(familymode ? "Familien-" : "") + "Aliase definiert.\n");
MG Mud User88f12472016-06-24 23:31:02 +0200309 return 1;
310}
311
MG Mud User88f12472016-06-24 23:31:02 +0200312static int alias(string str)
313{
Zesstraf86ed742019-04-25 18:37:27 +0200314 // unbearbeitetes Kommando ohne Verb ermitteln (auch ohne Trim an Anfang und
315 // Ende)
Zesstrafb4cc3d2019-05-06 21:16:30 +0200316 string um;
Zesstraf86ed742019-04-25 18:37:27 +0200317 if (unmodified && unmodified!="")
MG Mud User88f12472016-06-24 23:31:02 +0200318 um=implode(old_explode(unmodified," ")[1..]," ");
Zesstraf86ed742019-04-25 18:37:27 +0200319
MG Mud User88f12472016-06-24 23:31:02 +0200320 if (um=="") um=0;
Zesstraf86ed742019-04-25 18:37:27 +0200321 if( !(str = um||_unparsed_args()) || str=="*")
Zesstrafb4cc3d2019-05-06 21:16:30 +0200322 return query_aliases(0, 0);
MG Mud User88f12472016-06-24 23:31:02 +0200323
Zesstrafb4cc3d2019-05-06 21:16:30 +0200324 // optionen auswerten bis keine mehr kommen, dabei vorne den String
325 // verkuerzen
326 int display_as_aliascommand, familymode;
Zesstraf332ded2019-04-25 18:40:02 +0200327 while(sizeof(str) >= 2 && str[0] == '-')
328 {
329 if (str[1] == 'a')
330 display_as_aliascommand = 1;
331 else if (str[1] == 'f')
332 familymode = 1;
333 else
334 break;
335 // "-? " abschneiden
336 str = trim(str[2..], TRIM_LEFT);
MG Mud User88f12472016-06-24 23:31:02 +0200337 }
Zesstraf332ded2019-04-25 18:40:02 +0200338 if (!sizeof(str) || str=="*")
Zesstrafb4cc3d2019-05-06 21:16:30 +0200339 return query_aliases(display_as_aliascommand, familymode);
MG Mud User88f12472016-06-24 23:31:02 +0200340
Zesstrafb4cc3d2019-05-06 21:16:30 +0200341 int pos=member(str,' ');
Zesstraf86ed742019-04-25 18:37:27 +0200342 if (pos < 0) // Nur 1 Arg, Alias abfragen
MG Mud User88f12472016-06-24 23:31:02 +0200343 {
Zesstrafb4cc3d2019-05-06 21:16:30 +0200344 <string|int>* tmp;
345 if (familymode)
Bugfixc487d4c2019-05-28 11:04:29 +0200346 tmp=FALIASDB->QueryFamilyAlias(str)[str];
Zesstrafb4cc3d2019-05-06 21:16:30 +0200347 else
348 tmp=aliases[str];
349
350 if (tmp) // genau eins angegebenen
351 printf((familymode ? FALIFORMAT : ALIFORMAT)
352 +"\n",str,present_alias(tmp));
Zesstraf86ed742019-04-25 18:37:27 +0200353 else if (str[<1]=='*') // * am Ende, alle ausgeben, die passend anfangen
354 {
355 str=str[0..<2];
Zesstrafb4cc3d2019-05-06 21:16:30 +0200356 mapping selected_aliases;
357 if (familymode)
358 selected_aliases=FALIASDB->QueryFamilyAlias();
359 else
360 selected_aliases = aliases;
361 string *hits=filter(m_indices(selected_aliases),
362 function int (string alname, string start)
363 { return strstr(alname, start) == 0; },
364 str);
Zesstraf86ed742019-04-25 18:37:27 +0200365 if (!sizeof(hits))
MG Mud User88f12472016-06-24 23:31:02 +0200366 {
Zesstraf86ed742019-04-25 18:37:27 +0200367 printf("Du hast kein Alias, das mit \"%s\" anfaengt.\n", str);
368 return 1;
MG Mud User88f12472016-06-24 23:31:02 +0200369 }
Zesstraf86ed742019-04-25 18:37:27 +0200370 hits=sort_array(hits, #'>);
Zesstrafb4cc3d2019-05-06 21:16:30 +0200371 foreach(string hit: &hits)
372 hit = sprintf((familymode ? FALIFORMAT : ALIFORMAT),
373 hit, present_alias(selected_aliases[hit]));
Zesstraf86ed742019-04-25 18:37:27 +0200374 More("Folgende Aliase beginnen mit \""+str+"\":\n"+implode(hits,"\n"));
375 }
376 else // Nix gefunden
MG Mud User88f12472016-06-24 23:31:02 +0200377 printf("Du hast kein Alias \"%s\" definiert.\n",str);
378 return 1;
379 }
Zesstraf86ed742019-04-25 18:37:27 +0200380
MG Mud User88f12472016-06-24 23:31:02 +0200381 if (!pos)
382 {
Zesstraf86ed742019-04-25 18:37:27 +0200383 write("Fehler: Leerzeichen am Alias-Anfang\n");
MG Mud User88f12472016-06-24 23:31:02 +0200384 return 1;
385 }
Zesstraf86ed742019-04-25 18:37:27 +0200386 // Kommandoverb alles bis zum ersten " ".
Zesstrafb4cc3d2019-05-06 21:16:30 +0200387 string commandverb=str[0..pos-1];
Zesstraf86ed742019-04-25 18:37:27 +0200388 if (commandverb=="unalias")
MG Mud User88f12472016-06-24 23:31:02 +0200389 {
390 write
391 ("Es nicht moeglich, den Befehl unalias zu ueberladen (waer dumm :))\n");
392 return 1;
393 }
Zesstraf86ed742019-04-25 18:37:27 +0200394 if (commandverb=="*")
MG Mud User88f12472016-06-24 23:31:02 +0200395 {
396 write
397 ("Es nicht moeglich, den Befehl \"*\" zu ueberladen.\n");
398 return 1;
399 }
400
Zesstrafb4cc3d2019-05-06 21:16:30 +0200401 // ab hier wird der Expansionstext in ein Array von Strings geparst. Alle
402 // Alias-Argument ($n, $* oder $n*) stehen an der jeweiligen Stelle als
403 // laufender Index im Array. Negative Zahlen stehen fuer $n*, d.h. alle
404 // Argument nach dem genannten.
405 // Bsp: ({"stecke ", 1, " in ", -2 })
406 //TODO: regexplode("teile $1 mit $2* Ich bin jetzt weg, \$ verdienen!","[$][0-9][*]{0,1}",RE_PCRE)
407 str=str[pos+1..];
408 <string|int>* tmp=({}); // Alias-Array
409 int l, num;
MG Mud User88f12472016-06-24 23:31:02 +0200410 while (l=sizeof(str)) {
Zesstrafb4cc3d2019-05-06 21:16:30 +0200411 pos=0; // Positionszaehler in str
412 int cont=1; // Statusflag fuer inneres while
413 while (cont)
414 {
415 // innere Schleife: scannt ein Argument und haengt es als Element in
416 // tmp an. Laeuft ueber den String bis Stringende oder & oder $
417 // erreicht wird, dann ist ein Argument vollstaendig und das naechste
418 // faengt an.
419 if (pos<l)
420 {
421 if(str[pos]=='\\') // escapte '\' werden zu einzelnen '\'.
422 {
MG Mud User88f12472016-06-24 23:31:02 +0200423 str=str[0..pos-1]+str[pos+1..];
424 l--;
Zesstrafb4cc3d2019-05-06 21:16:30 +0200425 }
426 else
427 {
428 if (str[pos]=='$' || str[pos]=='&') // & ist historisch...
429 { // Argument-Platzhalter gefunden
MG Mud User88f12472016-06-24 23:31:02 +0200430 cont=0;
Zesstrafb4cc3d2019-05-06 21:16:30 +0200431 if (pos>0) { // vorhergehender Textblock vollstaendig, anhaengen
MG Mud User88f12472016-06-24 23:31:02 +0200432 tmp+=({str[0..pos-1]});
433 }
434 if (pos==l-1) {
435 printf("Fehler: %c am Zeilenende\n",str[pos]);
436 return 1;
437 }
Zesstrafb4cc3d2019-05-06 21:16:30 +0200438 // $* oder $n ? Im Falle von $n landet in num der ASCII-Wert des
439 // Zeichens, von welchem der Wert von '0' abgezogen wird -> num
440 // enthaelt danach 0..9, wenn eine Ziffer angegeben wurde.
441 num=str[++pos]; // naechstes Zeichen holen
442 if (num=='*') {
443 // Argument 1 und pos muss wieder eins zurueck.
MG Mud User88f12472016-06-24 23:31:02 +0200444 num=1;
445 pos--;
446 } else {
447 num-='0';
448 }
449 if (num<0 || num>9) {
Zesstrafb4cc3d2019-05-06 21:16:30 +0200450 printf("Fehler: Nach %c muss eine Ziffer oder * folgen\n",
MG Mud User88f12472016-06-24 23:31:02 +0200451 str[pos-1]);
452 return 1;
453 }
Zesstrafb4cc3d2019-05-06 21:16:30 +0200454 // str nach Argumentkennung weiter verarbeiten.
455 str=str[pos+1..];
456 // Aber fuer den Fall $n* das naechste Zeichen auch untersuchen
457 if (sizeof(str) && str[0]=='*') {
458 str=str[1..]; // auch ueberspringen
459 num = negate(num); // Im Array negiert kodieren
MG Mud User88f12472016-06-24 23:31:02 +0200460 }
461 tmp+=({num});
462 }
463 }
Zesstrafb4cc3d2019-05-06 21:16:30 +0200464 ++pos; // naechstes Zeichen im naechste inner while angucken
MG Mud User88f12472016-06-24 23:31:02 +0200465 }
Zesstrafb4cc3d2019-05-06 21:16:30 +0200466 // Ende des gesamten Strings erreicht.
467 else
468 {
469 cont=0; // ende inner while
470 // letzten Argumentblock anhaengen
471 if (str!="") tmp+=({str});
472 str=""; // beendet outer while
473 }
474 } // inner while
475 } // outer while
476
477 if (familymode)
478 {
479 int err=FALIASDB->AddOrReplaceFamilyAlias(commandverb, tmp);
480 if (err < 1)
481 {
482 printf("Neues Familienalias konnte nicht definiert werden.\n");
483 if (err==-2)
484 printf("Du hast schon genuegend Aliase definiert!\n");
485 }
486 else
487 {
488 printf("Neues Familienalias: %s\t= %s\n",
489 commandverb, present_alias(tmp));
490 // Alias direkt aktivieren, aber nur falls es keins in diesem Char gibt
491 // (was dann eh schon aktiv ist).
492 if (!member(aliases, commandverb))
493 active_aliases[commandverb] = tmp;
MG Mud User88f12472016-06-24 23:31:02 +0200494 }
495 }
MG Mud User88f12472016-06-24 23:31:02 +0200496 else
497 {
Zesstrafb4cc3d2019-05-06 21:16:30 +0200498 if ((!aliases[commandverb]) && (sizeof(aliases)>2000))
499 printf("Du hast schon genuegend Aliase definiert!\n");
500 else
501 {
Zesstrac687e292019-05-28 22:43:11 +0200502 if (member(active_aliases, commandverb)
503 && !member(aliases, commandverb))
504 printf("Hinweis: das neue Alias ueberschattet ein Familienalias.\n");
505 aliases[commandverb] = tmp;
Zesstrafb4cc3d2019-05-06 21:16:30 +0200506 active_aliases[commandverb] = tmp;
507 printf("Neues Alias: %s\t= %s\n",commandverb, present_alias(tmp));
508 }
MG Mud User88f12472016-06-24 23:31:02 +0200509 }
510 return 1;
511}
512
513static int unalias(string str) {
MG Mud User88f12472016-06-24 23:31:02 +0200514
Zesstrafb4cc3d2019-05-06 21:16:30 +0200515 string um;
MG Mud User88f12472016-06-24 23:31:02 +0200516 if (unmodified&&unmodified!="")
517 um=implode(old_explode(unmodified," ")[1..]," ");
518 if (um=="") um=0;
Zesstraf86ed742019-04-25 18:37:27 +0200519 if ( !(str=um || _unparsed_args()))
520 return 0;
521
Zesstrafb4cc3d2019-05-06 21:16:30 +0200522 int familymode;
Zesstraf332ded2019-04-25 18:40:02 +0200523 while(sizeof(str) >= 2 && str[0] == '-')
524 {
525 if (str[1] == 'f')
526 familymode = 1;
527 else
528 break;
529 // "-f " abschneiden
530 str = trim(str[2..], TRIM_LEFT);
531 }
532
MG Mud User88f12472016-06-24 23:31:02 +0200533 if (str == "*.*" || str == "*") {
534 write(break_string(
535 "Versuchs mal mit 'unalias .*', wenn Du wirklich alle Alias entfernen "
536 "willst.",78));
537 return 1;
538 }
Zesstrafb4cc3d2019-05-06 21:16:30 +0200539
540 mapping selected_aliases;
541 if (familymode)
542 selected_aliases=FALIASDB->QueryFamilyAlias();
543 else
544 selected_aliases = aliases;
545
546 string *to_delete;
547 // Genau ein Alias gegeben?
548 if (member(selected_aliases,str))
549 to_delete = ({str});
550 else // sonst als RegExp interpretieren
551 to_delete=regexp(m_indices(selected_aliases),("^"+str+"$"));
552
553 if (sizeof(to_delete))
Zesstraf86ed742019-04-25 18:37:27 +0200554 {
Zesstrafb4cc3d2019-05-06 21:16:30 +0200555 foreach(string key : to_delete)
Zesstraf86ed742019-04-25 18:37:27 +0200556 {
Zesstrafb4cc3d2019-05-06 21:16:30 +0200557 if (familymode)
558 FALIASDB->DeleteFamilyAlias(key);
559 else
560 m_delete(aliases, key);
561 // auf jeden Fall noch deaktivieren
562 m_delete(active_aliases, key);
MG Mud User88f12472016-06-24 23:31:02 +0200563 }
Zesstrafb4cc3d2019-05-06 21:16:30 +0200564 if (sizeof(to_delete) == 1)
565 write("Du entfernst das Alias \""+ to_delete[0] +"\".\n");
566 else
567 write(break_string(("Du entfernst folgende Aliase: "
568 +CountUp(to_delete) + ".\n"),75));
Zesstra3fe70c62019-05-28 22:46:19 +0200569 // Wenn nicht im Familienmodus (d.h. Char-Aliase wurden geloescht), wird
570 // versucht, gleichnamige Familienaliase (sofern vorhanden) zu
571 // aktivieren.
572 if (!familymode)
573 {
574 merge_family_aliases(to_delete, 1);
575 }
MG Mud User88f12472016-06-24 23:31:02 +0200576 }
Zesstrafb4cc3d2019-05-06 21:16:30 +0200577 else
578 write("So ein Alias hast Du nicht definiert.\n");
579
MG Mud User88f12472016-06-24 23:31:02 +0200580 return 1;
581}
582
583varargs string _unparsed_args(int level)
584{
585 return unparsed_args[level];
586}
587
588#define ARTIKEL ({"das","der","die","des","dem","den","ein","eine","einer",\
589 "eines"})
590
591#define TRENNER ({"in","aus","ueber","auf","unter","mit","durch","fuer",\
592 "von","vom","im","aufs","ein","weg","zurueck"})
593
594static string _single_spaces(string str)
595{
596 return regreplace(str, " *", " ", 1);
597}
598
599static mixed _return_args(string str)
600{
601 string *t,*t2,verb,s2;
602 int i,l,j,l2;
603
604 t=explode(trim(str,TRIM_BOTH)," ");
605 verb=t[0];
606 t = t[1..];
607 if (!sizeof(t))
608 {
609 unparsed_args[0]=unparsed_args[1]=unparsed_args[2]=0;
610 return str=verb;
611 }
612 else
613 str = unparsed_args[0] = implode(t, " ");
614
615 str=unparsed_args[1]=lower_case(_single_spaces(str));
616 t=regexplode(str,"\\<im\\>|\\<ins\\>");
617 for (i=1;i<sizeof(t);i+=2) t[i]="in";
618 t=regexplode(implode(t,""),"[\\,\\!\\:][\\,\\!\\:]*");
619 l=sizeof(t);
620 for(i=1;i<l;i+=2) t[i]="";
621 t=old_explode(implode(t,"")," ")-({""});
622 for (i=sizeof(t)-2;i>=0;i--)
623 {
624 if (member(ARTIKEL,t[i])>=0)
625 t=t[0..i-1]+t[i+1..];
626 }
627 unparsed_args[2]=implode(t," ");
628 t=regexplode((str=implode(t," ")),"[0-9][0-9]*\\.");
629 if ((l=sizeof(t))>2)
630 {
631 i=1;
632 while (i<l-1)
633 {
634 t[i]=" "+t[i][0..<2]+" ";
635 if ((l2=sizeof(t2=old_explode(t[i+1]," ")))<2)
636 t[i+1]+=t[i];
637 else
638 {
639 for (j=1;j<l2;j++)
640 {
641 if (member(TRENNER,t2[j])>=0)
642 {
643 t2[j-1]+=t[i];
644 l2=0;
645 }
646 }
647 if (!l2)
648 t[i+1]=implode(t2," ");
649 else
650 t[i+1]+=t[i];
651 }
652 t[i]="";
653 i+=2;
654 }
655 str=_single_spaces(verb+" "+implode(t," "));
656 if (str[<1]==' ') str=str[0..<2];
657 } else str=verb+(str==""?"":" "+str);
658 if (show_processing>2)
659 printf("-> {%s}\n",str);
660 return str;
661}
662
663static void decay_average()
664{
665 if (absolute_hb_count()-last_chg>14)
666 {
667 last_chg=absolute_hb_count()-last_chg;
668 if (last_chg>3000)
669 last_chg=absolute_hb_count(),cmds_per_time=0;
670 else
671 {
672 while (last_chg>14)
673 cmds_per_time=cmds_per_time*9/10, last_chg-=15;
674 last_chg=absolute_hb_count()-last_chg;
675 }
676 }
677}
678
679private void DelayPreparedSpells() {
680 mixed ps;
681
682 if (pointerp(ps=QueryProp(P_PREPARED_SPELL))
683 && sizeof(ps)>=1 && intp(ps[0])) {
684 ps[0]++;
685 SetProp(P_PREPARED_SPELL,ps);
686 write("Die Ausfuehrung Deines vorbereiteten Spruches wird verzoegert.\n");
687 } else if (ps) {
688 SetProp(P_PREPARED_SPELL,0);
689 }
690}
691
692static mixed bb;
693#ifndef BBMASTER
694#define BBMASTER "/secure/bbmaster"
695#endif
696
697/** Interpretiert Aliase und History-Kommandos
MG Mud User88f12472016-06-24 23:31:02 +0200698 \param[in] str string - Kommando des Spielers
699 \return interpretiertes Alias bzw. korrektes Kommando aus der History
700*/
701private string parsecommand(string str)
702{
703 if (str[0]=='\\')
704 {
705 // Kommando soll nicht interpretiert werden
706 return str[1..];
707 }
708 else if (str[0]=='&')
709 {
710 // Kommando aus der History
711 string cmd = str[1..];
712 int cmd_size = sizeof(cmd);
713 int cmd_found = 0;
714 if (cmd_size)
715 {
716 // Test ob &<text> etwas findet
717 for (int i=0;i<hist_size-1 && !cmd_found;i++)
718 {
719 int idx = (hist_size-i+hist_now-1)%hist_size;
720 if (history[idx][0..cmd_size-1]==cmd)
721 {
722 str = history[idx];
723 cmd_found = 1;
724 }
725 if (cmd_found)
726 {
727 if (show_processing)
728 printf("[%s]\n",str);
729 }
730 }
731 }
732 if (!cmd_found)
733 {
734 // Test, ob &<nr> klappt
735 int nummer;
736 if (str=="&&")
737 str = "&-0";
738 if (sscanf(str,"&%d",nummer))
739 {
740 if (nummer<0 || (!nummer && str[1]=='-'))
741 {
742 if (nummer<-(hist_size-1))
743 nummer=-1;
744 else
745 nummer=(hist_now+nummer-1+hist_size)%hist_size;
746 }
747 else
748 {
749 if (nummer>hist_now || hist_now-nummer>hist_size)
750 nummer=-1;
751 else
752 nummer=nummer%hist_size;
753 }
754 if (nummer<0
755 || ( (cmd=history[nummer]) =="\n\n") )
756 notify_fail("Der Befehl ist nicht in der History!\n");
757 else
758 {
759 str = cmd;
760 if (show_processing)
761 printf("[%s]\n",str);
762 }
763 }
764 }
765 }
766 switch (str)
767 {
768 case "n": return "norden";
769 case "s": return "sueden";
770 case "w": return "westen";
771 case "o": return "osten";
772 case "nw": return "nordwesten";
773 case "sw": return "suedwesten";
774 case "so": return "suedosten";
775 case "no": return "nordosten";
776 case "ob": return "oben";
777 case "u": return "unten";
778 }
779 // Test auf Alias
780 string output = "";
781 string* input = explode(str," ");
782 int input_size = sizeof(input);
Zesstrafb4cc3d2019-05-06 21:16:30 +0200783 mixed alias = active_aliases[input[0]];
MG Mud User88f12472016-06-24 23:31:02 +0200784 if (!alias)
785 return str;
Zesstrafb4cc3d2019-05-06 21:16:30 +0200786 // Das Alias ist in ein Array von Strings gespeichert. Alle
787 // Alias-Argument ($n, $* oder $n*) stehen an der jeweiligen Stelle als
788 // laufender Index im Array. An der Stelle werden die Argumente vom Alias
789 // eingefuegt, alle anderen Elemente werden in den output kopiert. Negative
790 // Zahlen stehen fuer $n*, d.h. alle Argument nach dem genannten.
791 // Bsp: ({"stecke ", 1, " in ", -2 })
MG Mud User88f12472016-06-24 23:31:02 +0200792 foreach (mixed a:alias)
793 {
794 if (!intp(a))
795 output += a;
796 else
797 {
798 if (a >= 0)
799 {
Zesstrafb4cc3d2019-05-06 21:16:30 +0200800 // Einzelnes Argument ($n). Argument anstelle von a einfuegen, falls
801 // genug angegeben wurden
MG Mud User88f12472016-06-24 23:31:02 +0200802 if (input_size > a)
803 output += input[a];
804 }
805 else
806 {
Zesstrafb4cc3d2019-05-06 21:16:30 +0200807 // Argumente ab n ($n*). Alle von a bis Ende einfuegen.
MG Mud User88f12472016-06-24 23:31:02 +0200808 a = -a;
809 if (input_size > a)
810 output += implode(input[a..]," ");
811 }
812 }
813 }
814 output = _single_spaces(output);
815 str = trim(output,TRIM_RIGHT);
816 if (show_processing>1)
817 printf("[%s]\n",str);
818 return str;
819}
820
821/** Behandelt alle Sonderfaelle der Eingabe des Spielers
822 Alle Befehle des Spielers, die nicht durch Objekte behandelt
823 werden sollen, werden hier erkannt und ausgefuehrt.
824 Dazu gehoert auch die Interpretation von Aliases und History-
825 befehlen.
826 \param[in] str string: Kommando des Spielers
827 \return auszufuehrendes Kommando
828 oder 0 fuer ein nicht interpretierbares Kommando
829 oder 1 fuer ein bereits durchgefuehrtes Kommando
830*/
831mixed modify_command(string str)
832{
833
834 if (extern_call() && previous_object() &&
835 (previous_object()!=this_object() || process_call()) )
836 {
837 return 0;
838 }
839
840 // Leerzeichen an den Enden abschneiden.
841 str = trim(str, TRIM_BOTH);
842
843 if (bb)
844 BBMASTER->BBWrite(trim(str,TRIM_RIGHT,"\n"), 0);
845
846 decay_average();
847 cmds_per_time+=10000;
848
849 unparsed_args[0]=unparsed_args[1]=unparsed_args[2]=unmodified="";
850
851 if (!sizeof(str)) return "";
852
853 // Kommando wird geparst
854 unmodified=parsecommand(str);
855
856 // Environment schonmal merken.
857 last_command_env=environment();
858
859 if (unmodified == "")
860 return "";
861 // Kommando in History merken, auch wenn es im Kommandoblock abgebrochen
862 // wird.
863 AddHistory(unmodified);
864
865 // pruefen, ob Kommandoblock gesetzt ist.
866 // (Fuer Magier mit mschau ein wird das ignoriert.)
867 // BTW: Es wird absichtlich nicht das Ergebnis der Closure zurueckgegeben,
868 // sonst wuerde man beliebigen Objekten nicht nur das Abbrechen, sondern
869 // auch das Aendern von Kommandos ermoeglichen.
870 if (disablecommands && !IS_LEARNING(ME) )
871 {
872 if (disablecommands[B_TIME] >= time()
873 && objectp(disablecommands[B_OBJECT]))
874 {
875 // disablecommands valid
876 // hart-kodierte Ausnameliste pruefen
877 if ( member(({"mrufe","mschau","bug","idee","typo","detail"}),
878 explode(str," ")[0]) == -1)
879 {
880 if (closurep(disablecommands[B_VALUE]))
881 {
882 if (funcall(disablecommands[B_VALUE],_return_args(unmodified)))
883 {
884 // Non-zero Closure-Ergebnis, Abbruch. Die gerufene Funktion ist
885 // fuer eine geeignete Meldung an den Spieler verantwortlich.
886 return 1;
887 }
888 }
889 // wenn Text, dann auch pruefen, ob das Kommandoverb in den Ausnahmen
890 // steht. (query_verb() geht leider hier noch nicht.)
891 else if (stringp(disablecommands[B_VALUE])
892 && member(disablecommands[B_EXCEPTIONS],
893 explode(str," ")[0]) == -1)
894 {
895 // meldung ausgeben...
896 tell_object(PL, disablecommands[B_VALUE]);
897 // und Ende...
898 return 1;
899 }
900 }
901 }
902 else disablecommands=0;
903 }
904
905 // Verfolger direkt ins Env reinholen.
906 if (remove_call_out("TakeFollowers")>=0)
907 catch(TakeFollowers();publish);
908
909 DelayPreparedSpells();
910
911 // Historyeintrag korrigieren
912 if (unmodified[0]=='^')
913 {
914 string *oldnew,pre,post;
915 if (sizeof(oldnew=explode(unmodified,"^"))>2)
916 {
917 int hist_idx = (hist_now-1)%hist_size;
918 sscanf(history[hist_idx],"%s"+oldnew[1]+"%s", pre, post);
919 unmodified = pre+oldnew[2]+post;
920 if (show_processing)
921 write("["+unmodified+"]\n");
922 // korrigiertes Kommando natuerlich auch in die History.
923 AddHistory(unmodified);
924 }
925 }
926
927 if( bb )
928 BBMASTER->BBWrite(" -> " + unmodified, 1);
929
930 if (show_processing>1)
931 printf("[%s]\n",unmodified);
932
933 mixed ret = _return_args(unmodified);
934
935 // wenn Spieler eingewilligt hat und die SyntaxDB geladen ist, Befehl
936 // dorthin melden.
937 if (syntaxdb)
938 {
939 if (!objectp(syntaxdb[0]))
940 syntaxdb[0] = find_object("/secure/syntaxdb");
941 if (syntaxdb[0])
942 catch(syntaxdb[0]->start_cmd(unmodified);nolog);
943 }
944 return ret;
945}
946
947static int do_list(string str)
948{
949 string *cmdlist;
950 int i;
951
952 if (!QueryProp(P_WANTS_TO_LEARN))
953 return 0;
954 cmdlist=old_explode(_unparsed_args()||"",";")-({ "" });
955 for (i=0;i<sizeof(cmdlist);i++)
956 {
957 cmdlist[i]=implode(old_explode(cmdlist[i]," ")-({}), " ");
958 if (show_processing)
959 write("["+cmdlist[i]+"]\n");
960 command(cmdlist[i]);
961 }
962 return 1;
963}
964
965//falls die aliasliste kaputt ist ...
966
967int unalias_all()
968{
Zesstrafb4cc3d2019-05-06 21:16:30 +0200969 if (IS_ELDER(this_interactive()))
970 {
971 aliases=([]);
Zesstra3fe70c62019-05-28 22:46:19 +0200972 merge_family_aliases(0,0);
Zesstrafb4cc3d2019-05-06 21:16:30 +0200973 }
MG Mud User88f12472016-06-24 23:31:02 +0200974 return 1;
975}
976
977object _query_last_command_env()
978{
979 return last_command_env;
980}
981
982int _query_show_alias_processing()
983{
984 return show_processing;
985}
986
987int _query_histmin()
988{
989 return histmin;
990}
991
992varargs void AddAction(mixed fun, mixed cmd, int flag, int lvl)
993{
994 int i;
995 mixed *cmds;
996
997 log_file( "ARCH/ADD_ACTION", sprintf(
998 "%s:\n TO: %O TP: %O PO: %O\n fun: %O cmd: %O flag: %O lvl: %O",
999 dtime(time()), this_object(), this_player(), previous_object(),
1000 fun, cmd, flag, lvl));
1001
1002 if (!(cmds=Query(P_LOCALCMDS))) cmds=({});
1003
1004 if (!pointerp(cmd)) cmd=({cmd});
1005
1006 for (i = sizeof(cmd)-1; i>=0; i--)
1007 cmds += ({({ cmd[i] , fun, flag, lvl})});
1008
1009 Set(P_LOCALCMDS, cmds);
1010}
1011
1012static int auswerten(mixed cmd, string str)
1013{
1014 if (closurep(cmd))
1015 return funcall(cmd,str);
1016 if (stringp(cmd))
1017 return call_other(this_object(),cmd,str);
1018 return 0;
1019}
1020
1021static varargs int __auswerten(string str, string intern)
1022{
1023 string verb;
1024 mixed *cmd, cmds;
1025 int i,ret,lvl,l,vl;
1026
1027 if (!intern)
1028 verb=query_verb();
1029 else
1030 verb=intern;
1031 lvl=query_wiz_level(ME);
1032 vl=sizeof(verb);
1033 cmds=QueryProp(P_LOCALCMDS);
1034
1035 for(i=sizeof(cmds)-1;i>=0;i--)
1036 {
1037 cmd=cmds[i],l=sizeof(cmd[0]);
1038 if (cmd[0]==verb[0..l-1] && cmd[3]<=lvl && (cmd[2]||vl==l) &&
1039 (ret=auswerten(cmd[1],str)))
1040 return ret;
1041 }
1042 // An dieser Stelle gibt es hier und vermutlich nirgendwo anders etwas, was
1043 // dieses Kommando als gueltig betrachtet. Wir informieren ggf. die
1044 // Syntax-DB. (Achtung: wenn jemand ne add_action() im Spielerobjekt
1045 // einbaut, die vor dieser eingetragen wird, ist die Annahme ggf. falsch.)
1046 // wenn Spieler eingewilligt hat und die SyntaxDB geladen ist, Befehl
1047 // dorthin melden.
1048 if (syntaxdb)
1049 {
1050 if (!objectp(syntaxdb[0]))
1051 syntaxdb[0] = find_object("/secure/syntaxdb");
1052 if (syntaxdb[0])
1053 catch(syntaxdb[0]->cmd_unsuccessful();nolog);
1054 }
1055
1056 return 0;
1057}
1058
1059public void syntax_log_ep(int type)
1060{
1061 // wenn Spieler eingewilligt hat und die SyntaxDB geladen ist, Befehl
1062 // dorthin melden.
1063 if (syntaxdb && syntaxdb[0])
1064 {
1065 catch(syntaxdb[0]->LogEP(type);nolog);
1066 }
1067}
1068
1069static mixed _query_localcmds()
1070{
1071 mixed *l;
1072
1073 l=Query(P_LOCALCMDS);
1074 if (!pointerp(l))
1075 l=({});
1076 return ({
1077 ({"ali","alias",0,0}),
1078 ({"alias","alias",0,0}),
1079 ({"unali","unalias",1,0}),
1080 ({"histmin","histmin",0,0}),
1081 ({"histlen","histlen",0,0}),
1082 ({"hist","show_hist",0,0}),
1083 ({"history","show_hist",0,0}),
1084 ({"do","do_list",0,LEARNER_LVL}),
1085 ({"ersetzungsanzeige","replacedisplay",0,0}),
1086 ({"syntaxsammlung","collect_cmds",0,0}),
1087 ({"fehlermeldung","set_errormessage",0,SEER_LVL}),
1088 })+l;
1089}
1090
1091static int collect_cmds(string cmd)
1092{
1093 if (!stringp(cmd))
1094 {
1095 _notify("Mit diesem Befehl kannst Du mithelfen, Syntaxen im MG zu "
1096 "verbessern. Wenn Du einverstanden bist, speichern wir "
1097 "anonym (d.h. ohne Deinen Charnamen), welche Deiner Befehle "
1098 "erfolgreich und nicht erfolgreich waren. Uebliche "
1099 "Kommunikationsbefehle werden dabei nicht gespeichert.",
1100 0);
1101 _notify("Mit 'syntaxsammlung ja' kannst Du die Speicherung einschalten, "
1102 "mit 'syntaxsammlung nein' kannst Du sie ausschalten.",0);
1103 _notify("Deine Befehle werden zur Zeit"
1104 + (QueryProp("_syntaxdb") ? " " : " NICHT ")
1105 + "gespeichert.", 0);
1106 }
1107 else if (cmd == "ja")
1108 {
1109 SetProp("_syntaxdb", 1);
1110 _notify("Ab jetzt werden Deine Befehle gespeichert. Vielen Dank!", 0);
1111 }
1112 else
1113 {
1114 SetProp("_syntaxdb", 0);
1115 _notify("Ab jetzt werden Deine Befehle NICHT gespeichert.", 0);
1116 }
1117 return 1;
1118}
1119
1120int _query_command_average()
1121{
1122 decay_average();
1123 return cmds_per_time;
1124}
1125
1126nomask void __set_bb(int flag) {
1127 if( previous_object()!=find_object(BBMASTER) || process_call() )
1128 return;
1129 bb=flag;
1130}
1131
1132
1133nomask public void countCmds( int type, string key )
1134{
1135 string tmp;
1136
1137 if ( this_player() != this_interactive()
1138 || this_interactive() != this_object()
1139 || member( cmd_types, type ) < 0 )
1140 return;
1141
1142 tmp = sprintf( "%d\n%s", type, key );
1143
1144 commands -= ({ tmp });
1145 commands += ({ tmp });
1146 commands = commands[0..max_commands-1];
1147}
1148
1149
1150nomask public string *getCmds()
1151{
1152 string *tmp;
1153
1154 if ( previous_object() != find_object(BBMASTER) )
1155 return ({});
1156
1157 tmp = commands;
1158 commands = ({});
1159
1160 return tmp;
1161}
1162
1163/*
1164 * Force the monster to do a command. The force_us() function isn't
1165 * always good, because it checks the level of the caller, and this function
1166 * can be called by a room.
1167 */
1168int command_me(string cmd)
1169{
1170 if (IS_LEARNER(ME))
1171 {
1172 if (!this_interactive() || !previous_object())
1173 return 0;
1174 if( geteuid(ME)!=geteuid(this_interactive())
1175 || geteuid(ME)!=geteuid(previous_object()) )
1176 {
1177 if( query_wiz_level(ME)<query_wiz_level(previous_object()))
1178 tell_object(ME,previous_object()->name()+" zwingt Dich zu: "
1179 + cmd + ".\n");
1180 else
1181 {
1182 tell_object(ME,previous_object()->name()
1183 + " versucht, Dich zu " + cmd + " zu zwingen.\n" );
1184 return 0;
1185 }
1186 }
1187 }
1188 return command(cmd);
1189}
1190
1191
1192static mixed _query_p_lib_disablecommands() {
1193 // abgelaufen oder Objekt zerstoert? Weg damit.
1194 if (pointerp(disablecommands)
1195 && (disablecommands[B_TIME] < time()
1196 || !objectp(disablecommands[B_OBJECT])) )
1197 return(disablecommands = 0);
1198
1199 // sonst Kopie zurueck (copy(0) geht)
1200 return(copy(disablecommands));
1201}
1202
1203static mixed _set_p_lib_disablecommands(mixed data) {
1204
1205 // setzendes Objekt ermitteln, da diese Funktion nur per SetProp() gerufen
1206 // werden sollte (!), ist das PO(1);
1207 object origin = previous_object(1);
1208 // wenn nicht existent, direkt abbruch
1209 if (!objectp(origin))
1210 return _query_p_lib_disablecommands();
1211
1212 // Prop loeschen? Explizit loeschen darf jeder, allerdings nicht direkt
1213 // ungeprueft ueberschreiben.
1214 if (!data) {
1215 return (disablecommands = 0 );
1216 }
1217 // mal direkt buggen bei falschen Datentyp, damits auffaellt.
1218 if (!pointerp(data) || sizeof(data) < 2 || !intp(data[0])
1219 || (!stringp(data[1]) && !closurep(data[1]))
1220 || (sizeof(data) >= 3 && !pointerp(data[2])) )
1221 raise_error(sprintf(
1222 "Wrong data type for P_DISABLE_COMMANDS. Expected Array with "
1223 "2 or 3 elements (int, string|closure, [string*]), got %.25O\n",
1224 data));
1225
1226 // Wenn abgelaufen oder gleiches Objekt wie letztes Mal: eintragen.
1227 if (!disablecommands || (disablecommands[B_TIME] < time()
1228 || !objectp(disablecommands[B_OBJECT])
1229 || disablecommands[B_OBJECT] == origin) ) {
1230 // Loggen nur, wenn eine Closure eingetragen wird. Reduziert den
1231 // Logscroll und Strings haben deutlich weniger Missbrauchspotential.
1232 if (closurep(data[1])) {
1233 CBLOG(sprintf("[%s] CB gesetzt von %O, gueltig bis %s, Daten: %O\n",
1234 strftime("%Y%m%d-%H:%M:%S"),origin,
1235 strftime("%Y%m%d-%H:%M:%S",data[0]),
1236 (stringp(data[1]) ? regreplace(data[1],"\n","\\n",0)
1237 : data[1])));
1238 }
1239 if (sizeof(data)+1 <= B_EXCEPTIONS)
1240 disablecommands = ({ origin, data[0], data[1], ({}) });
1241 else
1242 disablecommands = ({ origin, data[0], data[1], data[2] });
1243 return(copy(disablecommands));
1244 }
1245
1246 return(_query_p_lib_disablecommands());
1247}
1248
1249static mixed _set__syntaxdb(mixed v)
1250{
1251 Set("_syntaxdb", v, F_VALUE);
1252 if (v)
1253 syntaxdb = ({find_object("/secure/syntaxdb")});
1254 else
1255 syntaxdb = 0;
1256 return QueryProp("_syntaxdb");
1257}
1258