blob: 535165d4d37a4ccdb9e13759e4857ea20afdbcdc [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"
Zesstra25387d92017-02-03 20:20:56 +01001139 "freunde = Deine Freunde (entsprechend Freundschaftsband)\n"
1140 "me = "+(this_player()->QueryProp(P_MAILADDR))+"\n");
Arathorn4c2c85d2020-03-09 23:12:26 +01001141 for (i=0;i<sizeof(a);i++)
Zesstra25387d92017-02-03 20:20:56 +01001142 if (strstr(aliases[a[i]],"@")==-1) s+=sprintf("%-12s = %s\n",a[i],aliases[a[i]]);
1143 write(s);
1144}
1145
1146
1147
1148/* ------ Das Mailmenue --------------------------------------------------*/
1149
1150
1151static void mail_cmds(string str) {
1152
1153 string *strargs;
1154 int i,nrargs;
Arathorn4c2c85d2020-03-09 23:12:26 +01001155
Zesstra25387d92017-02-03 20:20:56 +01001156 update();
1157
1158 if (!str || str=="" || !(nrargs=sizeof(strargs=old_explode(str[0..0]+lower_case(str[1..])," ")))) {
1159 ListContent();
1160 return input();
1161 }
1162 strargs[0]=strargs[0][0..3];
1163 if (IS_NUMBER(strargs[0])) {
1164 strargs=({"lies",strargs[0]});
1165 nrargs=2;
1166 }
1167 DEBUGVAR(strargs);
1168 switch (strargs[0]) {
1169 case "q": // quit
Arathorn4c2c85d2020-03-09 23:12:26 +01001170 case "quit":
Zesstra25387d92017-02-03 20:20:56 +01001171 remove(); return;
1172 case "?": // Hilfeseite
1173 case "hilf":
1174 case "h":
1175 MediumHelpPage();
1176 return;
1177 case "oeff": // change folder
Arathorn4c2c85d2020-03-09 23:12:26 +01001178 case "c":
Zesstra25387d92017-02-03 20:20:56 +01001179 if (nrargs<2) {
1180 write("Welchen Ordner willst Du oeffnen (Name, Nummer, +, -)?\n");
1181 break;
1182 }
1183 ChangeFolder(strargs[1]);
1184 break;
1185 case "ordn": // list folders
Arathorn4c2c85d2020-03-09 23:12:26 +01001186 case "i":
Zesstra25387d92017-02-03 20:20:56 +01001187 ListFolders();
1188 break;
1189 case "anze": // list content
1190 case "l":
1191 ListContent();
1192 break;
1193 case "alia": // list aliases
1194 case "a":
1195 ListAliases();
1196 break;
1197 case "erze": // make new folder
Arathorn4c2c85d2020-03-09 23:12:26 +01001198 case "n":
Zesstra25387d92017-02-03 20:20:56 +01001199 if (nrargs<2) {
1200 write("Bitte als Argument einen Namen fuer den neuen Ordner angeben!\n");
1201 break;
1202 }
1203 MakeFolder(lower_case(strargs[1]));
1204 break;
1205 case "entf": // delete folder
Arathorn4c2c85d2020-03-09 23:12:26 +01001206 case "e":
Zesstra25387d92017-02-03 20:20:56 +01001207 if (nrargs<2) {
1208 write("Bitte als Argument Name oder Nummer des zu loeschenden Ordners angeben.\n");
1209 break;
1210 }
1211 RemoveFolder(GetFolderName(strargs[1]));
1212 break;
1213 case "loes": // delete message
1214 case "d":
1215 if (nrargs==1) DeleteMessage(({akt_nr-1}));
1216 else DeleteMessage(GetNumbers(strargs[1..]));
1217 break;
1218 case "schr": // write mail
Arathorn4c2c85d2020-03-09 23:12:26 +01001219 case "m":
Zesstra25387d92017-02-03 20:20:56 +01001220 if (nrargs<2) {
1221 write("Bitte Empfaenger als Argument angeben!\n");
1222 break;
1223 }
1224 write_mail(strargs[1..]);
1225 return;
1226 case "vers": // move message to other folder
1227 case "verl":
1228 case "v":
1229 if (nrargs<2 || (nrargs>2 && !IS_NUMBER(strargs[1]))) {
1230 write("Syntax: v [nr|nr-nr [nr|nr-nr ...]] <ordnername>|<ordnernr>|+|-\n");
1231 break;
1232 }
1233 if (nrargs==2) MoveMessage(({akt_nr-1}),GetFolderName(strargs[1]));
1234 else MoveMessage(GetNumbers(strargs[1..<2]),GetFolderName(strargs[<1]));
1235 update(0,1); // unbedingt neuladen.
1236 break;
1237 case "bean":
1238 case "r":
1239 case "grup":
1240 case "g":
Arathorn4c2c85d2020-03-09 23:12:26 +01001241 if (nrargs<2) {
Zesstra25387d92017-02-03 20:20:56 +01001242 if (Reply(akt_nr-1,(strargs[0][0]=='g'))) return;
1243 break;
1244 }
1245 if (!IS_NUMBER(strargs[1])) {
1246 write("Argumentfehler: Bitte Nummer des Briefes angeben, auf den sich die Antwort\n"
1247 "beziehen soll. Ohne Argument bezieht sie sich auf den aktuellen Brief.\n");
1248 break;
1249 }
1250 if (nrargs>2) {
1251 write("Zu viele Argumente. Eine Antwort darf sich nur auf einen Brief beziehen!\n");
1252 break;
1253 }
1254 if (Reply(to_int(strargs[1])-1,(strargs[0][0]=='g'))) return;
1255 break;
1256 case "weit":
1257 case "f":
Arathorn4c2c85d2020-03-09 23:12:26 +01001258 if (nrargs<2 ||
Zesstra25387d92017-02-03 20:20:56 +01001259 (IS_NUMBER(strargs[nrargs-1])&&sizeof(old_explode(strargs[nrargs-1],"@"))==1)) {
1260 write("Syntax: f [nr|nr-nr [nr|nr-nr ...]] empfaenger [empf2 ...]\n");
1261 break;
Arathorn4c2c85d2020-03-09 23:12:26 +01001262 }
Zesstra25387d92017-02-03 20:20:56 +01001263 if (!IS_NUMBER(strargs[1])) {
Arathorn4c2c85d2020-03-09 23:12:26 +01001264 if (Forward(strargs[1..],akt_nr-1)) return;
Zesstra25387d92017-02-03 20:20:56 +01001265 } // return, nicht break: input() wird von get_carbon_copy() aufger.
1266 else {
1267 int pos; // letzte Position, an der eine Nummer steht
Arathorn4c2c85d2020-03-09 23:12:26 +01001268
Zesstra25387d92017-02-03 20:20:56 +01001269 for (pos=nrargs-1;pos>1&&!IS_NUMBER(strargs[pos]);pos--);
1270 if (ForwardArea(strargs[(pos+1)..],GetNumbers(strargs[1..pos])))
1271 return;
Arathorn4c2c85d2020-03-09 23:12:26 +01001272 }
Zesstra25387d92017-02-03 20:20:56 +01001273 break;
1274 case "Weit":
1275 case "F":
1276 if (nrargs<2 || (nrargs==2 && IS_NUMBER(strargs[1]))) {
1277 write("Haeh? Bitte so: F [nr] empfaenger\n");
1278 break;
1279 }
1280 if (!IS_NUMBER(strargs[1])) {
1281 if (Forward(strargs[1..],akt_nr-1,1)) return;
1282 break;
1283 }
1284 if (IS_NUMBER(strargs[2])||member(strargs[1],'-')>=0) {
1285 write("Argumentfehler: Wenn Du eigenen Text anhaengen willst, darfst Du nur einen\n"
1286 "Brief angeben, nicht mehrere.\n");
1287 break;
1288 }
1289 if (Forward(strargs[2..],to_int(strargs[1])-1,1)) return;
1290 break;
1291 case "lies":
1292 if (nrargs<2) { if (ReadMessage(akt_nr-1)) return; } else
1293 if (ReadMessage(to_int(strargs[1])-1)) return;
1294 break;
1295 case ".":
1296 if (ReadMessage(akt_nr-1)) return;
1297 break;
1298 case "+":
1299 if (akt_nr==sizeof(folders[1][akt_folder]))
1300 write("Noch weiter vorwaerts gehts nicht!\nMit 'c +' kannst Du den naechsten Ordner oeffnen.\n");
1301 else if (ReadMessage(akt_nr)) return;
1302 break;
1303 case "-":
1304 if (akt_nr==1)
1305 write("Noch weiter zurueck gehts nicht!\nMit 'c -' kannst Du den vorhergehenden Ordner oeffnen.\n");
1306 else if (ReadMessage(akt_nr-2)) return;
1307 break;
1308 case "spei":
1309 case "s":
1310 if ((nrargs==2 && !IS_NUMBER(strargs[1]))) {
1311 write("Syntax: s [nr|nr-nr [nr|nr-nr ...]]\n");
1312 break;
1313 }
1314 if (nrargs==1) (SaveMessage(({akt_nr-1})));
1315 else (SaveMessage(GetNumbers(strargs[1..])));
1316 break;
1317 default:
1318 write("Kommando nicht verstanden. Eine Hilfsseite bekommst Du mit 'h'.\n");
1319 break;
1320 }
1321 return input();
1322}
1323
1324
1325/*------------------------------------------------------------------------*/
1326
1327static string prompt() {
1328 string path;
Arathorn4c2c85d2020-03-09 23:12:26 +01001329
Zesstra25387d92017-02-03 20:20:56 +01001330 update();
1331 if (!pointerp(folders)||!pointerp(folders[0])||
1332 sizeof(folders[0])<=akt_folder)
1333 path="(kein Ordner)";
1334 else
1335 path= "(" + folders[0][akt_folder] + ":" +
1336 ( sizeof(folders[1][akt_folder]) ?
1337 akt_nr + "/" + sizeof(folders[1][akt_folder]) :
1338 "leer") + ")";
1339 return(path + " [Hilfe mit h] => ");
1340}
1341
1342
1343static void input() {
1344 //prompt();
1345 input_to("mail_cmds", INPUT_PROMPT, prompt());
1346 return;
1347}
1348
1349
1350static mixed GetAlias(mixed a);
1351
1352#ifdef MAIL_SUPPORT_BCC
1353static mixed RecurseProcessNames(mixed a);
1354#endif
1355
1356
1357static mixed process_names(mixed s) {
1358 mixed a1,a2,h;
1359 int i;
1360 string domain;
1361
1362 if (stringp(s)) {
1363 a1=explode(regreplace(lower_case(s),","," ",1)," ")-({""});
1364 }
1365 else a1=s;
1366 a2=({});
1367 foreach(string str: a1)
1368 a2+=explode(str,",");
1369
1370 a1=({});
1371
1372// printf("DEBUG ANFANG: %O\n",a2);
1373
Arathorn0a8e4d32020-07-29 18:36:59 +02001374 foreach(string str: a2)
1375 {
1376 if (str=="freunde")
1377 a1 += ("/p/service/tiamak/obj/fbmaster"->get_friends(
1378 getuid(this_player()), 8));
1379 else if (str=="me")
1380 a1+=({this_player()->QueryProp(P_MAILADDR)});
1381 else if (aliases[str])
1382 a1+=GetAlias(str);
Zesstra25387d92017-02-03 20:20:56 +01001383#ifdef MAIL_SUPPORT_BCC
1384 else if (str[0]=='-')
Arathorn0a8e4d32020-07-29 18:36:59 +02001385 a1+=map(RecurseProcessNames(str[1..]), function string (string x) {
1386 return("-"+x);
1387 });
Zesstra25387d92017-02-03 20:20:56 +01001388#endif
Arathorn0a8e4d32020-07-29 18:36:59 +02001389 else if ( (str[0]>='a' && str[0]<='z') ||
1390 sscanf(str,"%s@%s",domain,domain) ||
1391 str[0]=='\\')
1392 a1+=({str});
Zesstra25387d92017-02-03 20:20:56 +01001393 }
Arathorn4c2c85d2020-03-09 23:12:26 +01001394
Zesstra25387d92017-02-03 20:20:56 +01001395// printf("DEBUG ENDE: %O\n",a1);
1396
Arathorn0a8e4d32020-07-29 18:36:59 +02001397 a1=filter(a1, function int (string x) {
1398 return(sizeof(x)>1);
1399 });
Zesstra25387d92017-02-03 20:20:56 +01001400
1401 return(map(a1,#'lower_case));
Arathorn4c2c85d2020-03-09 23:12:26 +01001402}
Zesstra25387d92017-02-03 20:20:56 +01001403
1404
1405static mixed GetAlias(mixed a) { return process_names(aliases[a]); }
1406#ifdef MAIL_SUPPORT_BCC
1407static mixed RecurseProcessNames(mixed a) { return process_names(a); }
1408#endif
1409
1410
1411static mapping Read_mailrc(string file) {
1412 mapping al;
1413 int i;
1414 mixed ar;
1415 string s1,s2;
1416
1417 if (!(ar=read_file(file))) {
1418// write(file+" not readable\n");
1419 return ([]);
1420 }
1421 al=([]);
1422 ar=explode(ar,"\n");
1423 for (i=sizeof(ar)-1;i>=0;i--)
Arathorn4c2c85d2020-03-09 23:12:26 +01001424 if (sscanf(ar[i],"%s %s",s1,s2)==2)
Zesstra25387d92017-02-03 20:20:56 +01001425 al+=([s1:s2]);
1426// printf("Got aliases %O",al);
1427 return al;
1428}
1429
1430
1431string * unify_array(string * a) {
1432// int i;
1433// for (i=sizeof(a)-1;i>=0;i--) a=a-({a[i]})+({a[i]});
1434// Rikus 14.02.2001
1435 a=m_indices(mkmapping(a));
1436 return a;
1437}
1438
1439
1440string GetReTitle(string s) {
1441 int nr,s2;
1442
1443 if (!s) s="";
1444 if (s[0..7]=="Re: Re: ") return "Re^3: "+s[8..];
1445 else if (sscanf(s,"Re^%d: %s",nr,s2))
1446 return "Re^"+(nr+1)+": "+s2;
1447 else return "Re: "+s;
1448}
1449
1450
1451int * GetNumbers(mixed s) {
1452 int i,h1,h2;
1453 mixed ret;
Arathorn4c2c85d2020-03-09 23:12:26 +01001454
Zesstra25387d92017-02-03 20:20:56 +01001455 if (intp(s)) return ({s-1});
1456 if (stringp(s)) s=({s-1});
1457 if (!pointerp(s)) return 0;
1458
1459 ret=({});
1460
1461 for (i=sizeof(s)-1;i>=0;i--) {
1462 if (sscanf(s[i],"%d-%d",h1,h2)==2) {
1463 if (h2-h1>100) {
1464 write("Nicht so viele auf einmal, bitte.\n");
1465 return ({});
1466 }
1467 for (h1--;h1<h2;h1++) ret=ret-({h1})+({h1});
1468 }
1469 else
1470 ret=ret-({h1=to_int(s[i])-1})+({h1});
1471 }
1472 ret=sort_array(ret,#'>); //')
1473 DEBUGVAR(ret);
1474 if (ret[0]<0) {
1475 write("Illegale Nummer: "+(ret[0]+1)+", nichts unter 1 bitte!\n");
1476 return ({});
1477 }
1478 if (ret[<1]>=sizeof(folders[1][akt_folder])) {
1479 write("Illegale Nummer: "+(ret[<1]+1)+", so gross ist dieser Ordner nicht!\n");
1480 return ({});
1481 }
1482 return ret;
1483}
1484
1485
1486/*
1487int is_number(string s) {
1488 return (s[0]>='0'&&s[0]<='9');
1489}
1490*/
1491
1492
1493string GetFolderName(mixed fol) { // int oder string. alles andere -> Fehler!
1494 mixed h;
1495
1496 if (fol=="+") fol=akt_folder+1;
1497 if (fol=="-") fol=akt_folder-1;
1498 if ((!fol)||(intp(fol))||(IS_NUMBER(fol))) {
1499 if (!intp(fol)) fol=to_int(fol)-1;
Arathorn4c2c85d2020-03-09 23:12:26 +01001500 if (fol<0||fol>=sizeof(folders[0]))
Zesstra25387d92017-02-03 20:20:56 +01001501 return write("Einen Ordner mit Nummer "+(fol+1)+" gibt es nicht.\n"),0;
1502 return folders[0][fol];
1503 }
1504 fol=lower_case(fol);
1505 if (sizeof(h=regexp(folders[0],"^"+fol))==1) return h[0];
1506 if (member(folders[0],fol)==-1)
1507 return write("Einen Ordner mit Namen "+fol+" hast Du nicht.\n"),0;
1508 return fol;
1509}
1510
1511int query_prevent_shadow() { return 1; }