blob: 56c9b89fc75210d8715f18d1568e6c09dba6a0c9 [file] [log] [blame]
Zesstra25387d92017-02-03 20:20:56 +01001/* =========================================================================
2
Arathorn4c2c85d2020-03-09 23:12:26 +01003 Ein Mailobjekt fuer Morgengrauen.
Zesstra25387d92017-02-03 20:20:56 +01004 (C) 1993-97 Loco@MG. Unter Verwendung des std/post-codes von Jof
Arathorn4c2c85d2020-03-09 23:12:26 +01005
Zesstra25387d92017-02-03 20:20:56 +01006 Verwendung ausserhalb von Morgengrauen ist gestattet unter folgenden
7 Bedingungen:
8 - Benutzung erfolgt auf eigene Gefahr. Jegliche Verantwortung wird
9 abgelehnt.
10 - Auch in veraenderten oder abgeleiteten Objekten muss ein Hinweis auf
11 die Herkunft erhalten bleiben.
12 - Bitte Loco Bescheid sagen.
13 Ein Update-Service besteht nicht. Diese Lizenz kann jederzeit
14 zurueckgezogen werden.
15
16 Letzte Aenderungen:
17 190494 [Loco] mail <spieler> fuehrt nicht ins mailmenue anschliessend.
18 280494 [Loco] .mailrc
19 020594 [Loco] system.mailrc, aliase anzeigen, Text retten, selfdestruct
20 in reset() im Fehlerfall, kleinere bugfixes
21 070794 [Loco] Kleinigkeiten (bugfixes und Optimierungen), '+'
22 231195 [Loco] Bereiche bei Speichern und Loeschen
23 171295 [Loco] Bereiche bei forward. Stapelweise Kleinigkeiten.
24 191295 [Loco] Kleinere Zeitoptimierungen, teilweise schiefgelaufen und
25 deswegen doch nicht, minor bugfixes.
26 190295 [Loco] keine folderlist beim hochstarten
27 110696 [Loco] Forwardserver-Unterstuetzung (.forward-aehnlich)
28 031296 [Loco] major update:
29 Erlaube in der Blueprint nichtinteraktives Versenden
30 vorbereiteter mails (z.B. fuer mpa: versende artikel);
31 Zeitoptimierungen durch effektiveres caching;
32 '-';
33 Einige optische Aenderungen;
34 Warnung bei grossen mailfiles;
35 Unterstuetzung von bcc's;
36 d,m,f,s erlauben Listen;
37 Abkuerzungen und '-' bei Folderargumenten
38 080297 [Loco] Zeitoptimierungen, interne Aenderungen, Bugfixes
39 280103 [Muadib]Silentflag
40 020304 [Vanion]In do_mail() wird jetzt M_NOCHECK gemovet, sonst hat ein
41 Mailer eines Spielers, der voll ist, kein Environment.
42 100105 [Zook] Magier mit Level >= 26 bekommen erst spaeter eine
Arathorn4c2c85d2020-03-09 23:12:26 +010043 Mitteilung (Gebietswartung insb. f. Regionsmagier
44 erfordert schlicht ein groesseres Postfach).
45
Zesstra25387d92017-02-03 20:20:56 +010046----------------------------------------------------------------------------
47
48Aufrufe von aussen zur Benutzung:
49
Arathorn4c2c85d2020-03-09 23:12:26 +010050a) im geklonten Objekt:
Zesstra25387d92017-02-03 20:20:56 +010051 obj->do_mail() interaktives Mailmenue
52 obj->do_mail(empf) 'halbinteraktiv': _eine_ mail, an Empfaenger str
53 Objekt zerstoert sich nach Gebrauch selbst.
Arathorn4c2c85d2020-03-09 23:12:26 +010054 Bei obj->do_mail("-silent") wird der Inhalt des Mailfolders nicht
Zesstra25387d92017-02-03 20:20:56 +010055 aufgelistet. Ansonsten wie obj->do_mail()
Arathorn4c2c85d2020-03-09 23:12:26 +010056
Zesstra25387d92017-02-03 20:20:56 +010057b) in der blueprint: nur non-interactive
58 obj->do_mail(empf,titel,text)
Arathorn4c2c85d2020-03-09 23:12:26 +010059 sendet mail mit Titel titel und Inhalt text an Empfaenger empf.
Zesstra25387d92017-02-03 20:20:56 +010060 Aliase etc. werden von this_interactive() genommen.
61 Nur fuer 'trusted objects' zugelassen, siehe #define TRUSTED
62
63=========================================================================== */
64
65#include "post.h"
66
Zesstraafd72e02017-02-03 20:32:56 +010067inherit "/std/thing";
Zesstra25387d92017-02-03 20:20:56 +010068//inherit "std/more"; // wird vom nedit inherited
69inherit NEDIT;
70
71#include <properties.h>
72#include <language.h>
73#include <config.h>
74#include <mail.h>
75#include <wizlevels.h>
76#include <moving.h>
77#include <defines.h>
78#include <input_to.h>
79
80#undef DEBUG
81
82#define TRUSTED(o) (objectp(o) && BLUE_NAME(o)=="/obj/mpa")
83// (geteuid(o)=="p:service"|| \
84// geteuid(o)==geteuid(this_interactive())))
85
Zesstraafd72e02017-02-03 20:32:56 +010086#define MAILFILE(name) (MAILPATH+name[0..0]+"/"+name)
Zesstra25387d92017-02-03 20:20:56 +010087#define MAILFILEO(name) (MAILFILE(name)+".o")
88#define MAILDEMON0297 // Maildemon-Version 8.Feb.97 vorhanden?
89
90#define IS_NUMBER(n) (stringp(n) && sizeof(n) && n[0]>='0' && n[0]<='9')
91
92#ifdef DEBUG
93#define DEBUGVAR(x) if(find_player("tiamak")) tell_object(find_player("tiamak"),sprintf("Value of x is %O\n",x))
94#else
95#define DEBUGVAR(x)
96#endif
97
98// Zaehlung: akt_nr ab 1, akt_folder ab 0
99
100static string subject, message, receiver, sender, *carbon;
101#ifdef MAIL_SUPPORT_BCC
102static string* blindcarbon;
103#endif
104static string name, office_name;
105static int done, akt_folder, i, akt_nr, directflag;
106static int folder_size,folder_date; // cacheverwaltung
107static mapping aliases;
108
109mixed *folders;
110
111// Prototypen, die nun mal gebraucht werden
112
113static varargs void SendMail(string text,int flag);
114static void input();
115static mixed process_names(mixed s);
116static void get_carbon_copy(string str);
117static varargs string* send_mail(mixed back);
118string * unify_array(string * a);
119static mapping Read_mailrc(string file);
120static varargs void update(int directflag,int nocondflag);
Arathorn4c2c85d2020-03-09 23:12:26 +0100121static varargs void ListContent(int limit);
Zesstra25387d92017-02-03 20:20:56 +0100122string GetFolderName(mixed fol);
123static void LagWarning();
124string GetReTitle(string s);
125static string Message2string(int nr);
126int * GetNumbers(mixed s);
127
Zesstra93769582019-11-29 00:32:59 +0100128protected void create() {
129 ::create();
Zesstra25387d92017-02-03 20:20:56 +0100130 seteuid(getuid());
131 SetProp(P_IDS,({"mailer"}));
132 SetProp(P_NAME,"mailer");
133 office_name="Morgengrauens Post";
134 akt_folder=-1;
135 folder_size=folder_date=-42;
136 SetProp(P_NODROP,1);
137 SetProp(P_SHORT,0);
138 SetProp(P_WEIGHT,0);
Arathorn4c2c85d2020-03-09 23:12:26 +0100139}
Zesstra25387d92017-02-03 20:20:56 +0100140
141
Zesstra93769582019-11-29 00:32:59 +0100142public varargs void init(object origin) {
Zesstra25387d92017-02-03 20:20:56 +0100143 (::init());
144 init_rescue();
145 add_action("postneustart","post");
146 add_action("postneustart","mail");
147}
148
149
150void reset() {
151 object pl;
152 (::reset());
153 if (!name) {remove();return;}
154 pl=find_player(name);
155 if (!pl || environment()!=pl) {remove();return;}
156 if (nedittext && !query_input_pending(pl)) {
157 tell_object(pl,"\
158*** Hoppla! Du hast noch einen nicht fertiggeschriebenen Brief!\n\
159*** Mit ~r kannst Du weiterschreiben.\n");
160 return;
161 }
162 if (query_input_pending(pl)!=this_object())
163 {remove();return;}
164}
165
166
167mixed postneustart() {
168 if (!this_interactive() || name!=geteuid(this_interactive())
169 || query_input_pending(this_interactive())
170 || this_interactive()!=this_player()) return 0;
171 write("Und weiter gehts...\n");
172 if (nedittext) return RescueText();
173 return input();
174}
175
176
177string SetOfficeName(string n) {
178 return office_name=n;
179}
180
181
182static varargs void write_mail(mixed str, string std_subject, string text) {
183 string str2;
184 int h;
Arathorn4c2c85d2020-03-09 23:12:26 +0100185
Zesstra25387d92017-02-03 20:20:56 +0100186 carbon=process_names(str);
Arathorn4c2c85d2020-03-09 23:12:26 +0100187 if (!sizeof(carbon)) {
Zesstra25387d92017-02-03 20:20:56 +0100188 write("Kein Empfaenger angegeben!\n"),(directflag?remove():input());
189 return;
190 }
191 write("Empfaenger: "+implode(map(carbon,#'capitalize/*'*/),", ")+"\n");
192 str=carbon[0];
193 if (sizeof(carbon)>=2) carbon=carbon[1..<1];
194 else carbon=0;
195 if ((str2=str) && str2!="" && str2[0]=='\\') str2=str2[1..];
196 if (!str) { write("WEM willst Du schreiben?\n"),(directflag?remove():input()); return;
197 }
198 if (!master()->find_userinfo(str2) && member(str2,'@')==-1)
199 {
200 write("Mit dem Namen gibt es hier niemanden.\n"),(directflag?remove():input());
201 return;
202 }
Arathorn4c2c85d2020-03-09 23:12:26 +0100203
Zesstra25387d92017-02-03 20:20:56 +0100204 receiver=str;
205
206 if (text) {
207 subject=std_subject;
208 return SendMail(text,1); // flag 1: keine CC's bitte.
209 }
210
211 //write("Titel");
212 //if (std_subject) write(" ("+std_subject+")");
213 //write(": ");
214 string pr;
215 if (std_subject) pr = "Titel ("+std_subject+"): ";
216 else pr = "Titel: ";
217 subject=std_subject;
218 input_to("get_subject",INPUT_PROMPT,pr);
219 return;
220}
221
222
223static varargs void get_subject(string str,string pretext) {
224 DEBUGVAR(str);
225 DEBUGVAR(subject);
226 if ((!str||str=="") && !subject)
227 {
228 input_to("get_subject",INPUT_PROMPT,"Titel (Abbrechen mit ~q): ");
229 return;
230 }
231 if (str=="~q"||str=="~Q") return SendMail(0); // entspricht Abbruch im Editor.
232 if (str && str!="") subject=str;
233 write("Bitte gib jetzt Deine Nachricht an:\n\
234** oder . wenn fertig, ~q fuer Abbruch, ~h fuer eine Hilfsseite\n");
235 nedit("SendMail",pretext);
236}
237
238
239static varargs void SendMail(string text,int flag) {
240 // flag: 1 = keine CC abfragen.
241 if (!text) {
242 write("Abbruch! Brief landet im Reisswolf.\n");
243 if (directflag) {remove(); return;
244 }
Arathorn4c2c85d2020-03-09 23:12:26 +0100245
Zesstra25387d92017-02-03 20:20:56 +0100246 subject=receiver=carbon=message=0;
247 return input();
248 }
249 message=text;
250 if (flag) return get_carbon_copy(0);
251 //write("Cc: ");
252 input_to("get_carbon_copy",INPUT_PROMPT, "Cc: ");
253 return;
254}
255
256
257static void get_carbon_copy(string str) { // Aufruf mit 0, wenn keine cc gewuenscht.
258 int i,j;
259 object p;
260 string *oldcarbons,*h,*receivers;
261 mapping orignames;
Arathorn4c2c85d2020-03-09 23:12:26 +0100262
Zesstra25387d92017-02-03 20:20:56 +0100263 oldcarbons=carbon;
264 if (str=="~q") return SendMail(0); // Abbruch, entspricht Abbruch im Editor
265 if (!str || str=="") carbon=0;
266 else carbon=process_names(str);
267 carbon=(oldcarbons ? oldcarbons : ({}))+(carbon ? carbon : ({}));
268
269#ifdef MAIL_SUPPORT_BCC
270 blindcarbon=filter(carbon,
271 function status (string x)
272 {if (x[0]=='-') return(1);
273 return(0);});
274 carbon-=blindcarbon;
275 blindcarbon=map(blindcarbon,
Arathorn4c2c85d2020-03-09 23:12:26 +0100276 function string (string x)
Zesstra25387d92017-02-03 20:20:56 +0100277 {return(x[1..]);} );
278#endif
279
280#ifdef MAIL_SUPPORT_BCC
281 oldcarbons=({receiver})+carbon+blindcarbon; // speichere alle Originaladressen
282#else
283 oldcarbons=({receiver})+carbon;
284#endif
285
286 /* Forwards auswerten, dabei werden auch ungueltige Adressen gefiltert */
287 /* orignames speichert die Zuordnung Zieladressen -> Originaladressen */
288
289 orignames=([]);
290 h=explode(FWSERV->QueryForward(receiver),",");
291
292 DEBUGVAR(h);
293 for (j=sizeof(h);j--;)
294 orignames[(h[j][0]=='\\'?h[j][1..]:h[j])]=({receiver[0]=='\\'?receiver[1..]:receiver});
295 receiver=h[0];
296 receivers=h[1..]; // Missbrauch dieser Variable!
297
298 DEBUGVAR(orignames);
299
300 for (i=sizeof(carbon);i--;) {
301 h=explode(FWSERV->QueryForward(carbon[i])||"",",");
302 for (j=sizeof(h);j--;) {
303 h[j]=(h[j][0]=='\\'?h[j][1..]:h[j]);
304 orignames[h[j]]=(orignames[h[j]]||({}))+({carbon[i][0]=='\\'?carbon[i][1..]:carbon[i]});
305 receivers+=h;
306 }
307 }
308 carbon=receivers;
309
310#ifdef MAIL_SUPPORT_BCC
311 receivers=({});
312 for (i=sizeof(blindcarbon)-1;i>=0;i--) {
313 h=old_explode(FWSERV->QueryForward(blindcarbon[i]),",");
314 for (j=sizeof(h)-1;j>=0;j--) {
315 h[j]=(h[j][0]=='\\'?h[j][1..]:h[j]);
316 orignames[h[j]]=(orignames[h[j]]||({}))+({blindcarbon[i][0]=='\\'?blindcarbon[i][1..]:blindcarbon[i]});
317 receivers+=h;
318 }
319 }
320 blindcarbon=receivers;
321#endif
322
323 carbon=send_mail();
324 receivers=({});
325
326 if (!pointerp(carbon) || !sizeof(carbon)){
327 write("Brief NICHT verschickt, da keine Empfaenger gefunden!\n");
Arathorn4c2c85d2020-03-09 23:12:26 +0100328 } else {
329 string *a;
Zesstra25387d92017-02-03 20:20:56 +0100330 DEBUGVAR(orignames);
331 for (i=0;i<sizeof(carbon);i++){
332 DEBUGVAR(carbon[i]);
333 /* evtl. abfragen nach query_editing und/oder query_input_to */
334 /* Benachrichtige Spieler, die ein forward gesetzt haben */
335 a=orignames[carbon[i]];
336 if (pointerp(a))
337 {
338 a=a-({carbon[i]});
Arathorn4c2c85d2020-03-09 23:12:26 +0100339 for (j=sizeof(a);j--;)
340 if (p=find_player(a[j]))
Zesstra25387d92017-02-03 20:20:56 +0100341 tell_object(p,"Ein Postreiter ruft Dir aus einiger Entfernung zu, dass Du neue Post hast!\nDer Brief wurde wunschgemaess weitergeleitet.\n");
342 }
343 /* Benachrichtige Empfaenger */
344#ifndef MAILDEMON0297
Arathorn4c2c85d2020-03-09 23:12:26 +0100345 if (p=find_player(carbon[i]))
Zesstra25387d92017-02-03 20:20:56 +0100346 tell_object(p,"Ein Postreiter ruft Dir aus einiger Entfernung zu, dass Du neue Post hast!\n");
347#endif
348 receivers+=orignames[carbon[i]]||orignames["\\"+carbon[i]]||({});
349 }
350 DEBUGVAR(carbon);
351 write("Abgesandt an: "+implode(unify_array(map(receivers,#'capitalize)),", ")+"\n");//')));
352 }
353 for (i=sizeof(oldcarbons);i--;)
354 if (oldcarbons[i][0]=='\\')
355 oldcarbons[i]=oldcarbons[i][1..];
356 oldcarbons=oldcarbons-receivers;
357 if (sizeof(oldcarbons)) {
358 write("Empfaenger unbekannt: "+implode(map(oldcarbons,#'capitalize),", ")+"\nIrgendjemand wirft Dir den zurueckgekommenen Brief zu.\n");//')))
359 send_mail(oldcarbons);
360 }
361
362 message=receiver=carbon=subject=0;
363 if (directflag) {
364 if (directflag==1) remove(); // 1: Direktmodus, 2: non-interactive
365 return;
366 }
367 return input();
368}
369
370
371static varargs string* send_mail(mixed back) {
372 mixed *mail;
Arathorn4c2c85d2020-03-09 23:12:26 +0100373
Zesstra25387d92017-02-03 20:20:56 +0100374 mail=allocate(9);
375
376#ifdef DEBUG
377 DEBUGVAR(receiver);
378 DEBUGVAR(carbon);
379#endif
380
381 if (!pointerp(carbon) || !sizeof(carbon)) carbon=0;
382 mail[MSG_FROM]=this_player()->query_real_name();
383 mail[MSG_SENDER]=office_name;
384 mail[MSG_RECIPIENT]=(back ? mail[MSG_FROM] : receiver);
385 mail[MSG_CC]=(back ? 0 : carbon);
386#ifdef MAIL_SUPPORT_BCC
387 mail[MSG_BCC]=blindcarbon;
388#else
389 mail[MSG_BCC]=0;
390#endif
391
392 mail[MSG_SUBJECT]=(back ? "Zurueck! Empfaenger unbekannt: "+implode(back,", ") : subject);
393 mail[MSG_DATE]=ctime(time());
394 mail[MSG_ID]="MorgenGrauen:"+time();
395 mail[MSG_BODY]=message;
396 return MAILDEMON->DeliverMail(mail,NO_SYSTEM_ALIASES|NO_USER_ALIASES);
397}
398
Zesstra25387d92017-02-03 20:20:56 +0100399varargs void do_mail(mixed str,string titel,string text) {
400 // text und titel angegeben: versende Text, keine weiteren Taetigkeiten.
401
Arathorn4c2c85d2020-03-09 23:12:26 +0100402 int i;
Zesstra25387d92017-02-03 20:20:56 +0100403 int silent;
Arathorn4c2c85d2020-03-09 23:12:26 +0100404
405 if (name)
406 return; /* security flag :-) */
407
408 if (!this_interactive())
409 return;
410
Zesstra25387d92017-02-03 20:20:56 +0100411 if (!text) {
Arathorn4c2c85d2020-03-09 23:12:26 +0100412 name = geteuid(this_interactive());
413 move(this_interactive(), M_NOCHECK);
414 if (!name)
415 remove();
Zesstra25387d92017-02-03 20:20:56 +0100416 }
Arathorn4c2c85d2020-03-09 23:12:26 +0100417
418 aliases = Read_mailrc(ALIASFILE(geteuid(this_interactive())))+
419 Read_mailrc(SYSALIAS);
420
421 int display_limit;
422 if (str)
423 {
424 str = lower_case(str);
425
426 // Eingabestring zerlegen, um die Elemente der Reihe nach parsen zu
427 // koennen.
428 string* params = explode(str, " ");
429 string* recipients = ({});
430
431 /* Ueber alle Argumente laufen und auf Verwendbares pruefen.
432 Muss for() sein, damit wir zwischendrin mittels p++ Eintraege
433 ueberspringen koennen.
434 Gueltige Argumente sind -show [<zahl>|zeilen], -silent,
435 Empfaengerliste.
436 Wenn hinter -show irgendwas kommt, das weder Integer noch "zeilen"
437 ist, wird es verworfen.
438 Wenn irgendwelche Empfaenger angegeben sind, wird auf jeden Fall
439 an write_mail() weitergegeben, egal was sonst fuer Argumente
440 dabeiwaren. Dies ist Absicht, damit man sich z.B. ein Alias
441 "mail -show 20 $*" bauen kann, das ohne weitere Angaben den
442 Posteingang oeffnet, aber eine neue Mail erstellt, wenn man dahinter
443 einen Empfaenger angibt. Auf diese Weise kann man einen im Alias
444 eingestellten Defaultwert bei der Eingabe des Befehls immer noch
445 mit -silent oder einer anderen Zahl ueberschreiben. */
446 int p;
447 for(p=0; p<sizeof(params); p++)
Zesstra25387d92017-02-03 20:20:56 +0100448 {
Arathorn4c2c85d2020-03-09 23:12:26 +0100449 // Wenn das Argument -silent ist, Flag setzen.
450 if (params[p] == "-silent")
451 {
452 display_limit = 0;
453 silent = 1;
Zesstra25387d92017-02-03 20:20:56 +0100454 }
Arathorn4c2c85d2020-03-09 23:12:26 +0100455 // Wenn es -show ist, checken wir ob das Array noch ein weiteres
456 // Element enthaelt und wenn ja, werten wir es aus und
457 else if (params[p] == "-show")
458 {
459 // hat das Array noch ein Element nach -show?
460 if (sizeof(params) >= p+2)
461 {
462 // wenn ja, ist es ein String ungleich Leerstring?
463 if (sizeof(params[p+1]))
464 {
465 string howmany = params[p+1];
466 // "zeilen" zuerst checken, weil das sonst im naechsten Check
467 // auch zu silent = 1 fuehren wuerde.
468 if (howmany == "zeilen")
469 display_limit = this_player()->QueryProp(P_SCREENSIZE);
470 // Kann man es in ein Integer >0 wandeln?
471 // Wenn 0 rauskommt, wurde entweder "-show 0" angegeben, oder
472 // ein ungueltiger Parameter. Beides interpretieren wir als
473 // "silent".
474 else if (to_int(howmany) == 0)
475 silent = 1;
476 // Alle anderen Ergebnisse werden als Zeilenlimit fuer die
477 // Anzeige interpretiert.
478 else
479 display_limit = to_int(howmany);
480 }
481 // Argumente nach -show werden in jedem Fall nicht nochmal
482 // verarbeitet, d.h. ein Schleifendurchlauf wird uebersprungen.
483 p++;
484 }
485 }
486 // Alles andere duerfte dann wohl ein Adressat sein.
487 else
488 {
489 recipients += ({params[p]});
490 }
491 }
492
493 // Wenn wir potentielle Empfaenger identifiziert haben, bauen wir den
494 // Argumentstring neu zusammen, damit wir ihn spaeter an write_mail()
495 // uebergeben koennen.
496 if(sizeof(recipients))
497 {
498 str = implode(recipients, " ");
499 directflag = 1;
500 if (text)
501 {
502 if (this_interactive()!=this_player())
503 return 0;
504 if (!TRUSTED(previous_object()))
505 return write(break_string(
506 "WARNUNG!!! Objekt "+object_name(previous_object())+" versucht, "
507 "Mail mit Deinem Absender zu versenden! Bitte Erzmagier oder "
508 "Loco verstaendigen.",78)+"\n");
509 directflag = 2;
510 return write_mail(str, titel, text);
511 }
512 directflag = 1;
Zesstra25387d92017-02-03 20:20:56 +0100513 return write_mail(str);
514 }
515 }
Arathorn4c2c85d2020-03-09 23:12:26 +0100516
Zesstra25387d92017-02-03 20:20:56 +0100517 update(0,1);
518 if (!pointerp(folders) || sizeof(folders)!=2 || sizeof(folders[0])==0) {
519 write("Du hast im Moment keine Post !\n");
520 folders=({({}),({})});
521 }
522 write("Du hast "+sizeof(folders[0])+" Ordner, Liste mit 'i'.\n");
523
524 if(!silent)
525 {
Arathorn4c2c85d2020-03-09 23:12:26 +0100526 ListContent(display_limit);
Zesstra25387d92017-02-03 20:20:56 +0100527 }
Arathorn4c2c85d2020-03-09 23:12:26 +0100528
Zesstra25387d92017-02-03 20:20:56 +0100529 write("Gesamtgroesse Deines Postfachs: "+
530 (i=(file_size(MAILFILEO(name))+512)/1024)+" KB.\n");
531 // Kleiner Hack als Uebergangsloesung, weil ich die dumme Warnung
532 // nicht mehr sehen kann. ;^)
533 // 22.10.2000, Tiamak
534 if(IS_ARCH(this_interactive())) i=0;
535
536 //
537 // Kleiner Hack, damit Regionsmitarbeiter und groessere Magier
538 // bei ihren Gebietswartungen nicht staendig mit nervigen
539 // Meldungen belaestigt werden:
540 //
541 // 2005-01-10, Zook
542 if (query_wiz_level(this_interactive()) > DOMAINMEMBER_LVL) {
Arathorn4c2c85d2020-03-09 23:12:26 +0100543 if (i>700)
Zesstra25387d92017-02-03 20:20:56 +0100544 write("*************************************************************\n"
545 "* Dein Postfach ist zu gross! Bitte versuche aufzuraeumen *\n"
546 "* und damit die Groesse zu reduzieren. Grosse Postfaecher *\n"
547 "* verursachen unnoetiges Lag fuer die Spieler. *\n"
548 "*************************************************************\n");
549 i=0;
550 }
551
552 if (i>500) // Extra-Warnung fuer Catweazle
553 // man koennte natuerlich auch eine Channel-Meldung ausspucken
554 // mit dem Hinweis, wer das aktuelle Lag verursacht... vielleicht
555 // ab 800 KB? ;-)
556 write("*****************************************************************\n"
557 "* Dein Postfach hat eine absolut unakzeptable Groesse erreicht. *\n"
558 "* Uebergrosse Postfaecher verursachen unnoetiges Lag fuer alle! *\n"
559 "* Bitte raeume es dringend auf, d.h. loesche alle Briefe, die *\n"
560 "* Du nicht _unbedingt_ benoetigst, oder lager sie aus und *\n"
561 "* loesche sie anschliessend. Hauptsache, weg damit. *\n"
562 "*****************************************************************\n");
563 else if (i>300) // Warnung fuer bestimmte Magier und Seher ab 300 KB
564 write("WARNUNG! Dein Postfach hat eine bedenkliche Groesse erreicht.\n"
565 "Beachte, dass uebergrosse Postfaecher nicht nur unnoetig Speicher, sondern\n"
566 "insbesondere auch Rechenzeit verbrauchen und damit groesseres Lag verursachen\n"
567 "koennen. Du solltest also dringend aufraeumen und alle nicht unbedingt\n"
568 "notwendigen Briefe loeschen (evtl. natuerlich vorher auslagern.\n");
569 else if (i>200) // Hinweis fuer andere.
570 write("Der Postbeamte macht dich darauf aufmerksam, dass Dein Postfach bereits\n"
571 "ziemlich voll ist und Du dringend einmal aufraeumen solltest.\n");
572 else if (i>100) // Hinweis fuer andere.
573 write("Der Postbeamte macht dich darauf aufmerksam, dass Dein Postfach\n"
574 "relativ voll ist.\n");
Arathorn4c2c85d2020-03-09 23:12:26 +0100575
Zesstra25387d92017-02-03 20:20:56 +0100576
577 if ((i=FWSERV->QueryForward(name))!=name)
578 write("Du hast einen Nachsendeauftrag gestellt, Deine Post wird an\n"
579 +i+" weitergeleitet.\n");
580 return input();
581}
582
583
584static void MediumHelpPage() {
Arathorn4c2c85d2020-03-09 23:12:26 +0100585 if (sizeof(folders[0]))
Zesstra25387d92017-02-03 20:20:56 +0100586 write("Aktueller Ordner ist \""+folders[0][akt_folder]+"\"\n");
587 write("\n\
588Brief <nr> lesen '<nr>' (lies <nr>)\n\
589Aktueller / naechster / letzter Brief '.' / '+' / '-'\n\
590Brief schreiben 'm <name>' (schreibe)\n\
591Brief beantworten 'r [nr]' (beantworte)\n\
592Gruppenantwort an alle Empfaenger 'g [nr]' (gruppe)\n\
593Brief(e) loeschen 'd [nummern]' (loesche)\n\
594Brief(e) weitersenden 'f [nummern] <name>' (weiter)\n\
595Weitersenden plus eigenen Text 'F [nr] <name>' (Weiter)\n\
596Brief(e) in anderen Ordner verschieben 'v [nummern] <ordner>' (verschiebe)\n\
597Mails in diesem Ordner listen 'l' (oder nichts) (anzeigen)\n\
598Aktuellen Ordner wechseln 'c <ordner>' (oeffne)\n\
599Neuen Ordner anlegen 'n <ordnername>' (erzeuge)\n\
600Leeren Ordner loeschen 'e <ordner>' (entferne)\n\
601Alle Ordner anzeigen 'i' (ordner)\n\
602"+ (IS_WIZARD(this_player()) ? "\
603Brief(e) speichern in Datei 's [nummern]' (speichere)\n\
604 "+SAVEFILENAME+"\n" : "")+ "\
605Mailaliase anzeigen 'a' (aliase)\n\
606Verfuegbare Kommandos zeigen '?' oder 'h'\n\
607Postmenue verlassen 'q'\n\
608Kommando <cmd> ausfuehren '!<cmd>'\n\
609[nummern] bedeutet: [nr|nr-nr [nr|nr-nr ...]]. (Liste von Nr und Bereichen)\n\
610Bei der Langform reicht es, die ersten 4 Zeichen eines Kommandos anzugeben.\n\
611Falls ein Befehl (z.B. \'v\' nicht funktioniert, pruefe bitte, ob dies ein \n\
612clientseitiges Makro bei Dir ist.\n\
613");
614 return input();
615}
616
617static varargs int GetFolders(int nocondflag) {
618// nocondflag: no condition, unbedingt neuladen
619
620// Cache-Verwaltung endlich funktionsfaehig [251196]
621// IDEE: Uhrzeit & Groesse untersuchen, ausserdem nach Verschieben neuladen.
622// Auch nach automatischem Verschieben (unread -> newmail)!
623
624
625// write("DEBUG: GetFolders called, old date "+folder_date+", old size "+folder_size+", nocondflag="+nocondflag+"\n");
Arathorn4c2c85d2020-03-09 23:12:26 +0100626 if (!nocondflag &&
Zesstra25387d92017-02-03 20:20:56 +0100627 file_time(MAILFILEO(name))==folder_date &&
628 file_size(MAILFILEO(name))==folder_size) return 0;
629
630 if (!restore_object(MAILFILE(name))) folders=({({}),({})});
631 folder_date=file_time(MAILFILEO(name));
632 folder_size=file_size(MAILFILEO(name));
633 if (!pointerp(folders) || sizeof(folders)!=2) folders=({({}),({})});
634// write("DEBUG: GetFolders finished, new date "+folder_date+", new size "+folder_size+"\n");
635 return 1;
636}
637
638static varargs void update(int directflag,int nocondflag) {
639 // directflag: Mailer wird im Direktmodus betrieben
640 // nocondflag: Unbedingt neuladen
641
642 int i,j,k,newletters;
643 mixed *ignored;
Arathorn4c2c85d2020-03-09 23:12:26 +0100644
Zesstra25387d92017-02-03 20:20:56 +0100645 if (!GetFolders(nocondflag)) return; // es hat sich nix getan
646
647 if (akt_nr<1) akt_nr=1;
648
649 DEBUGVAR(akt_folder);
650
651 if (akt_folder>=sizeof(folders[0]) || akt_folder<0) {
652 akt_folder=member(folders[0], "newmail");
653 if (akt_folder==-1) {
654 MAILDEMON->MakeFolder("newmail",name);
655 GetFolders(1);
656 DEBUGVAR(folders[0]);
657 akt_folder=member(folders[0], "newmail");
658 }
659 if (!directflag && akt_folder!=-1) write("Ordner 'newmail' aufgeschlagen.\n");
660 }
661
662// if (!pointerp(folders)) return write("ERROR: folders no array in update\n"); // Kann eigentlich nicht vorkommen
663 if (sizeof(folders[0]) && akt_nr>sizeof(folders[1][akt_folder]))
664 akt_nr=sizeof(folders[1][akt_folder]);
665 j=member(folders[0], "unread");
666 if (j==-1) return;
667 newletters=0;
668
669 // Testweise eine neue Version, die aber voraussetzt, dass die Position von
670 // unread in der Folderliste von /secure/mail waehrend der Aktion
671 // nicht veraendert wird.
672 // alt ausgeklammert, ausserdem ueberall 0 statt k
673 // k=0;
674 // Neue Version wieder testweise drin
675
676 // while (j != -1 && pointerp(folders[1][j]) && sizeof(folders[1][j])>0) {
677 for (k=0;k<sizeof(folders[1][j]);k++) {
678
679 // write("DEBUG: j="+j+"\n");
Arathorn4c2c85d2020-03-09 23:12:26 +0100680
Zesstra25387d92017-02-03 20:20:56 +0100681 if (pointerp(ignored=this_player()->QueryProp(P_IGNORE)) &&
682 member(ignored, lower_case(folders[1][j][k][MSG_FROM]+".mail"))>=0) {
683 mixed msg;
684 msg=folders[1][j][k];
685 write("Du laesst einen Brief von "+capitalize(msg[MSG_FROM])+
686 " unbesehen zurueckgehen.\n");
687 msg[MSG_BODY]=this_player()->name()+" \
688hat diesen Brief ungeoeffnet an Dich zurueckgehen lassen\n\
689und moechte nicht mehr von Deinen Briefen belaestigt werden.\n\
690Titel: "+msg[MSG_SUBJECT]+"\n\
691------ Inhalt: ------------------------\n"+
692 msg[MSG_BODY];
693 msg[MSG_RECIPIENT]=msg[MSG_FROM];
694 msg[MSG_SUBJECT]="Annahme verweigert - zurueck an Absender";
695 msg[MSG_CC]=0;
696 msg[MSG_BCC]=0;
697 MAILDEMON->DeliverMail(msg,NO_SYSTEM_ALIASES|NO_USER_ALIASES);
698 if (find_player(msg[MSG_RECIPIENT]))
699 tell_object(find_player(msg[MSG_RECIPIENT]),
700 "Ein Postreiter ruft Dir aus einiger Entfernung leicht sauer zu, dass er einen\nzurueckgekommenen Brief fuer Dich hat.\n");
701 MAILDEMON->RemoveMsg(0,j,name);
702 } else {
703 // Testweise durch DeleteUnreadFolder ersetzt (080297)
704#ifndef MAILDEMON0297
705 MAILDEMON->MoveMsg(0, j, "newmail", name);
706#endif
707 newletters++;
708 }
709 // GetFolders(1);
710 // j=member_array("unread",folders[0]);
711 // Letzte 2 Zeilen in "neuer" Version ersatzlos gestrichen
712 }
713
714#ifdef MAILDEMON0297
715 MAILDEMON->DeleteUnreadFolder(name);
716#else
717 MAILDEMON->RemoveFolder("unread",name);
718#endif
719 if (newletters) {
Arathorn4c2c85d2020-03-09 23:12:26 +0100720 if (office_name=="mpa Kurierdienst")
Zesstra25387d92017-02-03 20:20:56 +0100721 write(break_string("Ein Kurier sagt \"Tach, Post!\", drueckt Dir "+
722 ((newletters==1) ? "einen neuen Brief" : newletters+" neue Briefe")
723 +" in die Hand und verschwindet wieder.\n",78));
Arathorn4c2c85d2020-03-09 23:12:26 +0100724 else
Zesstra25387d92017-02-03 20:20:56 +0100725 write("Du siehst, wie ein Postbeamter "+
726 ((newletters==1) ? "einen neuen Brief" : newletters+" neue Briefe")
727 +" in Dein Fach legt.\n");
728 }
729 GetFolders(1); // jetzt ohne unread, damit im endgueltigen Zustand.
730 while (akt_folder>=sizeof(folders[0])) akt_folder--;
731 if ((!akt_nr)&&sizeof(folders[1][akt_folder])) akt_nr=1;
732}
733
Arathorn4c2c85d2020-03-09 23:12:26 +0100734// MSG_TIME enthaelt leider einen Datumsstring, so dass wir die MSG_ID
735// verwenden, um die Zeit daraus zu ermitteln. Die MSG_ID hat immer das
736// Format MUDNAME+":"+time().
737private string msgIDtoTime(string msg_id) {
738 int msg_time;
739 string unused;
740 // Damit das auch dann funktioniert, wenn man die Mailfolder aus dem
741 // Livemud im Testmud einliest, das ja ggf. einen anderen Namen hat,
742 // verwenden wir einen generischen Suchstring. Das Mud sollte dann aber
743 // keinen : im Namen haben.
744 if (sscanf(msg_id, "%s:%d", unused, msg_time) == 2)
745 return strftime("%d.%m.%Y", msg_time);
746 else
747 return "unbekannt";
748}
Zesstra25387d92017-02-03 20:20:56 +0100749
Arathorn4c2c85d2020-03-09 23:12:26 +0100750static varargs void ListContent(int limit) {
Zesstra25387d92017-02-03 20:20:56 +0100751 update();
Arathorn4c2c85d2020-03-09 23:12:26 +0100752
753 if (!pointerp(folders) || sizeof(folders) != 2 ||
754 !pointerp(folders[0]) || !sizeof(folders[0])) {
Zesstra25387d92017-02-03 20:20:56 +0100755 write("Du hast keinen einzigen Ordner!\n");
756 return;
757 }
Arathorn4c2c85d2020-03-09 23:12:26 +0100758
Zesstra25387d92017-02-03 20:20:56 +0100759 write("Ordner "+folders[0][akt_folder]+": ");
Arathorn4c2c85d2020-03-09 23:12:26 +0100760 if (!pointerp(folders[1]) || akt_folder >= sizeof(folders[1]) ||
Zesstra25387d92017-02-03 20:20:56 +0100761 !pointerp(folders[1][akt_folder])) {
762 write("Dieser Ordner ist leer.\n");
763 return;
764 }
Arathorn4c2c85d2020-03-09 23:12:26 +0100765
766 int mailcount = sizeof(folders[1][akt_folder]);
767 write(sprintf("%d Brief%s\n", mailcount, mailcount!=1 ? "e" : ""));
768
769 // Wieviele Zeichen muessen wir fuer die fortlaufenden Mail-Nummern
770 // reservieren? Dazu errechnen wir die Anzahl Ziffern der Arraygroesse.
771 int num_width = sizeof(to_string(mailcount));
772 // 4 Zeichen muessen reichen, damit sind immerhin 9999 Mails numerierbar.
773 num_width = min(4, num_width);
774
775 int sender_width;
776 string sender_name;
777 // Feldbreite fuer die Absenderangabe ermitteln. Wird weiter unten fuer
778 // die Anzeige der Mails benoetigt, um das Namensfeld dynamisch
779 // einzustellen. Dies soll helfen, mehr vom Subject anzeigen zu koennen.
780 // Leider muessen wir dazu einmal extra ueber die Liste laufen.
781 int i;
782 if (limit) {
783 limit = max(mailcount - limit, 0);
784 }
785 for (i = limit ; i < mailcount ; i++) {
786 sender_name = folders[1][akt_folder][i][MSG_FROM];
787 if (sizeof(sender_name) > sender_width)
788 sender_width = sizeof(sender_name);
789 // Wenn wir schon die max. Namenslaenge fuer Spieler erreicht haben,
790 // muss der Rest nicht mehr durchlaufen werden.
791 if (sender_width >= 11) {
792 // Groesse beschraenken; es kann sein, dass alte Mailboxen noch Mails
793 // von extern enthalten, und deren Mailadressen sprengen dann das
794 // Format.
795 sender_width = min(11, sender_width);
796 break;
797 }
798 }
799
800 // Subject-Breite anpassen, je nach Groesse der anderen dynamischen Felder.
801 // sender_width ist max 11, num_width ist max 4.
802 int subject_width = 46+(11-sender_width)+(4-num_width);
803
804 /* Format der Zeile. Wir bauen dynamische Feldbreiten an den Stellen ein,
805 wo es sinnvoll ist, und haben um den Mailzaehler herum zwei String-
806 Felder, die die Markierung fuer die aktuell bearbeitete Mail aufnehmen.
807 Absender und Betreffzeile werden durch den : im Formatcode
808 abgeschnitten. Es muss insbesondere beim Absender der : verwendet
809 werden, damit laengere Namen abgeschnitten werden, bei kuerzeren aber
810 korrekt mit Leerzeichen aufgefuellt wird. Verwendet man stattdessen
811 den ., macht sprintf() das nicht.
812
813 Beispiel einer Zeile mit markierter Mail:
814 [125:](Spielername, 18.12.2019) Test
815 ^_^ ^---------^ ^--^
816 | | |
817 num_width sender_width subject_width */
818 string lineformat = "%s%"+num_width+"d:%s"+ // Mail-Zaehler
819 "(%:"+sender_width+"s, %10s) "+ // Absender + Datum
820 "%:-"+subject_width+"s\n"; // Betreffzeile
821
822 for (i = limit ; i < mailcount ; i++) {
823 // Leeres Subject wird als 0 gespeichert. Falls das zutrifft, wird das
824 // hier beruecksichtigt.
825 string subject = folders[1][akt_folder][i][MSG_SUBJECT];
826 if (!stringp(subject) || !sizeof(subject))
827 subject = "<kein Betreff>";
828 write(sprintf(lineformat,
829 (i+1==akt_nr) ? "[" : " ",
830 i+1,
831 (i+1==akt_nr) ? "]" : " ",
832 capitalize(folders[1][akt_folder][i][MSG_FROM]),
833 msgIDtoTime(folders[1][akt_folder][i][MSG_ID]),
834 subject
835 ));
Zesstra25387d92017-02-03 20:20:56 +0100836 }
837 return;
838}
839
840
Arathorn4c2c85d2020-03-09 23:12:26 +0100841static void ChangeFolder(mixed x) {
Zesstra25387d92017-02-03 20:20:56 +0100842 if (!(x=GetFolderName(x))) return;
843 akt_folder=member(folders[0],x);
844 write("Du oeffnest den Ordner '"+x+"'.\n");
845 if (akt_nr<=0) akt_nr=1;
Arathorn4c2c85d2020-03-09 23:12:26 +0100846 if (akt_nr>=sizeof(folders[1][akt_folder]))
Zesstra25387d92017-02-03 20:20:56 +0100847 akt_nr=sizeof(folders[1][akt_folder]);
848 ListContent();
849}
850
851
852static void ListFolders() {
853 int i;
854 update();
855 write("Du hast "+sizeof(folders[0])+" Ordner:\n");
856 for (i=0;i<sizeof(folders[0]);i++)
857 write(sprintf("%2s%3d: %-20s(%3d Briefe)\n",
858 ((i==akt_folder)?"->":" "),
859 i+1,folders[0][i],sizeof(folders[1][i])));
860 write("Gesamtgroesse Deines Postfachs: "+
861 ((file_size(MAILFILEO(name))+512)/1024)+" KB.\n");
862}
863
864
865static void MakeFolder(string s) {
866 int ret;
867 if (sscanf(s,"%d",ret)||s[0]<'a'||s[0]>'z') return
868 write("Um Probleme zu vermeiden, duerfen Ordner nicht mit Nummern oder Sonderzeichen\nbezeichnet werden.\n");
869 if (s=="newmail"||s=="unread") return
870 write("Die Ordnernamen 'newmail' und 'unread' sind reserviert.\n");
871 ret=MAILDEMON->MakeFolder(s, name);
872 if (ret==1) write("Ok, neuer Ordner mit Namen "+s+" angelegt.\n");
873 else write("Ein Ordner mit dem Namen existiert bereits.\n");
874 return;
875}
876
877
878static int RemoveFolder(string x) {
879 int ret;
880 if (!x) return -42; // folder existiert nicht, Fehlermeldung bereits geg.
881// if (intp(x)) x=folders[0][x];
882
883 if (x=="newmail") return
884 write("Der Ordnername 'newmail' ist reserviert.\nDieser Ordner darf nicht geloescht werden.\n"),-43;
885
886 ret=MAILDEMON->RemoveFolder(x, name);
887 switch (ret) {
888 case 1: write("Ordner "+x+" geloescht.\n"); break;
889 case -1: write("Kein solcher Ordner.\n"); break;
890 case 0: write("Der Ordner war nicht leer - nicht geloescht.\n"); break;
891 default: write("Fehler Nummer "+ret+" - was auch immer das heisst...\n"); break;
892 }
893 return ret;
894}
895
896
897static varargs int DeleteMessage(int *nrs) {
898 int ret,x;
899 mixed m;
900 if ( sizeof(nrs) > 15 ) LagWarning();
901
902 for (x=sizeof(nrs)-1;x>=0;x--) {
903 write("Loesche Brief "+(nrs[x]+1)+": ");
904 ret=MAILDEMON->RemoveMsg(nrs[x], akt_folder, name);
905 switch(ret) {
906 case 1: write("Ok.\n"); break;
907 case 0: write("Kein solcher Brief im aktuellen Ordner.\n"); break;
908 case -1:write("Kein aktueller Ordner.\n"); update(); return ret;
909 default: write("MAILDEMON: Interner Fehler Nummer "+ret+"!\n"); break;
910 }
911 }
Arathorn4c2c85d2020-03-09 23:12:26 +0100912
Zesstra25387d92017-02-03 20:20:56 +0100913 return ret;
914}
915
916//"
917
918static int MoveMessage(mixed msg,mixed fol) {
919 int ret,i;
Arathorn4c2c85d2020-03-09 23:12:26 +0100920
Zesstra25387d92017-02-03 20:20:56 +0100921 for (i=0;i<sizeof(msg);i++) {
922 ret=MAILDEMON->MoveMsg(msg[i]-i, akt_folder, fol, name);
923 switch(ret) {
924 case 1:
925 write("Brief "+(msg[i]+1)+" verschoben nach "+fol+".\n");
926 break;
Arathorn4c2c85d2020-03-09 23:12:26 +0100927 case 0:
Zesstra25387d92017-02-03 20:20:56 +0100928 write("So viele Briefe sind nicht im aktuellen Ordner.\n"); return 0;
929 case -1:
930 write("Seltsamer Fehler - duerfte eigentlich nicht passieren:\n'Kein aktueller Ordner.'\n"); return -1;
931 case -3:
932 write("Den Zielordner "+fol+" gibt es nicht!\n"); return ret;
933 default:
934 write("MAILDEMON: MoveMsg Interner Fehler "+ret+". Bitte Erzmagier verstaendigen.\n"); return ret;
935 }
936 }
Arathorn4c2c85d2020-03-09 23:12:26 +0100937 if (akt_nr>=sizeof(folders[1][akt_folder]))
Zesstra25387d92017-02-03 20:20:56 +0100938 akt_nr=sizeof(folders[1][akt_folder])-1;
Arathorn4c2c85d2020-03-09 23:12:26 +0100939
Zesstra25387d92017-02-03 20:20:56 +0100940 return ret;
941}
942
943
944static varargs int Reply(int nr,int group) {
945 mixed to,dummy;
946 if (!pointerp(folders)||!pointerp(folders[0])||
947 sizeof(folders[0])<=akt_folder) {
948 write("Seltsamer Fehler: Kein aktueller Ordner!\n");
949 return 0;
950 }
951 if (nr<0 || !pointerp(folders[1][akt_folder]) ||
952 sizeof(folders[1][akt_folder])<=nr){
953 write("Einen Brief mit Nummer "+(nr+1)+" gibt es in diesem Ordner nicht!\n");
954 return 0;
955 }
956
957 if (sscanf("\n"+lower_case(folders[1][akt_folder][nr][MSG_BODY]),
958 "%s\nreply-to:%s\n",dummy,to)==2) { // Reply-to gesetzt
959 while (to[0]==' ') to=to[1..]; // ueberschuessige Leerzeichen entfernen
960 while (to[<1]==' ') to=to[0..<2];
961 }
Arathorn4c2c85d2020-03-09 23:12:26 +0100962 else
Zesstra25387d92017-02-03 20:20:56 +0100963 to=folders[1][akt_folder][nr][MSG_FROM];
964 if (group) // Gruppenantwort
965 to=({to,
966 folders[1][akt_folder][nr][MSG_RECIPIENT]})+
967 (pointerp(folders[1][akt_folder][nr][MSG_CC]) ? folders[1][akt_folder][nr][MSG_CC] : ({}))
968 -({name});
969#ifdef DEBUG
970 DEBUGVAR(name);
971 DEBUGVAR(to);
972#endif
973 write_mail(to,GetReTitle(folders[1][akt_folder][nr][MSG_SUBJECT]));
974 return 1;
975}
976
977
978static varargs int Forward(mixed to,mixed nr,int appendflag) {
979 mixed msg;
980 if (!pointerp(folders)||!pointerp(folders[0])||
981 sizeof(folders[0])<=akt_folder) {
982 write("Seltsamer Fehler: Kein aktueller Ordner!\n");
983 return 0;
984 }
985 if (nr<0 || !pointerp(folders[1][akt_folder]) ||
986 sizeof(folders[1][akt_folder])<=nr){
987 write("Nicht so viele Briefe in diesem Ordner!\n");
988 return 0;
989 }
990 to=process_names(to);
991 receiver=to[0];
992 carbon=to[1..];
993 subject="Fw: "+folders[1][akt_folder][nr][MSG_SUBJECT];
994 message="Weitergesendeter Brief, urspruenglich von: "+
995 folders[1][akt_folder][nr][MSG_FROM]+"\n\
996-----------------------------\n\
997"+folders[1][akt_folder][nr][MSG_BODY]+"\
998-----------------------------\n";
999 if (!appendflag) return get_carbon_copy(0),1;
1000 else {
1001 write("Text kann angehaengt werden\n");
1002 get_subject(subject,message);
1003 }
1004 return 1;
1005}
1006
1007
1008
1009static int ForwardArea(mixed to,int * nrs) {
1010 mixed msg;
1011
1012 if (!sizeof(nrs)) return 0;
1013 if (sizeof(nrs)==1) return Forward(to,nrs[0]);
1014 if (sizeof(nrs)>15) LagWarning();
1015
1016 to=process_names(to);
1017 receiver=to[0];
1018 carbon=to[1..];
1019 subject="Fw: Gesammelte Briefe ("+dtime(time())[5..23]+")";
1020 message="";
1021 for (i=0;i<sizeof(nrs);i++) {
1022 write("Brief "+(nrs[i]+1)+": ");
1023 message+=Message2string(nrs[i])+
1024 "----------------------------------------------------------------------\n";
1025 write("Angehaengt.\n");
1026 }
1027/*
1028 if (!appendflag) {
1029*/
1030 return get_carbon_copy(0),1;
1031/* }
1032 else {
1033 write("Text kann angehaengt werden\n");
1034 get_subject(subject,message);
1035 }
1036 return 1;
1037*/
1038}
1039
1040//----------
1041
1042
1043static int ReadMessage(int nr) {
1044 if (nr<sizeof(folders[1][akt_folder]) && nr>=0)
1045 akt_nr=nr+1;
1046 message=Message2string(nr);
1047 if (!message) return 0;
1048 this_player()->More(message,0,#'input); //')
1049 return 1;
1050}
1051
1052
1053static string Message2string(int nr) {
1054 mixed letter;
1055 string message;
1056 int x;
1057 if (!pointerp(folders)||!pointerp(folders[0])||
1058 sizeof(folders[0])<=akt_folder){
1059 write("Seltsamer Fehler: Kein aktueller Ordner!\n");
1060 return 0;
1061 }
1062 if (!pointerp(folders[1][akt_folder]) ||
1063 sizeof(folders[1][akt_folder])<=nr ||
1064 nr<0) {
1065 write("Diese Nummer gibt es in diesem Ordner nicht!\n");
1066 return 0;
1067 }
1068 letter=folders[1][akt_folder][nr];
1069 message=
1070 "Absender: "+capitalize(letter[MSG_FROM])+"\n"+
1071 ((letter[MSG_FROM]==letter[MSG_SENDER]) ? "" :
1072 "Abgesandt aber von: "+capitalize(letter[MSG_SENDER])+"\n") +
1073 "An: "+capitalize(letter[MSG_RECIPIENT]);
1074 if (stringp(letter[MSG_CC]) && letter[MSG_CC]!="" ||
1075 pointerp(letter[MSG_CC]) && sizeof(letter[MSG_CC])) {
1076 message+="\nCc: ";
Arathorn4c2c85d2020-03-09 23:12:26 +01001077 if (!pointerp(letter[MSG_CC])) message+=capitalize(letter[MSG_CC]);
Zesstra25387d92017-02-03 20:20:56 +01001078 else message+=implode(map(letter[MSG_CC],#'capitalize),", ");//'))
1079 }
1080 message+="\nDatum: "+letter[MSG_DATE]+"\n"+
1081/* Sinnlos, oder? "Id: "+letter[MSG_ID]+"\n"+ */
1082 "Titel: "+letter[MSG_SUBJECT]+"\n\n"+
1083 letter[MSG_BODY]+"\n\n";
1084 return message;
1085}
1086
1087
1088static void LagWarning() {
1089 write("\
1090WARNUNG!!! Diese Aktion kann sehr lange benoetigen. Bitte sparsam verwenden,\n\
1091 um das Lag fuer alle ertraeglich zu halten. Falls die Aktion mit einem\n\
1092 Fehler abbricht, waren es wahrscheinlich zu viele Briefe auf einmal.\n\
1093 Dann kannst Du mit \"mail\" wieder in das Mailmenu einsteigen und solltest\n\
1094 es mit weniger Briefen versuchen.\n");
1095}
1096
1097
1098static varargs int SaveMessage(int * nrs) {
1099 int x,nr;
1100 string rest;
1101 mixed letter;
1102
1103 if (!IS_WIZARD(this_player())) {
1104 write("Das koennen nur Magier!\n");
1105 return 0;
1106 }
1107 if (!sizeof(nrs)) {
1108 write("Speichere nichts.\n");
1109 return 1;
1110 }
Arathorn4c2c85d2020-03-09 23:12:26 +01001111
Zesstra25387d92017-02-03 20:20:56 +01001112 if ( sizeof(nrs) > 15 ) LagWarning();
1113
1114 for (nr=0;nr<sizeof(nrs);nr++) {
1115 write("Speichere Brief "+(nrs[nr]+1)+": ");
1116 letter=Message2string(nrs[nr]);
1117 letter+="----------------------------------------------------------------------\n";
1118 if (!letter) {
1119 write("Speichern unmoeglich.\n");
1120 return 0;
1121 }
1122 if (!write_file(SAVEFILENAME, letter))
1123 write("Brief zu lang!\n");
1124 else
1125 write("Ok.\n");
1126 }
1127 write("Speichern nach "+SAVEFILENAME+" fertig.\nBitte denk dran, diese Datei wieder zu loeschen!\n");
1128 return 1;
1129}
1130
1131// {'}
1132
1133static void ListAliases() {
1134 mixed a;
1135 int i;
1136 string s;
1137 a=sort_array(m_indices(aliases),#'>); // ');
1138 s=( "Definierte Aliase:\n"
1139 "d.xyz = Alle Mitarbeiter der Domain xyz\n"
1140 "freunde = Deine Freunde (entsprechend Freundschaftsband)\n"
1141 "me = "+(this_player()->QueryProp(P_MAILADDR))+"\n");
Arathorn4c2c85d2020-03-09 23:12:26 +01001142 for (i=0;i<sizeof(a);i++)
Zesstra25387d92017-02-03 20:20:56 +01001143 if (strstr(aliases[a[i]],"@")==-1) s+=sprintf("%-12s = %s\n",a[i],aliases[a[i]]);
1144 write(s);
1145}
1146
1147
1148
1149/* ------ Das Mailmenue --------------------------------------------------*/
1150
1151
1152static void mail_cmds(string str) {
1153
1154 string *strargs;
1155 int i,nrargs;
Arathorn4c2c85d2020-03-09 23:12:26 +01001156
Zesstra25387d92017-02-03 20:20:56 +01001157 update();
1158
1159 if (!str || str=="" || !(nrargs=sizeof(strargs=old_explode(str[0..0]+lower_case(str[1..])," ")))) {
1160 ListContent();
1161 return input();
1162 }
1163 strargs[0]=strargs[0][0..3];
1164 if (IS_NUMBER(strargs[0])) {
1165 strargs=({"lies",strargs[0]});
1166 nrargs=2;
1167 }
1168 DEBUGVAR(strargs);
1169 switch (strargs[0]) {
1170 case "q": // quit
Arathorn4c2c85d2020-03-09 23:12:26 +01001171 case "quit":
Zesstra25387d92017-02-03 20:20:56 +01001172 remove(); return;
1173 case "?": // Hilfeseite
1174 case "hilf":
1175 case "h":
1176 MediumHelpPage();
1177 return;
1178 case "oeff": // change folder
Arathorn4c2c85d2020-03-09 23:12:26 +01001179 case "c":
Zesstra25387d92017-02-03 20:20:56 +01001180 if (nrargs<2) {
1181 write("Welchen Ordner willst Du oeffnen (Name, Nummer, +, -)?\n");
1182 break;
1183 }
1184 ChangeFolder(strargs[1]);
1185 break;
1186 case "ordn": // list folders
Arathorn4c2c85d2020-03-09 23:12:26 +01001187 case "i":
Zesstra25387d92017-02-03 20:20:56 +01001188 ListFolders();
1189 break;
1190 case "anze": // list content
1191 case "l":
1192 ListContent();
1193 break;
1194 case "alia": // list aliases
1195 case "a":
1196 ListAliases();
1197 break;
1198 case "erze": // make new folder
Arathorn4c2c85d2020-03-09 23:12:26 +01001199 case "n":
Zesstra25387d92017-02-03 20:20:56 +01001200 if (nrargs<2) {
1201 write("Bitte als Argument einen Namen fuer den neuen Ordner angeben!\n");
1202 break;
1203 }
1204 MakeFolder(lower_case(strargs[1]));
1205 break;
1206 case "entf": // delete folder
Arathorn4c2c85d2020-03-09 23:12:26 +01001207 case "e":
Zesstra25387d92017-02-03 20:20:56 +01001208 if (nrargs<2) {
1209 write("Bitte als Argument Name oder Nummer des zu loeschenden Ordners angeben.\n");
1210 break;
1211 }
1212 RemoveFolder(GetFolderName(strargs[1]));
1213 break;
1214 case "loes": // delete message
1215 case "d":
1216 if (nrargs==1) DeleteMessage(({akt_nr-1}));
1217 else DeleteMessage(GetNumbers(strargs[1..]));
1218 break;
1219 case "schr": // write mail
Arathorn4c2c85d2020-03-09 23:12:26 +01001220 case "m":
Zesstra25387d92017-02-03 20:20:56 +01001221 if (nrargs<2) {
1222 write("Bitte Empfaenger als Argument angeben!\n");
1223 break;
1224 }
1225 write_mail(strargs[1..]);
1226 return;
1227 case "vers": // move message to other folder
1228 case "verl":
1229 case "v":
1230 if (nrargs<2 || (nrargs>2 && !IS_NUMBER(strargs[1]))) {
1231 write("Syntax: v [nr|nr-nr [nr|nr-nr ...]] <ordnername>|<ordnernr>|+|-\n");
1232 break;
1233 }
1234 if (nrargs==2) MoveMessage(({akt_nr-1}),GetFolderName(strargs[1]));
1235 else MoveMessage(GetNumbers(strargs[1..<2]),GetFolderName(strargs[<1]));
1236 update(0,1); // unbedingt neuladen.
1237 break;
1238 case "bean":
1239 case "r":
1240 case "grup":
1241 case "g":
Arathorn4c2c85d2020-03-09 23:12:26 +01001242 if (nrargs<2) {
Zesstra25387d92017-02-03 20:20:56 +01001243 if (Reply(akt_nr-1,(strargs[0][0]=='g'))) return;
1244 break;
1245 }
1246 if (!IS_NUMBER(strargs[1])) {
1247 write("Argumentfehler: Bitte Nummer des Briefes angeben, auf den sich die Antwort\n"
1248 "beziehen soll. Ohne Argument bezieht sie sich auf den aktuellen Brief.\n");
1249 break;
1250 }
1251 if (nrargs>2) {
1252 write("Zu viele Argumente. Eine Antwort darf sich nur auf einen Brief beziehen!\n");
1253 break;
1254 }
1255 if (Reply(to_int(strargs[1])-1,(strargs[0][0]=='g'))) return;
1256 break;
1257 case "weit":
1258 case "f":
Arathorn4c2c85d2020-03-09 23:12:26 +01001259 if (nrargs<2 ||
Zesstra25387d92017-02-03 20:20:56 +01001260 (IS_NUMBER(strargs[nrargs-1])&&sizeof(old_explode(strargs[nrargs-1],"@"))==1)) {
1261 write("Syntax: f [nr|nr-nr [nr|nr-nr ...]] empfaenger [empf2 ...]\n");
1262 break;
Arathorn4c2c85d2020-03-09 23:12:26 +01001263 }
Zesstra25387d92017-02-03 20:20:56 +01001264 if (!IS_NUMBER(strargs[1])) {
Arathorn4c2c85d2020-03-09 23:12:26 +01001265 if (Forward(strargs[1..],akt_nr-1)) return;
Zesstra25387d92017-02-03 20:20:56 +01001266 } // return, nicht break: input() wird von get_carbon_copy() aufger.
1267 else {
1268 int pos; // letzte Position, an der eine Nummer steht
Arathorn4c2c85d2020-03-09 23:12:26 +01001269
Zesstra25387d92017-02-03 20:20:56 +01001270 for (pos=nrargs-1;pos>1&&!IS_NUMBER(strargs[pos]);pos--);
1271 if (ForwardArea(strargs[(pos+1)..],GetNumbers(strargs[1..pos])))
1272 return;
Arathorn4c2c85d2020-03-09 23:12:26 +01001273 }
Zesstra25387d92017-02-03 20:20:56 +01001274 break;
1275 case "Weit":
1276 case "F":
1277 if (nrargs<2 || (nrargs==2 && IS_NUMBER(strargs[1]))) {
1278 write("Haeh? Bitte so: F [nr] empfaenger\n");
1279 break;
1280 }
1281 if (!IS_NUMBER(strargs[1])) {
1282 if (Forward(strargs[1..],akt_nr-1,1)) return;
1283 break;
1284 }
1285 if (IS_NUMBER(strargs[2])||member(strargs[1],'-')>=0) {
1286 write("Argumentfehler: Wenn Du eigenen Text anhaengen willst, darfst Du nur einen\n"
1287 "Brief angeben, nicht mehrere.\n");
1288 break;
1289 }
1290 if (Forward(strargs[2..],to_int(strargs[1])-1,1)) return;
1291 break;
1292 case "lies":
1293 if (nrargs<2) { if (ReadMessage(akt_nr-1)) return; } else
1294 if (ReadMessage(to_int(strargs[1])-1)) return;
1295 break;
1296 case ".":
1297 if (ReadMessage(akt_nr-1)) return;
1298 break;
1299 case "+":
1300 if (akt_nr==sizeof(folders[1][akt_folder]))
1301 write("Noch weiter vorwaerts gehts nicht!\nMit 'c +' kannst Du den naechsten Ordner oeffnen.\n");
1302 else if (ReadMessage(akt_nr)) return;
1303 break;
1304 case "-":
1305 if (akt_nr==1)
1306 write("Noch weiter zurueck gehts nicht!\nMit 'c -' kannst Du den vorhergehenden Ordner oeffnen.\n");
1307 else if (ReadMessage(akt_nr-2)) return;
1308 break;
1309 case "spei":
1310 case "s":
1311 if ((nrargs==2 && !IS_NUMBER(strargs[1]))) {
1312 write("Syntax: s [nr|nr-nr [nr|nr-nr ...]]\n");
1313 break;
1314 }
1315 if (nrargs==1) (SaveMessage(({akt_nr-1})));
1316 else (SaveMessage(GetNumbers(strargs[1..])));
1317 break;
1318 default:
1319 write("Kommando nicht verstanden. Eine Hilfsseite bekommst Du mit 'h'.\n");
1320 break;
1321 }
1322 return input();
1323}
1324
1325
1326/*------------------------------------------------------------------------*/
1327
1328static string prompt() {
1329 string path;
Arathorn4c2c85d2020-03-09 23:12:26 +01001330
Zesstra25387d92017-02-03 20:20:56 +01001331 update();
1332 if (!pointerp(folders)||!pointerp(folders[0])||
1333 sizeof(folders[0])<=akt_folder)
1334 path="(kein Ordner)";
1335 else
1336 path= "(" + folders[0][akt_folder] + ":" +
1337 ( sizeof(folders[1][akt_folder]) ?
1338 akt_nr + "/" + sizeof(folders[1][akt_folder]) :
1339 "leer") + ")";
1340 return(path + " [Hilfe mit h] => ");
1341}
1342
1343
1344static void input() {
1345 //prompt();
1346 input_to("mail_cmds", INPUT_PROMPT, prompt());
1347 return;
1348}
1349
1350
1351static mixed GetAlias(mixed a);
1352
1353#ifdef MAIL_SUPPORT_BCC
1354static mixed RecurseProcessNames(mixed a);
1355#endif
1356
1357
1358static mixed process_names(mixed s) {
1359 mixed a1,a2,h;
1360 int i;
1361 string domain;
1362
1363 if (stringp(s)) {
1364 a1=explode(regreplace(lower_case(s),","," ",1)," ")-({""});
1365 }
1366 else a1=s;
1367 a2=({});
1368 foreach(string str: a1)
1369 a2+=explode(str,",");
1370
1371 a1=({});
1372
1373// printf("DEBUG ANFANG: %O\n",a2);
1374
Arathorn4c2c85d2020-03-09 23:12:26 +01001375 foreach(string str: a2) {
Zesstra25387d92017-02-03 20:20:56 +01001376 if( !sizeof(str) ) continue;
1377 if (sscanf(str,"d.%s",domain)) {
1378 h=(get_dir("/d/"+domain+"/*")||({}))-({".",".."});
1379 // h immer ein Array
1380 h=filter(h,#'query_wiz_level);
1381 if (sizeof(h))
1382 a1+=h;
1383 else
1384 a1+=({"d."+domain});
1385 }
Arathorn4c2c85d2020-03-09 23:12:26 +01001386 else if (str=="freunde")
Zesstra25387d92017-02-03 20:20:56 +01001387 a1+=("/p/service/tiamak/obj/fbmaster"->get_friends(getuid(this_player()), 8));
Arathorn4c2c85d2020-03-09 23:12:26 +01001388 else if (str=="me")
Zesstra25387d92017-02-03 20:20:56 +01001389 a1+=({this_player()->QueryProp(P_MAILADDR)});
Arathorn4c2c85d2020-03-09 23:12:26 +01001390 else if (aliases[str])
Zesstra25387d92017-02-03 20:20:56 +01001391 a1+=GetAlias(str);
1392#ifdef MAIL_SUPPORT_BCC
1393 else if (str[0]=='-')
1394 a1+=map(RecurseProcessNames(str[1..]), function string (string x) {
1395 return("-"+x);});
1396#endif
Arathorn4c2c85d2020-03-09 23:12:26 +01001397 else if ( (str[0]>='a' && str[0]<='z')
1398 || (sscanf(str,"%s@%s",domain,domain))
1399 || str[0]=='\\')
Zesstra25387d92017-02-03 20:20:56 +01001400 a1+=({str});
1401 }
Arathorn4c2c85d2020-03-09 23:12:26 +01001402
Zesstra25387d92017-02-03 20:20:56 +01001403// printf("DEBUG ENDE: %O\n",a1);
1404
Arathorn4c2c85d2020-03-09 23:12:26 +01001405 a1=filter(a1,function int (string x)
Zesstra25387d92017-02-03 20:20:56 +01001406 { return(sizeof(x)>1); } );
1407
1408 return(map(a1,#'lower_case));
Arathorn4c2c85d2020-03-09 23:12:26 +01001409}
Zesstra25387d92017-02-03 20:20:56 +01001410
1411
1412static mixed GetAlias(mixed a) { return process_names(aliases[a]); }
1413#ifdef MAIL_SUPPORT_BCC
1414static mixed RecurseProcessNames(mixed a) { return process_names(a); }
1415#endif
1416
1417
1418static mapping Read_mailrc(string file) {
1419 mapping al;
1420 int i;
1421 mixed ar;
1422 string s1,s2;
1423
1424 if (!(ar=read_file(file))) {
1425// write(file+" not readable\n");
1426 return ([]);
1427 }
1428 al=([]);
1429 ar=explode(ar,"\n");
1430 for (i=sizeof(ar)-1;i>=0;i--)
Arathorn4c2c85d2020-03-09 23:12:26 +01001431 if (sscanf(ar[i],"%s %s",s1,s2)==2)
Zesstra25387d92017-02-03 20:20:56 +01001432 al+=([s1:s2]);
1433// printf("Got aliases %O",al);
1434 return al;
1435}
1436
1437
1438string * unify_array(string * a) {
1439// int i;
1440// for (i=sizeof(a)-1;i>=0;i--) a=a-({a[i]})+({a[i]});
1441// Rikus 14.02.2001
1442 a=m_indices(mkmapping(a));
1443 return a;
1444}
1445
1446
1447string GetReTitle(string s) {
1448 int nr,s2;
1449
1450 if (!s) s="";
1451 if (s[0..7]=="Re: Re: ") return "Re^3: "+s[8..];
1452 else if (sscanf(s,"Re^%d: %s",nr,s2))
1453 return "Re^"+(nr+1)+": "+s2;
1454 else return "Re: "+s;
1455}
1456
1457
1458int * GetNumbers(mixed s) {
1459 int i,h1,h2;
1460 mixed ret;
Arathorn4c2c85d2020-03-09 23:12:26 +01001461
Zesstra25387d92017-02-03 20:20:56 +01001462 if (intp(s)) return ({s-1});
1463 if (stringp(s)) s=({s-1});
1464 if (!pointerp(s)) return 0;
1465
1466 ret=({});
1467
1468 for (i=sizeof(s)-1;i>=0;i--) {
1469 if (sscanf(s[i],"%d-%d",h1,h2)==2) {
1470 if (h2-h1>100) {
1471 write("Nicht so viele auf einmal, bitte.\n");
1472 return ({});
1473 }
1474 for (h1--;h1<h2;h1++) ret=ret-({h1})+({h1});
1475 }
1476 else
1477 ret=ret-({h1=to_int(s[i])-1})+({h1});
1478 }
1479 ret=sort_array(ret,#'>); //')
1480 DEBUGVAR(ret);
1481 if (ret[0]<0) {
1482 write("Illegale Nummer: "+(ret[0]+1)+", nichts unter 1 bitte!\n");
1483 return ({});
1484 }
1485 if (ret[<1]>=sizeof(folders[1][akt_folder])) {
1486 write("Illegale Nummer: "+(ret[<1]+1)+", so gross ist dieser Ordner nicht!\n");
1487 return ({});
1488 }
1489 return ret;
1490}
1491
1492
1493/*
1494int is_number(string s) {
1495 return (s[0]>='0'&&s[0]<='9');
1496}
1497*/
1498
1499
1500string GetFolderName(mixed fol) { // int oder string. alles andere -> Fehler!
1501 mixed h;
1502
1503 if (fol=="+") fol=akt_folder+1;
1504 if (fol=="-") fol=akt_folder-1;
1505 if ((!fol)||(intp(fol))||(IS_NUMBER(fol))) {
1506 if (!intp(fol)) fol=to_int(fol)-1;
Arathorn4c2c85d2020-03-09 23:12:26 +01001507 if (fol<0||fol>=sizeof(folders[0]))
Zesstra25387d92017-02-03 20:20:56 +01001508 return write("Einen Ordner mit Nummer "+(fol+1)+" gibt es nicht.\n"),0;
1509 return folders[0][fol];
1510 }
1511 fol=lower_case(fol);
1512 if (sizeof(h=regexp(folders[0],"^"+fol))==1) return h[0];
1513 if (member(folders[0],fol)==-1)
1514 return write("Einen Ordner mit Namen "+fol+" hast Du nicht.\n"),0;
1515 return fol;
1516}
1517
1518int query_prevent_shadow() { return 1; }