blob: 36fee46ea6011cce7e14c7435cd49a4589fc6f35 [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
699 Eigentlich muesste hier noch die Umwandlung der Sonderzeichen
700 verschiedener Zeichensaetze mit convert_charset gemacht werden,
701 aber noch gibt es keine Moeglichkeit, den vom Spieler genutzten
702 Zeichensatz zu identifizieren.
703 \param[in] str string - Kommando des Spielers
704 \return interpretiertes Alias bzw. korrektes Kommando aus der History
705*/
706private string parsecommand(string str)
707{
708 if (str[0]=='\\')
709 {
710 // Kommando soll nicht interpretiert werden
711 return str[1..];
712 }
713 else if (str[0]=='&')
714 {
715 // Kommando aus der History
716 string cmd = str[1..];
717 int cmd_size = sizeof(cmd);
718 int cmd_found = 0;
719 if (cmd_size)
720 {
721 // Test ob &<text> etwas findet
722 for (int i=0;i<hist_size-1 && !cmd_found;i++)
723 {
724 int idx = (hist_size-i+hist_now-1)%hist_size;
725 if (history[idx][0..cmd_size-1]==cmd)
726 {
727 str = history[idx];
728 cmd_found = 1;
729 }
730 if (cmd_found)
731 {
732 if (show_processing)
733 printf("[%s]\n",str);
734 }
735 }
736 }
737 if (!cmd_found)
738 {
739 // Test, ob &<nr> klappt
740 int nummer;
741 if (str=="&&")
742 str = "&-0";
743 if (sscanf(str,"&%d",nummer))
744 {
745 if (nummer<0 || (!nummer && str[1]=='-'))
746 {
747 if (nummer<-(hist_size-1))
748 nummer=-1;
749 else
750 nummer=(hist_now+nummer-1+hist_size)%hist_size;
751 }
752 else
753 {
754 if (nummer>hist_now || hist_now-nummer>hist_size)
755 nummer=-1;
756 else
757 nummer=nummer%hist_size;
758 }
759 if (nummer<0
760 || ( (cmd=history[nummer]) =="\n\n") )
761 notify_fail("Der Befehl ist nicht in der History!\n");
762 else
763 {
764 str = cmd;
765 if (show_processing)
766 printf("[%s]\n",str);
767 }
768 }
769 }
770 }
771 switch (str)
772 {
773 case "n": return "norden";
774 case "s": return "sueden";
775 case "w": return "westen";
776 case "o": return "osten";
777 case "nw": return "nordwesten";
778 case "sw": return "suedwesten";
779 case "so": return "suedosten";
780 case "no": return "nordosten";
781 case "ob": return "oben";
782 case "u": return "unten";
783 }
784 // Test auf Alias
785 string output = "";
786 string* input = explode(str," ");
787 int input_size = sizeof(input);
Zesstrafb4cc3d2019-05-06 21:16:30 +0200788 mixed alias = active_aliases[input[0]];
MG Mud User88f12472016-06-24 23:31:02 +0200789 if (!alias)
790 return str;
Zesstrafb4cc3d2019-05-06 21:16:30 +0200791 // Das Alias ist in ein Array von Strings gespeichert. Alle
792 // Alias-Argument ($n, $* oder $n*) stehen an der jeweiligen Stelle als
793 // laufender Index im Array. An der Stelle werden die Argumente vom Alias
794 // eingefuegt, alle anderen Elemente werden in den output kopiert. Negative
795 // Zahlen stehen fuer $n*, d.h. alle Argument nach dem genannten.
796 // Bsp: ({"stecke ", 1, " in ", -2 })
MG Mud User88f12472016-06-24 23:31:02 +0200797 foreach (mixed a:alias)
798 {
799 if (!intp(a))
800 output += a;
801 else
802 {
803 if (a >= 0)
804 {
Zesstrafb4cc3d2019-05-06 21:16:30 +0200805 // Einzelnes Argument ($n). Argument anstelle von a einfuegen, falls
806 // genug angegeben wurden
MG Mud User88f12472016-06-24 23:31:02 +0200807 if (input_size > a)
808 output += input[a];
809 }
810 else
811 {
Zesstrafb4cc3d2019-05-06 21:16:30 +0200812 // Argumente ab n ($n*). Alle von a bis Ende einfuegen.
MG Mud User88f12472016-06-24 23:31:02 +0200813 a = -a;
814 if (input_size > a)
815 output += implode(input[a..]," ");
816 }
817 }
818 }
819 output = _single_spaces(output);
820 str = trim(output,TRIM_RIGHT);
821 if (show_processing>1)
822 printf("[%s]\n",str);
823 return str;
824}
825
826/** Behandelt alle Sonderfaelle der Eingabe des Spielers
827 Alle Befehle des Spielers, die nicht durch Objekte behandelt
828 werden sollen, werden hier erkannt und ausgefuehrt.
829 Dazu gehoert auch die Interpretation von Aliases und History-
830 befehlen.
831 \param[in] str string: Kommando des Spielers
832 \return auszufuehrendes Kommando
833 oder 0 fuer ein nicht interpretierbares Kommando
834 oder 1 fuer ein bereits durchgefuehrtes Kommando
835*/
836mixed modify_command(string str)
837{
838
839 if (extern_call() && previous_object() &&
840 (previous_object()!=this_object() || process_call()) )
841 {
842 return 0;
843 }
844
845 // Leerzeichen an den Enden abschneiden.
846 str = trim(str, TRIM_BOTH);
847
848 if (bb)
849 BBMASTER->BBWrite(trim(str,TRIM_RIGHT,"\n"), 0);
850
851 decay_average();
852 cmds_per_time+=10000;
853
854 unparsed_args[0]=unparsed_args[1]=unparsed_args[2]=unmodified="";
855
856 if (!sizeof(str)) return "";
857
858 // Kommando wird geparst
859 unmodified=parsecommand(str);
860
861 // Environment schonmal merken.
862 last_command_env=environment();
863
864 if (unmodified == "")
865 return "";
866 // Kommando in History merken, auch wenn es im Kommandoblock abgebrochen
867 // wird.
868 AddHistory(unmodified);
869
870 // pruefen, ob Kommandoblock gesetzt ist.
871 // (Fuer Magier mit mschau ein wird das ignoriert.)
872 // BTW: Es wird absichtlich nicht das Ergebnis der Closure zurueckgegeben,
873 // sonst wuerde man beliebigen Objekten nicht nur das Abbrechen, sondern
874 // auch das Aendern von Kommandos ermoeglichen.
875 if (disablecommands && !IS_LEARNING(ME) )
876 {
877 if (disablecommands[B_TIME] >= time()
878 && objectp(disablecommands[B_OBJECT]))
879 {
880 // disablecommands valid
881 // hart-kodierte Ausnameliste pruefen
882 if ( member(({"mrufe","mschau","bug","idee","typo","detail"}),
883 explode(str," ")[0]) == -1)
884 {
885 if (closurep(disablecommands[B_VALUE]))
886 {
887 if (funcall(disablecommands[B_VALUE],_return_args(unmodified)))
888 {
889 // Non-zero Closure-Ergebnis, Abbruch. Die gerufene Funktion ist
890 // fuer eine geeignete Meldung an den Spieler verantwortlich.
891 return 1;
892 }
893 }
894 // wenn Text, dann auch pruefen, ob das Kommandoverb in den Ausnahmen
895 // steht. (query_verb() geht leider hier noch nicht.)
896 else if (stringp(disablecommands[B_VALUE])
897 && member(disablecommands[B_EXCEPTIONS],
898 explode(str," ")[0]) == -1)
899 {
900 // meldung ausgeben...
901 tell_object(PL, disablecommands[B_VALUE]);
902 // und Ende...
903 return 1;
904 }
905 }
906 }
907 else disablecommands=0;
908 }
909
910 // Verfolger direkt ins Env reinholen.
911 if (remove_call_out("TakeFollowers")>=0)
912 catch(TakeFollowers();publish);
913
914 DelayPreparedSpells();
915
916 // Historyeintrag korrigieren
917 if (unmodified[0]=='^')
918 {
919 string *oldnew,pre,post;
920 if (sizeof(oldnew=explode(unmodified,"^"))>2)
921 {
922 int hist_idx = (hist_now-1)%hist_size;
923 sscanf(history[hist_idx],"%s"+oldnew[1]+"%s", pre, post);
924 unmodified = pre+oldnew[2]+post;
925 if (show_processing)
926 write("["+unmodified+"]\n");
927 // korrigiertes Kommando natuerlich auch in die History.
928 AddHistory(unmodified);
929 }
930 }
931
932 if( bb )
933 BBMASTER->BBWrite(" -> " + unmodified, 1);
934
935 if (show_processing>1)
936 printf("[%s]\n",unmodified);
937
938 mixed ret = _return_args(unmodified);
939
940 // wenn Spieler eingewilligt hat und die SyntaxDB geladen ist, Befehl
941 // dorthin melden.
942 if (syntaxdb)
943 {
944 if (!objectp(syntaxdb[0]))
945 syntaxdb[0] = find_object("/secure/syntaxdb");
946 if (syntaxdb[0])
947 catch(syntaxdb[0]->start_cmd(unmodified);nolog);
948 }
949 return ret;
950}
951
952static int do_list(string str)
953{
954 string *cmdlist;
955 int i;
956
957 if (!QueryProp(P_WANTS_TO_LEARN))
958 return 0;
959 cmdlist=old_explode(_unparsed_args()||"",";")-({ "" });
960 for (i=0;i<sizeof(cmdlist);i++)
961 {
962 cmdlist[i]=implode(old_explode(cmdlist[i]," ")-({}), " ");
963 if (show_processing)
964 write("["+cmdlist[i]+"]\n");
965 command(cmdlist[i]);
966 }
967 return 1;
968}
969
970//falls die aliasliste kaputt ist ...
971
972int unalias_all()
973{
Zesstrafb4cc3d2019-05-06 21:16:30 +0200974 if (IS_ELDER(this_interactive()))
975 {
976 aliases=([]);
Zesstra3fe70c62019-05-28 22:46:19 +0200977 merge_family_aliases(0,0);
Zesstrafb4cc3d2019-05-06 21:16:30 +0200978 }
MG Mud User88f12472016-06-24 23:31:02 +0200979 return 1;
980}
981
982object _query_last_command_env()
983{
984 return last_command_env;
985}
986
987int _query_show_alias_processing()
988{
989 return show_processing;
990}
991
992int _query_histmin()
993{
994 return histmin;
995}
996
997varargs void AddAction(mixed fun, mixed cmd, int flag, int lvl)
998{
999 int i;
1000 mixed *cmds;
1001
1002 log_file( "ARCH/ADD_ACTION", sprintf(
1003 "%s:\n TO: %O TP: %O PO: %O\n fun: %O cmd: %O flag: %O lvl: %O",
1004 dtime(time()), this_object(), this_player(), previous_object(),
1005 fun, cmd, flag, lvl));
1006
1007 if (!(cmds=Query(P_LOCALCMDS))) cmds=({});
1008
1009 if (!pointerp(cmd)) cmd=({cmd});
1010
1011 for (i = sizeof(cmd)-1; i>=0; i--)
1012 cmds += ({({ cmd[i] , fun, flag, lvl})});
1013
1014 Set(P_LOCALCMDS, cmds);
1015}
1016
1017static int auswerten(mixed cmd, string str)
1018{
1019 if (closurep(cmd))
1020 return funcall(cmd,str);
1021 if (stringp(cmd))
1022 return call_other(this_object(),cmd,str);
1023 return 0;
1024}
1025
1026static varargs int __auswerten(string str, string intern)
1027{
1028 string verb;
1029 mixed *cmd, cmds;
1030 int i,ret,lvl,l,vl;
1031
1032 if (!intern)
1033 verb=query_verb();
1034 else
1035 verb=intern;
1036 lvl=query_wiz_level(ME);
1037 vl=sizeof(verb);
1038 cmds=QueryProp(P_LOCALCMDS);
1039
1040 for(i=sizeof(cmds)-1;i>=0;i--)
1041 {
1042 cmd=cmds[i],l=sizeof(cmd[0]);
1043 if (cmd[0]==verb[0..l-1] && cmd[3]<=lvl && (cmd[2]||vl==l) &&
1044 (ret=auswerten(cmd[1],str)))
1045 return ret;
1046 }
1047 // An dieser Stelle gibt es hier und vermutlich nirgendwo anders etwas, was
1048 // dieses Kommando als gueltig betrachtet. Wir informieren ggf. die
1049 // Syntax-DB. (Achtung: wenn jemand ne add_action() im Spielerobjekt
1050 // einbaut, die vor dieser eingetragen wird, ist die Annahme ggf. falsch.)
1051 // wenn Spieler eingewilligt hat und die SyntaxDB geladen ist, Befehl
1052 // dorthin melden.
1053 if (syntaxdb)
1054 {
1055 if (!objectp(syntaxdb[0]))
1056 syntaxdb[0] = find_object("/secure/syntaxdb");
1057 if (syntaxdb[0])
1058 catch(syntaxdb[0]->cmd_unsuccessful();nolog);
1059 }
1060
1061 return 0;
1062}
1063
1064public void syntax_log_ep(int type)
1065{
1066 // wenn Spieler eingewilligt hat und die SyntaxDB geladen ist, Befehl
1067 // dorthin melden.
1068 if (syntaxdb && syntaxdb[0])
1069 {
1070 catch(syntaxdb[0]->LogEP(type);nolog);
1071 }
1072}
1073
1074static mixed _query_localcmds()
1075{
1076 mixed *l;
1077
1078 l=Query(P_LOCALCMDS);
1079 if (!pointerp(l))
1080 l=({});
1081 return ({
1082 ({"ali","alias",0,0}),
1083 ({"alias","alias",0,0}),
1084 ({"unali","unalias",1,0}),
1085 ({"histmin","histmin",0,0}),
1086 ({"histlen","histlen",0,0}),
1087 ({"hist","show_hist",0,0}),
1088 ({"history","show_hist",0,0}),
1089 ({"do","do_list",0,LEARNER_LVL}),
1090 ({"ersetzungsanzeige","replacedisplay",0,0}),
1091 ({"syntaxsammlung","collect_cmds",0,0}),
1092 ({"fehlermeldung","set_errormessage",0,SEER_LVL}),
1093 })+l;
1094}
1095
1096static int collect_cmds(string cmd)
1097{
1098 if (!stringp(cmd))
1099 {
1100 _notify("Mit diesem Befehl kannst Du mithelfen, Syntaxen im MG zu "
1101 "verbessern. Wenn Du einverstanden bist, speichern wir "
1102 "anonym (d.h. ohne Deinen Charnamen), welche Deiner Befehle "
1103 "erfolgreich und nicht erfolgreich waren. Uebliche "
1104 "Kommunikationsbefehle werden dabei nicht gespeichert.",
1105 0);
1106 _notify("Mit 'syntaxsammlung ja' kannst Du die Speicherung einschalten, "
1107 "mit 'syntaxsammlung nein' kannst Du sie ausschalten.",0);
1108 _notify("Deine Befehle werden zur Zeit"
1109 + (QueryProp("_syntaxdb") ? " " : " NICHT ")
1110 + "gespeichert.", 0);
1111 }
1112 else if (cmd == "ja")
1113 {
1114 SetProp("_syntaxdb", 1);
1115 _notify("Ab jetzt werden Deine Befehle gespeichert. Vielen Dank!", 0);
1116 }
1117 else
1118 {
1119 SetProp("_syntaxdb", 0);
1120 _notify("Ab jetzt werden Deine Befehle NICHT gespeichert.", 0);
1121 }
1122 return 1;
1123}
1124
1125int _query_command_average()
1126{
1127 decay_average();
1128 return cmds_per_time;
1129}
1130
1131nomask void __set_bb(int flag) {
1132 if( previous_object()!=find_object(BBMASTER) || process_call() )
1133 return;
1134 bb=flag;
1135}
1136
1137
1138nomask public void countCmds( int type, string key )
1139{
1140 string tmp;
1141
1142 if ( this_player() != this_interactive()
1143 || this_interactive() != this_object()
1144 || member( cmd_types, type ) < 0 )
1145 return;
1146
1147 tmp = sprintf( "%d\n%s", type, key );
1148
1149 commands -= ({ tmp });
1150 commands += ({ tmp });
1151 commands = commands[0..max_commands-1];
1152}
1153
1154
1155nomask public string *getCmds()
1156{
1157 string *tmp;
1158
1159 if ( previous_object() != find_object(BBMASTER) )
1160 return ({});
1161
1162 tmp = commands;
1163 commands = ({});
1164
1165 return tmp;
1166}
1167
1168/*
1169 * Force the monster to do a command. The force_us() function isn't
1170 * always good, because it checks the level of the caller, and this function
1171 * can be called by a room.
1172 */
1173int command_me(string cmd)
1174{
1175 if (IS_LEARNER(ME))
1176 {
1177 if (!this_interactive() || !previous_object())
1178 return 0;
1179 if( geteuid(ME)!=geteuid(this_interactive())
1180 || geteuid(ME)!=geteuid(previous_object()) )
1181 {
1182 if( query_wiz_level(ME)<query_wiz_level(previous_object()))
1183 tell_object(ME,previous_object()->name()+" zwingt Dich zu: "
1184 + cmd + ".\n");
1185 else
1186 {
1187 tell_object(ME,previous_object()->name()
1188 + " versucht, Dich zu " + cmd + " zu zwingen.\n" );
1189 return 0;
1190 }
1191 }
1192 }
1193 return command(cmd);
1194}
1195
1196
1197static mixed _query_p_lib_disablecommands() {
1198 // abgelaufen oder Objekt zerstoert? Weg damit.
1199 if (pointerp(disablecommands)
1200 && (disablecommands[B_TIME] < time()
1201 || !objectp(disablecommands[B_OBJECT])) )
1202 return(disablecommands = 0);
1203
1204 // sonst Kopie zurueck (copy(0) geht)
1205 return(copy(disablecommands));
1206}
1207
1208static mixed _set_p_lib_disablecommands(mixed data) {
1209
1210 // setzendes Objekt ermitteln, da diese Funktion nur per SetProp() gerufen
1211 // werden sollte (!), ist das PO(1);
1212 object origin = previous_object(1);
1213 // wenn nicht existent, direkt abbruch
1214 if (!objectp(origin))
1215 return _query_p_lib_disablecommands();
1216
1217 // Prop loeschen? Explizit loeschen darf jeder, allerdings nicht direkt
1218 // ungeprueft ueberschreiben.
1219 if (!data) {
1220 return (disablecommands = 0 );
1221 }
1222 // mal direkt buggen bei falschen Datentyp, damits auffaellt.
1223 if (!pointerp(data) || sizeof(data) < 2 || !intp(data[0])
1224 || (!stringp(data[1]) && !closurep(data[1]))
1225 || (sizeof(data) >= 3 && !pointerp(data[2])) )
1226 raise_error(sprintf(
1227 "Wrong data type for P_DISABLE_COMMANDS. Expected Array with "
1228 "2 or 3 elements (int, string|closure, [string*]), got %.25O\n",
1229 data));
1230
1231 // Wenn abgelaufen oder gleiches Objekt wie letztes Mal: eintragen.
1232 if (!disablecommands || (disablecommands[B_TIME] < time()
1233 || !objectp(disablecommands[B_OBJECT])
1234 || disablecommands[B_OBJECT] == origin) ) {
1235 // Loggen nur, wenn eine Closure eingetragen wird. Reduziert den
1236 // Logscroll und Strings haben deutlich weniger Missbrauchspotential.
1237 if (closurep(data[1])) {
1238 CBLOG(sprintf("[%s] CB gesetzt von %O, gueltig bis %s, Daten: %O\n",
1239 strftime("%Y%m%d-%H:%M:%S"),origin,
1240 strftime("%Y%m%d-%H:%M:%S",data[0]),
1241 (stringp(data[1]) ? regreplace(data[1],"\n","\\n",0)
1242 : data[1])));
1243 }
1244 if (sizeof(data)+1 <= B_EXCEPTIONS)
1245 disablecommands = ({ origin, data[0], data[1], ({}) });
1246 else
1247 disablecommands = ({ origin, data[0], data[1], data[2] });
1248 return(copy(disablecommands));
1249 }
1250
1251 return(_query_p_lib_disablecommands());
1252}
1253
1254static mixed _set__syntaxdb(mixed v)
1255{
1256 Set("_syntaxdb", v, F_VALUE);
1257 if (v)
1258 syntaxdb = ({find_object("/secure/syntaxdb")});
1259 else
1260 syntaxdb = 0;
1261 return QueryProp("_syntaxdb");
1262}
1263