blob: c089f1b0356ed464f2062c9d5525ae101a9e07b4 [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 {
Zesstra1b98da72020-10-19 21:50:22 +0200498 if ((!aliases[commandverb]) && (sizeof(aliases)>1500))
Zesstrafb4cc3d2019-05-06 21:16:30 +0200499 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));
Zesstra1b98da72020-10-19 21:50:22 +0200508 if (sizeof(aliases)>1000)
509 {
510 printf("Du hast bereits %d Aliase definiert. Bitte raeume auf!\n");
511 }
512 }
MG Mud User88f12472016-06-24 23:31:02 +0200513 }
514 return 1;
515}
516
517static int unalias(string str) {
MG Mud User88f12472016-06-24 23:31:02 +0200518
Zesstrafb4cc3d2019-05-06 21:16:30 +0200519 string um;
MG Mud User88f12472016-06-24 23:31:02 +0200520 if (unmodified&&unmodified!="")
521 um=implode(old_explode(unmodified," ")[1..]," ");
522 if (um=="") um=0;
Zesstraf86ed742019-04-25 18:37:27 +0200523 if ( !(str=um || _unparsed_args()))
524 return 0;
525
Zesstrafb4cc3d2019-05-06 21:16:30 +0200526 int familymode;
Zesstraf332ded2019-04-25 18:40:02 +0200527 while(sizeof(str) >= 2 && str[0] == '-')
528 {
529 if (str[1] == 'f')
530 familymode = 1;
531 else
532 break;
533 // "-f " abschneiden
534 str = trim(str[2..], TRIM_LEFT);
535 }
536
MG Mud User88f12472016-06-24 23:31:02 +0200537 if (str == "*.*" || str == "*") {
538 write(break_string(
539 "Versuchs mal mit 'unalias .*', wenn Du wirklich alle Alias entfernen "
540 "willst.",78));
541 return 1;
542 }
Zesstrafb4cc3d2019-05-06 21:16:30 +0200543
544 mapping selected_aliases;
545 if (familymode)
546 selected_aliases=FALIASDB->QueryFamilyAlias();
547 else
548 selected_aliases = aliases;
549
550 string *to_delete;
551 // Genau ein Alias gegeben?
552 if (member(selected_aliases,str))
553 to_delete = ({str});
554 else // sonst als RegExp interpretieren
555 to_delete=regexp(m_indices(selected_aliases),("^"+str+"$"));
556
557 if (sizeof(to_delete))
Zesstraf86ed742019-04-25 18:37:27 +0200558 {
Zesstrafb4cc3d2019-05-06 21:16:30 +0200559 foreach(string key : to_delete)
Zesstraf86ed742019-04-25 18:37:27 +0200560 {
Zesstrafb4cc3d2019-05-06 21:16:30 +0200561 if (familymode)
562 FALIASDB->DeleteFamilyAlias(key);
563 else
564 m_delete(aliases, key);
565 // auf jeden Fall noch deaktivieren
566 m_delete(active_aliases, key);
MG Mud User88f12472016-06-24 23:31:02 +0200567 }
Zesstrafb4cc3d2019-05-06 21:16:30 +0200568 if (sizeof(to_delete) == 1)
569 write("Du entfernst das Alias \""+ to_delete[0] +"\".\n");
570 else
571 write(break_string(("Du entfernst folgende Aliase: "
572 +CountUp(to_delete) + ".\n"),75));
Zesstra3fe70c62019-05-28 22:46:19 +0200573 // Wenn nicht im Familienmodus (d.h. Char-Aliase wurden geloescht), wird
574 // versucht, gleichnamige Familienaliase (sofern vorhanden) zu
575 // aktivieren.
576 if (!familymode)
577 {
578 merge_family_aliases(to_delete, 1);
579 }
MG Mud User88f12472016-06-24 23:31:02 +0200580 }
Zesstrafb4cc3d2019-05-06 21:16:30 +0200581 else
582 write("So ein Alias hast Du nicht definiert.\n");
583
MG Mud User88f12472016-06-24 23:31:02 +0200584 return 1;
585}
586
587varargs string _unparsed_args(int level)
588{
589 return unparsed_args[level];
590}
591
592#define ARTIKEL ({"das","der","die","des","dem","den","ein","eine","einer",\
593 "eines"})
594
595#define TRENNER ({"in","aus","ueber","auf","unter","mit","durch","fuer",\
596 "von","vom","im","aufs","ein","weg","zurueck"})
597
598static string _single_spaces(string str)
599{
600 return regreplace(str, " *", " ", 1);
601}
602
603static mixed _return_args(string str)
604{
605 string *t,*t2,verb,s2;
606 int i,l,j,l2;
607
608 t=explode(trim(str,TRIM_BOTH)," ");
609 verb=t[0];
610 t = t[1..];
611 if (!sizeof(t))
612 {
613 unparsed_args[0]=unparsed_args[1]=unparsed_args[2]=0;
614 return str=verb;
615 }
616 else
617 str = unparsed_args[0] = implode(t, " ");
618
619 str=unparsed_args[1]=lower_case(_single_spaces(str));
620 t=regexplode(str,"\\<im\\>|\\<ins\\>");
621 for (i=1;i<sizeof(t);i+=2) t[i]="in";
622 t=regexplode(implode(t,""),"[\\,\\!\\:][\\,\\!\\:]*");
623 l=sizeof(t);
624 for(i=1;i<l;i+=2) t[i]="";
625 t=old_explode(implode(t,"")," ")-({""});
626 for (i=sizeof(t)-2;i>=0;i--)
627 {
628 if (member(ARTIKEL,t[i])>=0)
629 t=t[0..i-1]+t[i+1..];
630 }
631 unparsed_args[2]=implode(t," ");
632 t=regexplode((str=implode(t," ")),"[0-9][0-9]*\\.");
633 if ((l=sizeof(t))>2)
634 {
635 i=1;
636 while (i<l-1)
637 {
638 t[i]=" "+t[i][0..<2]+" ";
639 if ((l2=sizeof(t2=old_explode(t[i+1]," ")))<2)
640 t[i+1]+=t[i];
641 else
642 {
643 for (j=1;j<l2;j++)
644 {
645 if (member(TRENNER,t2[j])>=0)
646 {
647 t2[j-1]+=t[i];
648 l2=0;
649 }
650 }
651 if (!l2)
652 t[i+1]=implode(t2," ");
653 else
654 t[i+1]+=t[i];
655 }
656 t[i]="";
657 i+=2;
658 }
659 str=_single_spaces(verb+" "+implode(t," "));
660 if (str[<1]==' ') str=str[0..<2];
661 } else str=verb+(str==""?"":" "+str);
662 if (show_processing>2)
663 printf("-> {%s}\n",str);
664 return str;
665}
666
667static void decay_average()
668{
669 if (absolute_hb_count()-last_chg>14)
670 {
671 last_chg=absolute_hb_count()-last_chg;
672 if (last_chg>3000)
673 last_chg=absolute_hb_count(),cmds_per_time=0;
674 else
675 {
676 while (last_chg>14)
677 cmds_per_time=cmds_per_time*9/10, last_chg-=15;
678 last_chg=absolute_hb_count()-last_chg;
679 }
680 }
681}
682
683private void DelayPreparedSpells() {
684 mixed ps;
685
686 if (pointerp(ps=QueryProp(P_PREPARED_SPELL))
687 && sizeof(ps)>=1 && intp(ps[0])) {
688 ps[0]++;
689 SetProp(P_PREPARED_SPELL,ps);
690 write("Die Ausfuehrung Deines vorbereiteten Spruches wird verzoegert.\n");
691 } else if (ps) {
692 SetProp(P_PREPARED_SPELL,0);
693 }
694}
695
696static mixed bb;
697#ifndef BBMASTER
698#define BBMASTER "/secure/bbmaster"
699#endif
700
701/** Interpretiert Aliase und History-Kommandos
MG Mud User88f12472016-06-24 23:31:02 +0200702 \param[in] str string - Kommando des Spielers
703 \return interpretiertes Alias bzw. korrektes Kommando aus der History
704*/
705private string parsecommand(string str)
706{
707 if (str[0]=='\\')
708 {
709 // Kommando soll nicht interpretiert werden
710 return str[1..];
711 }
712 else if (str[0]=='&')
713 {
714 // Kommando aus der History
715 string cmd = str[1..];
716 int cmd_size = sizeof(cmd);
717 int cmd_found = 0;
718 if (cmd_size)
719 {
720 // Test ob &<text> etwas findet
721 for (int i=0;i<hist_size-1 && !cmd_found;i++)
722 {
723 int idx = (hist_size-i+hist_now-1)%hist_size;
724 if (history[idx][0..cmd_size-1]==cmd)
725 {
726 str = history[idx];
727 cmd_found = 1;
728 }
729 if (cmd_found)
730 {
731 if (show_processing)
732 printf("[%s]\n",str);
733 }
734 }
735 }
736 if (!cmd_found)
737 {
738 // Test, ob &<nr> klappt
739 int nummer;
740 if (str=="&&")
741 str = "&-0";
742 if (sscanf(str,"&%d",nummer))
743 {
744 if (nummer<0 || (!nummer && str[1]=='-'))
745 {
746 if (nummer<-(hist_size-1))
747 nummer=-1;
748 else
749 nummer=(hist_now+nummer-1+hist_size)%hist_size;
750 }
751 else
752 {
753 if (nummer>hist_now || hist_now-nummer>hist_size)
754 nummer=-1;
755 else
756 nummer=nummer%hist_size;
757 }
758 if (nummer<0
759 || ( (cmd=history[nummer]) =="\n\n") )
760 notify_fail("Der Befehl ist nicht in der History!\n");
761 else
762 {
763 str = cmd;
764 if (show_processing)
765 printf("[%s]\n",str);
766 }
767 }
768 }
769 }
770 switch (str)
771 {
772 case "n": return "norden";
773 case "s": return "sueden";
774 case "w": return "westen";
775 case "o": return "osten";
776 case "nw": return "nordwesten";
777 case "sw": return "suedwesten";
778 case "so": return "suedosten";
779 case "no": return "nordosten";
780 case "ob": return "oben";
781 case "u": return "unten";
782 }
783 // Test auf Alias
784 string output = "";
785 string* input = explode(str," ");
786 int input_size = sizeof(input);
Zesstrafb4cc3d2019-05-06 21:16:30 +0200787 mixed alias = active_aliases[input[0]];
MG Mud User88f12472016-06-24 23:31:02 +0200788 if (!alias)
789 return str;
Zesstrafb4cc3d2019-05-06 21:16:30 +0200790 // Das Alias ist in ein Array von Strings gespeichert. Alle
791 // Alias-Argument ($n, $* oder $n*) stehen an der jeweiligen Stelle als
792 // laufender Index im Array. An der Stelle werden die Argumente vom Alias
793 // eingefuegt, alle anderen Elemente werden in den output kopiert. Negative
794 // Zahlen stehen fuer $n*, d.h. alle Argument nach dem genannten.
795 // Bsp: ({"stecke ", 1, " in ", -2 })
MG Mud User88f12472016-06-24 23:31:02 +0200796 foreach (mixed a:alias)
797 {
798 if (!intp(a))
799 output += a;
800 else
801 {
802 if (a >= 0)
803 {
Zesstrafb4cc3d2019-05-06 21:16:30 +0200804 // Einzelnes Argument ($n). Argument anstelle von a einfuegen, falls
805 // genug angegeben wurden
MG Mud User88f12472016-06-24 23:31:02 +0200806 if (input_size > a)
807 output += input[a];
808 }
809 else
810 {
Zesstrafb4cc3d2019-05-06 21:16:30 +0200811 // Argumente ab n ($n*). Alle von a bis Ende einfuegen.
MG Mud User88f12472016-06-24 23:31:02 +0200812 a = -a;
813 if (input_size > a)
814 output += implode(input[a..]," ");
815 }
816 }
817 }
818 output = _single_spaces(output);
819 str = trim(output,TRIM_RIGHT);
820 if (show_processing>1)
821 printf("[%s]\n",str);
822 return str;
823}
824
825/** Behandelt alle Sonderfaelle der Eingabe des Spielers
826 Alle Befehle des Spielers, die nicht durch Objekte behandelt
827 werden sollen, werden hier erkannt und ausgefuehrt.
828 Dazu gehoert auch die Interpretation von Aliases und History-
829 befehlen.
830 \param[in] str string: Kommando des Spielers
831 \return auszufuehrendes Kommando
832 oder 0 fuer ein nicht interpretierbares Kommando
833 oder 1 fuer ein bereits durchgefuehrtes Kommando
834*/
835mixed modify_command(string str)
836{
837
838 if (extern_call() && previous_object() &&
839 (previous_object()!=this_object() || process_call()) )
840 {
841 return 0;
842 }
843
844 // Leerzeichen an den Enden abschneiden.
845 str = trim(str, TRIM_BOTH);
846
847 if (bb)
848 BBMASTER->BBWrite(trim(str,TRIM_RIGHT,"\n"), 0);
849
850 decay_average();
851 cmds_per_time+=10000;
852
853 unparsed_args[0]=unparsed_args[1]=unparsed_args[2]=unmodified="";
854
855 if (!sizeof(str)) return "";
856
857 // Kommando wird geparst
858 unmodified=parsecommand(str);
859
860 // Environment schonmal merken.
861 last_command_env=environment();
862
863 if (unmodified == "")
864 return "";
865 // Kommando in History merken, auch wenn es im Kommandoblock abgebrochen
866 // wird.
867 AddHistory(unmodified);
868
869 // pruefen, ob Kommandoblock gesetzt ist.
870 // (Fuer Magier mit mschau ein wird das ignoriert.)
871 // BTW: Es wird absichtlich nicht das Ergebnis der Closure zurueckgegeben,
872 // sonst wuerde man beliebigen Objekten nicht nur das Abbrechen, sondern
873 // auch das Aendern von Kommandos ermoeglichen.
874 if (disablecommands && !IS_LEARNING(ME) )
875 {
876 if (disablecommands[B_TIME] >= time()
877 && objectp(disablecommands[B_OBJECT]))
878 {
879 // disablecommands valid
880 // hart-kodierte Ausnameliste pruefen
881 if ( member(({"mrufe","mschau","bug","idee","typo","detail"}),
882 explode(str," ")[0]) == -1)
883 {
884 if (closurep(disablecommands[B_VALUE]))
885 {
886 if (funcall(disablecommands[B_VALUE],_return_args(unmodified)))
887 {
888 // Non-zero Closure-Ergebnis, Abbruch. Die gerufene Funktion ist
889 // fuer eine geeignete Meldung an den Spieler verantwortlich.
890 return 1;
891 }
892 }
893 // wenn Text, dann auch pruefen, ob das Kommandoverb in den Ausnahmen
894 // steht. (query_verb() geht leider hier noch nicht.)
895 else if (stringp(disablecommands[B_VALUE])
896 && member(disablecommands[B_EXCEPTIONS],
897 explode(str," ")[0]) == -1)
898 {
899 // meldung ausgeben...
900 tell_object(PL, disablecommands[B_VALUE]);
901 // und Ende...
902 return 1;
903 }
904 }
905 }
906 else disablecommands=0;
907 }
908
909 // Verfolger direkt ins Env reinholen.
910 if (remove_call_out("TakeFollowers")>=0)
911 catch(TakeFollowers();publish);
912
913 DelayPreparedSpells();
914
915 // Historyeintrag korrigieren
916 if (unmodified[0]=='^')
917 {
918 string *oldnew,pre,post;
919 if (sizeof(oldnew=explode(unmodified,"^"))>2)
920 {
921 int hist_idx = (hist_now-1)%hist_size;
922 sscanf(history[hist_idx],"%s"+oldnew[1]+"%s", pre, post);
923 unmodified = pre+oldnew[2]+post;
924 if (show_processing)
925 write("["+unmodified+"]\n");
926 // korrigiertes Kommando natuerlich auch in die History.
927 AddHistory(unmodified);
928 }
929 }
930
931 if( bb )
932 BBMASTER->BBWrite(" -> " + unmodified, 1);
933
934 if (show_processing>1)
935 printf("[%s]\n",unmodified);
936
937 mixed ret = _return_args(unmodified);
938
939 // wenn Spieler eingewilligt hat und die SyntaxDB geladen ist, Befehl
940 // dorthin melden.
941 if (syntaxdb)
942 {
943 if (!objectp(syntaxdb[0]))
944 syntaxdb[0] = find_object("/secure/syntaxdb");
945 if (syntaxdb[0])
946 catch(syntaxdb[0]->start_cmd(unmodified);nolog);
947 }
948 return ret;
949}
950
951static int do_list(string str)
952{
953 string *cmdlist;
954 int i;
955
956 if (!QueryProp(P_WANTS_TO_LEARN))
957 return 0;
958 cmdlist=old_explode(_unparsed_args()||"",";")-({ "" });
959 for (i=0;i<sizeof(cmdlist);i++)
960 {
961 cmdlist[i]=implode(old_explode(cmdlist[i]," ")-({}), " ");
962 if (show_processing)
963 write("["+cmdlist[i]+"]\n");
964 command(cmdlist[i]);
965 }
966 return 1;
967}
968
969//falls die aliasliste kaputt ist ...
970
971int unalias_all()
972{
Zesstrafb4cc3d2019-05-06 21:16:30 +0200973 if (IS_ELDER(this_interactive()))
974 {
975 aliases=([]);
Zesstra3fe70c62019-05-28 22:46:19 +0200976 merge_family_aliases(0,0);
Zesstrafb4cc3d2019-05-06 21:16:30 +0200977 }
MG Mud User88f12472016-06-24 23:31:02 +0200978 return 1;
979}
980
981object _query_last_command_env()
982{
983 return last_command_env;
984}
985
986int _query_show_alias_processing()
987{
988 return show_processing;
989}
990
991int _query_histmin()
992{
993 return histmin;
994}
995
996varargs void AddAction(mixed fun, mixed cmd, int flag, int lvl)
997{
998 int i;
999 mixed *cmds;
1000
1001 log_file( "ARCH/ADD_ACTION", sprintf(
1002 "%s:\n TO: %O TP: %O PO: %O\n fun: %O cmd: %O flag: %O lvl: %O",
1003 dtime(time()), this_object(), this_player(), previous_object(),
1004 fun, cmd, flag, lvl));
1005
1006 if (!(cmds=Query(P_LOCALCMDS))) cmds=({});
1007
1008 if (!pointerp(cmd)) cmd=({cmd});
1009
1010 for (i = sizeof(cmd)-1; i>=0; i--)
1011 cmds += ({({ cmd[i] , fun, flag, lvl})});
1012
1013 Set(P_LOCALCMDS, cmds);
1014}
1015
1016static int auswerten(mixed cmd, string str)
1017{
1018 if (closurep(cmd))
1019 return funcall(cmd,str);
1020 if (stringp(cmd))
1021 return call_other(this_object(),cmd,str);
1022 return 0;
1023}
1024
1025static varargs int __auswerten(string str, string intern)
1026{
1027 string verb;
1028 mixed *cmd, cmds;
1029 int i,ret,lvl,l,vl;
1030
1031 if (!intern)
1032 verb=query_verb();
1033 else
1034 verb=intern;
1035 lvl=query_wiz_level(ME);
1036 vl=sizeof(verb);
1037 cmds=QueryProp(P_LOCALCMDS);
1038
1039 for(i=sizeof(cmds)-1;i>=0;i--)
1040 {
1041 cmd=cmds[i],l=sizeof(cmd[0]);
1042 if (cmd[0]==verb[0..l-1] && cmd[3]<=lvl && (cmd[2]||vl==l) &&
1043 (ret=auswerten(cmd[1],str)))
1044 return ret;
1045 }
1046 // An dieser Stelle gibt es hier und vermutlich nirgendwo anders etwas, was
1047 // dieses Kommando als gueltig betrachtet. Wir informieren ggf. die
1048 // Syntax-DB. (Achtung: wenn jemand ne add_action() im Spielerobjekt
1049 // einbaut, die vor dieser eingetragen wird, ist die Annahme ggf. falsch.)
1050 // wenn Spieler eingewilligt hat und die SyntaxDB geladen ist, Befehl
1051 // dorthin melden.
1052 if (syntaxdb)
1053 {
1054 if (!objectp(syntaxdb[0]))
1055 syntaxdb[0] = find_object("/secure/syntaxdb");
1056 if (syntaxdb[0])
1057 catch(syntaxdb[0]->cmd_unsuccessful();nolog);
1058 }
1059
1060 return 0;
1061}
1062
1063public void syntax_log_ep(int type)
1064{
1065 // wenn Spieler eingewilligt hat und die SyntaxDB geladen ist, Befehl
1066 // dorthin melden.
1067 if (syntaxdb && syntaxdb[0])
1068 {
1069 catch(syntaxdb[0]->LogEP(type);nolog);
1070 }
1071}
1072
1073static mixed _query_localcmds()
1074{
1075 mixed *l;
1076
1077 l=Query(P_LOCALCMDS);
1078 if (!pointerp(l))
1079 l=({});
1080 return ({
1081 ({"ali","alias",0,0}),
1082 ({"alias","alias",0,0}),
1083 ({"unali","unalias",1,0}),
1084 ({"histmin","histmin",0,0}),
1085 ({"histlen","histlen",0,0}),
1086 ({"hist","show_hist",0,0}),
1087 ({"history","show_hist",0,0}),
1088 ({"do","do_list",0,LEARNER_LVL}),
1089 ({"ersetzungsanzeige","replacedisplay",0,0}),
1090 ({"syntaxsammlung","collect_cmds",0,0}),
1091 ({"fehlermeldung","set_errormessage",0,SEER_LVL}),
1092 })+l;
1093}
1094
1095static int collect_cmds(string cmd)
1096{
1097 if (!stringp(cmd))
1098 {
1099 _notify("Mit diesem Befehl kannst Du mithelfen, Syntaxen im MG zu "
1100 "verbessern. Wenn Du einverstanden bist, speichern wir "
1101 "anonym (d.h. ohne Deinen Charnamen), welche Deiner Befehle "
1102 "erfolgreich und nicht erfolgreich waren. Uebliche "
1103 "Kommunikationsbefehle werden dabei nicht gespeichert.",
1104 0);
1105 _notify("Mit 'syntaxsammlung ja' kannst Du die Speicherung einschalten, "
1106 "mit 'syntaxsammlung nein' kannst Du sie ausschalten.",0);
1107 _notify("Deine Befehle werden zur Zeit"
1108 + (QueryProp("_syntaxdb") ? " " : " NICHT ")
1109 + "gespeichert.", 0);
1110 }
1111 else if (cmd == "ja")
1112 {
1113 SetProp("_syntaxdb", 1);
1114 _notify("Ab jetzt werden Deine Befehle gespeichert. Vielen Dank!", 0);
1115 }
1116 else
1117 {
1118 SetProp("_syntaxdb", 0);
1119 _notify("Ab jetzt werden Deine Befehle NICHT gespeichert.", 0);
1120 }
1121 return 1;
1122}
1123
1124int _query_command_average()
1125{
1126 decay_average();
1127 return cmds_per_time;
1128}
1129
1130nomask void __set_bb(int flag) {
1131 if( previous_object()!=find_object(BBMASTER) || process_call() )
1132 return;
1133 bb=flag;
1134}
1135
1136
1137nomask public void countCmds( int type, string key )
1138{
1139 string tmp;
1140
1141 if ( this_player() != this_interactive()
1142 || this_interactive() != this_object()
1143 || member( cmd_types, type ) < 0 )
1144 return;
1145
1146 tmp = sprintf( "%d\n%s", type, key );
1147
1148 commands -= ({ tmp });
1149 commands += ({ tmp });
1150 commands = commands[0..max_commands-1];
1151}
1152
1153
1154nomask public string *getCmds()
1155{
1156 string *tmp;
1157
1158 if ( previous_object() != find_object(BBMASTER) )
1159 return ({});
1160
1161 tmp = commands;
1162 commands = ({});
1163
1164 return tmp;
1165}
1166
1167/*
1168 * Force the monster to do a command. The force_us() function isn't
1169 * always good, because it checks the level of the caller, and this function
1170 * can be called by a room.
1171 */
1172int command_me(string cmd)
1173{
1174 if (IS_LEARNER(ME))
1175 {
1176 if (!this_interactive() || !previous_object())
1177 return 0;
1178 if( geteuid(ME)!=geteuid(this_interactive())
1179 || geteuid(ME)!=geteuid(previous_object()) )
1180 {
1181 if( query_wiz_level(ME)<query_wiz_level(previous_object()))
1182 tell_object(ME,previous_object()->name()+" zwingt Dich zu: "
1183 + cmd + ".\n");
1184 else
1185 {
1186 tell_object(ME,previous_object()->name()
1187 + " versucht, Dich zu " + cmd + " zu zwingen.\n" );
1188 return 0;
1189 }
1190 }
1191 }
1192 return command(cmd);
1193}
1194
1195
1196static mixed _query_p_lib_disablecommands() {
1197 // abgelaufen oder Objekt zerstoert? Weg damit.
1198 if (pointerp(disablecommands)
1199 && (disablecommands[B_TIME] < time()
1200 || !objectp(disablecommands[B_OBJECT])) )
1201 return(disablecommands = 0);
1202
1203 // sonst Kopie zurueck (copy(0) geht)
1204 return(copy(disablecommands));
1205}
1206
1207static mixed _set_p_lib_disablecommands(mixed data) {
1208
1209 // setzendes Objekt ermitteln, da diese Funktion nur per SetProp() gerufen
1210 // werden sollte (!), ist das PO(1);
1211 object origin = previous_object(1);
1212 // wenn nicht existent, direkt abbruch
1213 if (!objectp(origin))
1214 return _query_p_lib_disablecommands();
1215
1216 // Prop loeschen? Explizit loeschen darf jeder, allerdings nicht direkt
1217 // ungeprueft ueberschreiben.
1218 if (!data) {
1219 return (disablecommands = 0 );
1220 }
1221 // mal direkt buggen bei falschen Datentyp, damits auffaellt.
1222 if (!pointerp(data) || sizeof(data) < 2 || !intp(data[0])
1223 || (!stringp(data[1]) && !closurep(data[1]))
1224 || (sizeof(data) >= 3 && !pointerp(data[2])) )
1225 raise_error(sprintf(
1226 "Wrong data type for P_DISABLE_COMMANDS. Expected Array with "
1227 "2 or 3 elements (int, string|closure, [string*]), got %.25O\n",
1228 data));
1229
1230 // Wenn abgelaufen oder gleiches Objekt wie letztes Mal: eintragen.
1231 if (!disablecommands || (disablecommands[B_TIME] < time()
1232 || !objectp(disablecommands[B_OBJECT])
1233 || disablecommands[B_OBJECT] == origin) ) {
1234 // Loggen nur, wenn eine Closure eingetragen wird. Reduziert den
1235 // Logscroll und Strings haben deutlich weniger Missbrauchspotential.
1236 if (closurep(data[1])) {
1237 CBLOG(sprintf("[%s] CB gesetzt von %O, gueltig bis %s, Daten: %O\n",
1238 strftime("%Y%m%d-%H:%M:%S"),origin,
1239 strftime("%Y%m%d-%H:%M:%S",data[0]),
1240 (stringp(data[1]) ? regreplace(data[1],"\n","\\n",0)
1241 : data[1])));
1242 }
1243 if (sizeof(data)+1 <= B_EXCEPTIONS)
1244 disablecommands = ({ origin, data[0], data[1], ({}) });
1245 else
1246 disablecommands = ({ origin, data[0], data[1], data[2] });
1247 return(copy(disablecommands));
1248 }
1249
1250 return(_query_p_lib_disablecommands());
1251}
1252
1253static mixed _set__syntaxdb(mixed v)
1254{
1255 Set("_syntaxdb", v, F_VALUE);
1256 if (v)
1257 syntaxdb = ({find_object("/secure/syntaxdb")});
1258 else
1259 syntaxdb = 0;
1260 return QueryProp("_syntaxdb");
1261}
1262