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