readmail.cpp 20 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
/* readmail.cpp */

/* Synchronet private mail reading function */

/* $Id$ */

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
11
 * Copyright 2005 Rob Swindell - http://www.synchro.net/copyright.html		*
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
 *																			*
 * This program is free software; you can redistribute it and/or			*
 * modify it under the terms of the GNU General Public License				*
 * as published by the Free Software Foundation; either version 2			*
 * of the License, or (at your option) any later version.					*
 * See the GNU General Public License for more details: gpl.txt or			*
 * http://www.fsf.org/copyleft/gpl.html										*
 *																			*
 * Anonymous FTP access to the most recent released source is available at	*
 * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net	*
 *																			*
 * Anonymous CVS access to the development source and modification history	*
 * is available at cvs.synchro.net:/cvsroot/sbbs, example:					*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login			*
 *     (just hit return, no password is necessary)							*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src		*
 *																			*
 * For Synchronet coding style and modification guidelines, see				*
 * http://www.synchro.net/source.html										*
 *																			*
 * You are encouraged to submit any modifications (preferably in Unix diff	*
 * format) via e-mail to mods@synchro.net									*
 *																			*
 * Note: If this box doesn't appear square, then you need to fix your tabs.	*
 ****************************************************************************/

#include "sbbs.h"

/****************************************************************************/
/* Reads mail waiting for usernumber.                                       */
/****************************************************************************/
void sbbs_t::readmail(uint usernumber, int which)
{
	char	str[256],str2[256],str3[256],done=0,domsg=1
46
			,*p,*tp,*sp,ch;
47
	char 	tmp[512];
48
	int		i,j;
rswindell's avatar
rswindell committed
49
	int		error;
50
51
52
53
54
55
56
57
	int		mismatches=0,act;
    long    length,l,lm_mode;
	ulong	last;
	bool	replied;
	file_t	fd;
	mail_t	*mail;
	smbmsg_t msg;

58
59
60
61
62
	if(which==MAIL_SENT && useron.rest&FLAG('K')) {
		bputs(text[R_ReadSentMail]);
		return;
	}

63
64
65
66
67
68
69
	msg.total_hfields=0;			/* init to NULL, cause not allocated yet */

	fd.dir=cfg.total_dirs+1;			/* temp dir for file attachments */

	if((i=smb_stack(&smb,SMB_STACK_PUSH))!=0) {
		errormsg(WHERE,ERR_OPEN,"MAIL",i);
		return; }
70
	sprintf(smb.file,"%smail",cfg.data_dir);
71
	smb.retry_time=cfg.smb_retry_time;
72
	smb.subnum=INVALID_SUB;
73
74
75
76
77
78
79
80
81
	if((i=smb_open(&smb))!=0) {
		smb_stack(&smb,SMB_STACK_POP);
		errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error);
		return; }

	if(cfg.sys_misc&SM_SYSVDELM && (SYSOP || cfg.sys_misc&SM_USRVDELM))
		lm_mode=LM_INCDEL;
	else
		lm_mode=0;
82
83
	mail=loadmail(&smb,&smb.msgs,usernumber,which,lm_mode);
	if(!smb.msgs) {
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
		if(which==MAIL_SENT)
			bputs(text[NoMailSent]);
		else if(which==MAIL_ALL)
			bputs(text[NoMailOnSystem]);
		else
			bputs(text[NoMailWaiting]);
		smb_close(&smb);
		smb_stack(&smb,SMB_STACK_POP);
		return; }

	last=smb.status.last_msg;

	if(which==MAIL_SENT)
		act=NODE_RSML;
	else if(which==MAIL_ALL)
		act=NODE_SYSP;
	else
		act=NODE_RMAL;
	action=act;
103
	if(smb.msgs>1 && which!=MAIL_ALL) {
104
105
106
107
108
		if(which==MAIL_SENT)
			bputs(text[MailSentLstHdr]);
		else
			bputs(text[MailWaitingLstHdr]);

109
		for(smb.curmsg=0;smb.curmsg<smb.msgs && !msgabort();smb.curmsg++) {
110
111
112
			if(msg.total_hfields)
				smb_freemsgmem(&msg);
			msg.total_hfields=0;
113
114
			msg.idx.offset=mail[smb.curmsg].offset;
			if(!loadmsg(&msg,mail[smb.curmsg].number))
115
116
				continue;
			smb_unlockmsghdr(&smb,&msg);
117
			bprintf(text[MailWaitingLstFmt],smb.curmsg+1
118
119
120
121
122
123
124
125
126
127
128
129
130
				,which==MAIL_SENT ? msg.to
				: (msg.hdr.attr&MSG_ANONYMOUS) && !SYSOP ? text[Anonymous]
				: msg.from
				,msg.hdr.attr&MSG_DELETE ? '-' : msg.hdr.attr&MSG_REPLIED ? 'R'
					: msg.hdr.attr&MSG_READ ? ' '
					: msg.from_net.type || msg.to_net.type ? 'N':'*'
				,msg.subj);
			smb_freemsgmem(&msg);
			msg.total_hfields=0; }

		ASYNC;
		if(!(sys_status&SS_ABORT)) {
			bprintf(text[StartWithN],1L);
131
132
133
			if((long)(smb.curmsg=getnum(smb.msgs))>0)
				smb.curmsg--;
			else if((long)smb.curmsg==-1) {
deuce's avatar
deuce committed
134
				free(mail);
135
136
137
138
139
				smb_close(&smb);
				smb_stack(&smb,SMB_STACK_POP);
				return; } }
		sys_status&=~SS_ABORT; }
	else {
140
		smb.curmsg=0;
141
142
		if(which==MAIL_ALL)
			domsg=0; }
143
144
145
146
147
148
149
150
151
152
	if(which==MAIL_SENT) {
		sprintf(str,"%s read sent mail",useron.alias);
		logline("E",str);
	} else if(which==MAIL_ALL) {
		sprintf(str,"%s read all mail",useron.alias);
		logline("S+",str);
	} else {
		sprintf(str,"%s read mail",useron.alias);
		logline("E",str);
	}
153
	if(useron.misc&RIP) {
154
155
		strcpy(str,which==MAIL_YOUR ? "mailread" : which==MAIL_ALL ?
			"allmail" : "sentmail");
156
157
158
159
160
161
162
163
		menu(str); }
	while(online && !done) {
		action=act;

		if(msg.total_hfields)
			smb_freemsgmem(&msg);
		msg.total_hfields=0;

164
165
166
167
168
		msg.idx.offset=mail[smb.curmsg].offset;
		msg.idx.number=mail[smb.curmsg].number;
		msg.idx.to=mail[smb.curmsg].to;
		msg.idx.from=mail[smb.curmsg].from;
		msg.idx.subj=mail[smb.curmsg].subj;
169
170
171
172
173
174
175
176
177
178
179
180
181

		if((i=smb_locksmbhdr(&smb))!=0) {
			errormsg(WHERE,ERR_LOCK,smb.file,i);
			break; }

		if((i=smb_getstatus(&smb))!=0) {
			smb_unlocksmbhdr(&smb);
			errormsg(WHERE,ERR_READ,smb.file,i);
			break; }
		smb_unlocksmbhdr(&smb);

		if(smb.status.last_msg!=last) { 	/* New messages */
			last=smb.status.last_msg;
deuce's avatar
deuce committed
182
			free(mail);
183
184
			mail=loadmail(&smb,&smb.msgs,usernumber,which,lm_mode);   /* So re-load */
			if(!smb.msgs)
185
				break;
186
187
			for(smb.curmsg=0;smb.curmsg<smb.msgs;smb.curmsg++)
				if(mail[smb.curmsg].number==msg.idx.number)
188
					break;
189
190
			if(smb.curmsg>=smb.msgs)
				smb.curmsg=(smb.msgs-1);
191
192
			continue; }

193
		if(!loadmsg(&msg,mail[smb.curmsg].number)) {	/* Message header gone */
194
			if(mismatches>5) {	/* We can't do this too many times in a row */
195
				errormsg(WHERE,ERR_CHK,"message number",mail[smb.curmsg].number);
196
				break; }
deuce's avatar
deuce committed
197
			free(mail);
198
199
			mail=loadmail(&smb,&smb.msgs,usernumber,which,lm_mode);
			if(!smb.msgs)
200
				break;
201
202
			if(smb.curmsg>(smb.msgs-1))
				smb.curmsg=(smb.msgs-1);
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
			mismatches++;
			continue; }
		smb_unlockmsghdr(&smb,&msg);
		msg.idx.attr=msg.hdr.attr;

		mismatches=0;

		if(domsg && !(sys_status&SS_ABORT)) {

			show_msg(&msg
				,msg.from_ext && msg.idx.from==1 && !msg.from_net.type
					? 0:P_NOATCODES);

			if(msg.hdr.auxattr&MSG_FILEATTACH) {  /* Attached file */
				smb_getmsgidx(&smb,&msg);
				strcpy(str,msg.subj);					/* filenames in title */
219
//				strupr(str);
220
221
				tp=str;
				while(online) {
222
					p=strchr(tp,' ');
223
224
225
226
227
					if(p) *p=0;
					sp=strrchr(tp,'/');              /* sp is slash pointer */
					if(!sp) sp=strrchr(tp,'\\');
					if(sp) tp=sp+1;
					padfname(tp,fd.name);
228
					sprintf(str2,"%sfile/%04u.in/%s"  /* str2 is path/fname */
229
230
231
232
233
234
235
236
237
238
239
						,cfg.data_dir,msg.idx.to,tp);
					length=flength(str2);
					if(length<1)
						bputs(text[FileNotFound]);
					else if(!(useron.exempt&FLAG('T')) && cur_cps && !SYSOP
						&& length/(long)cur_cps>(time_t)timeleft)
						bputs(text[NotEnoughTimeToDl]);
					else {
						sprintf(str3,text[DownloadAttachedFileQ]
							,tp,ultoac(length,tmp));
						if(length>0L && yesno(str3)) {
rswindell's avatar
rswindell committed
240
#if 0	/* no such thing as local logon */
241
242
							if(online==ON_LOCAL) {
								bputs(text[EnterPath]);
243
								if(getstr(str3,60,K_LINE)) {
244
245
246
247
248
249
250
251
252
253
254
255
									backslashcolon(str3);
									sprintf(tmp,"%s%s",str3,tp);
									if(!mv(str2,tmp,which!=MAIL_YOUR)) {
										logon_dlb+=length;
										logon_dls++;
										useron.dls=(ushort)adjustuserrec(&cfg,useron.number
											,U_DLS,5,1);
										useron.dlb=adjustuserrec(&cfg,useron.number
											,U_DLB,10,length);
										bprintf(text[FileNBytesSent]
											,fd.name,ultoac(length,tmp)); } } }

rswindell's avatar
rswindell committed
256
257
258
							else 
#endif
							{	/* Remote User */
259
								xfer_prot_menu(XFER_DOWNLOAD);
260
261
262
263
264
265
266
267
268
269
270
271
272
								mnemonics(text[ProtocolOrQuit]);
								strcpy(str3,"Q");
								for(i=0;i<cfg.total_prots;i++)
									if(cfg.prot[i]->dlcmd[0]
										&& chk_ar(cfg.prot[i]->ar,&useron)) {
										sprintf(tmp,"%c",cfg.prot[i]->mnemonic);
										strcat(str3,tmp); }
								ch=(char)getkeys(str3,0);
								for(i=0;i<cfg.total_prots;i++)
									if(cfg.prot[i]->dlcmd[0] && ch==cfg.prot[i]->mnemonic
										&& chk_ar(cfg.prot[i]->ar,&useron))
										break;
								if(i<cfg.total_prots) {
273
									error=protocol(cfg.prot[i],XFER_DOWNLOAD,str2,nulstr,false);
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
									if(checkprotresult(cfg.prot[i],error,&fd)) {
										if(which==MAIL_YOUR)
											remove(str2);
										logon_dlb+=length;	/* Update stats */
										logon_dls++;
										useron.dls=(ushort)adjustuserrec(&cfg,useron.number
											,U_DLS,5,1);
										useron.dlb=adjustuserrec(&cfg,useron.number
											,U_DLB,10,length);
										bprintf(text[FileNBytesSent]
											,fd.name,ultoac(length,tmp));
										sprintf(str3
											,"%s downloaded attached file: %s"
											,useron.alias
											,fd.name);
										logline("D-",str3); 
									}
									autohangup(); 
								} 
							} 
						} 
					}
					if(!p)
						break;
					tp=p+1;
299
					while(*tp==' ') tp++; 
300
				}
301
				sprintf(str,"%sfile/%04u.in",cfg.data_dir,usernumber);
302
303
				rmdir(str); }
			if(which==MAIL_YOUR && !(msg.hdr.attr&MSG_READ)) {
304
				mail[smb.curmsg].attr|=MSG_READ;
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
				if(thisnode.status==NODE_INUSE)
					telluser(&msg);
				if(msg.total_hfields)
					smb_freemsgmem(&msg);
				msg.total_hfields=0;
				msg.idx.offset=0;						/* Search by number */
				if(!smb_locksmbhdr(&smb)) { 			/* Lock the entire base */
					if(loadmsg(&msg,msg.idx.number)) {
						msg.hdr.attr|=MSG_READ;
						msg.idx.attr=msg.hdr.attr;
						if((i=smb_putmsg(&smb,&msg))!=0)
							errormsg(WHERE,ERR_WRITE,smb.file,i);
						smb_unlockmsghdr(&smb,&msg); }
					smb_unlocksmbhdr(&smb); }
				if(!msg.total_hfields) {				/* unsuccessful reload */
					domsg=0;
					continue; } }
			}
		else domsg=1;

		if(useron.misc&WIP) {
326
327
			strcpy(str,which==MAIL_YOUR ? "mailread" : which==MAIL_ALL ?
				"allmail" : "sentmail");
328
329
330
331
			menu(str); }

		ASYNC;
		if(which==MAIL_SENT)
332
			bprintf(text[ReadingSentMail],smb.curmsg+1,smb.msgs);
333
		else if(which==MAIL_ALL)
334
			bprintf(text[ReadingAllMail],smb.curmsg+1,smb.msgs);
335
		else
336
			bprintf(text[ReadingMail],smb.curmsg+1,smb.msgs);
337
338
		sprintf(str,"ADFLNQRT?<>[]{}-+");
		if(SYSOP)
339
			strcat(str,"CUSPH");
340
341
		if(which!=MAIL_YOUR)
			strcat(str,"E");
342
		l=getkeys(str,smb.msgs);
343
344
345
		if(l&0x80000000L) {
			if(l==-1)	/* ctrl-c */
				break;
346
			smb.curmsg=(l&~0x80000000L)-1;
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
			continue; }
		switch(l) {
			case 'A':   /* Auto-reply to last piece */
			case 'R':
				if(l==(cfg.sys_misc&SM_RA_EMU ? 'A' : 'R'))  /* re-read last message */
					break;

				if(which==MAIL_SENT)
					break;
				if((msg.hdr.attr&MSG_ANONYMOUS) && !SYSOP) {
					bputs(text[CantReplyToAnonMsg]);
					break; }

				quotemsg(&msg,1);

362
363
364
				if(msg.from_net.addr==NULL)
					strcpy(str,msg.from);
				else if(msg.from_net.type==NET_FIDO) 	/* FidoNet type */
365
					sprintf(str,"%s@%s",msg.from
366
						,smb_faddrtoa((faddr_t *)msg.from_net.addr,tmp));
367
368
				else if(msg.from_net.type==NET_INTERNET)
					strcpy(str,(char *)msg.from_net.addr);
369
				else
rswindell's avatar
rswindell committed
370
					sprintf(str,"%s@%s",msg.from,(char*)msg.from_net.addr);
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396

				strcpy(str2,str);

				bputs(text[Email]);
				if(!getstr(str,64,K_EDIT|K_AUTODEL))
					break;
				msg.hdr.number=msg.idx.number;
				smb_getmsgidx(&smb,&msg);

				if(!stricmp(str2,str))		/* Reply to sender */
					sprintf(str2,text[Regarding],msg.subj);
				else						/* Reply to other */
					sprintf(str2,text[RegardingByOn],msg.subj,msg.from
						,timestr((time_t *)&msg.hdr.when_written.time));

				p=strrchr(str,'@');
				if(p) { 							/* name @addr */
					replied=netmail(str,msg.subj,WM_QUOTE);
					sprintf(str2,text[DeleteMailQ],msg.from); }
				else {
					if(!msg.from_net.type && !stricmp(str,msg.from))
						replied=email(msg.idx.from,str2,msg.subj,WM_EMAIL|WM_QUOTE);
					else if(!stricmp(str,"SYSOP"))
						replied=email(1,str2,msg.subj,WM_EMAIL|WM_QUOTE);
					else if((i=finduser(str))!=0)
						replied=email(i,str2,msg.subj,WM_EMAIL|WM_QUOTE);
397
398
					else
						replied=false;
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
					sprintf(str2,text[DeleteMailQ],msg.from); }

				if(replied==true && !(msg.hdr.attr&MSG_REPLIED)) {
					if(msg.total_hfields)
						smb_freemsgmem(&msg);
					msg.total_hfields=0;
					msg.idx.offset=0;
					if(loadmsg(&msg,msg.idx.number)) {
						msg.hdr.attr|=MSG_REPLIED;
						msg.idx.attr=msg.hdr.attr;
						if((i=smb_putmsg(&smb,&msg))!=0)
							errormsg(WHERE,ERR_WRITE,smb.file,i);
						smb_unlockmsghdr(&smb,&msg); }
				}

414
				if(msg.hdr.attr&MSG_DELETE || !yesno(str2)) {
415
					if(smb.curmsg<smb.msgs-1) smb.curmsg++;
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
					else done=1;
					break;	}
				/* Case 'D': must follow! */
			case 'D':   /* Delete last piece (toggle) */
				if(msg.hdr.attr&MSG_PERMANENT) {
					bputs("\r\nPermanent message.\r\n");
					domsg=0;
					break; }
				if(msg.total_hfields)
					smb_freemsgmem(&msg);
				msg.total_hfields=0;
				msg.idx.offset=0;
				if(loadmsg(&msg,msg.idx.number)) {
					msg.hdr.attr^=MSG_DELETE;
					msg.idx.attr=msg.hdr.attr;
431
	//				  mail[smb.curmsg].attr=msg.hdr.attr;
432
433
434
					if((i=smb_putmsg(&smb,&msg))!=0)
						errormsg(WHERE,ERR_WRITE,smb.file,i);
					smb_unlockmsghdr(&smb,&msg); }
435
				if(smb.curmsg<smb.msgs-1) smb.curmsg++;
436
437
438
439
440
				else done=1;
				break;
			case 'F':  /* Forward last piece */
				domsg=0;
				bputs(text[ForwardMailTo]);
441
				if(!getstr(str,LEN_ALIAS,cfg.uq&UQ_NOUPRLWR ? K_NONE:K_UPRLWR))
442
443
444
445
446
					break;
				i=finduser(str);
				if(!i)
					break;
				domsg=1;
447
				if(smb.curmsg<smb.msgs-1) smb.curmsg++;
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
				else done=1;
				smb_getmsgidx(&smb,&msg);
				forwardmail(&msg,i);
				if(msg.hdr.attr&MSG_PERMANENT)
					break;
				sprintf(str2,text[DeleteMailQ],msg.from);
				if(!yesno(str2))
					break;
				if(msg.total_hfields)
					smb_freemsgmem(&msg);
				msg.total_hfields=0;
				msg.idx.offset=0;
				if(loadmsg(&msg,msg.idx.number)) {
					msg.hdr.attr|=MSG_DELETE;
					msg.idx.attr=msg.hdr.attr;
463
	//				  mail[smb.curmsg].attr=msg.hdr.attr;
464
465
466
467
					if((i=smb_putmsg(&smb,&msg))!=0)
						errormsg(WHERE,ERR_WRITE,smb.file,i);
					smb_unlockmsghdr(&smb,&msg); }

468
469
				break;
			case 'H':
470
				domsg=0;
471
				msghdr(&msg);
472
473
474
				break;
			case 'L':     /* List mail */
				domsg=0;
475
476
				bprintf(text[StartWithN],(long)smb.curmsg+1);
				if((i=getnum(smb.msgs))>0)
477
478
479
480
					i--;
				else if(i==-1)
					break;
				else
481
					i=smb.curmsg;
482
483
484
485
486
487
				if(which==MAIL_SENT)
					bputs(text[MailSentLstHdr]);
				else if(which==MAIL_ALL)
					bputs(text[MailOnSystemLstHdr]);
				else
					bputs(text[MailWaitingLstHdr]);
488
				for(;i<smb.msgs && !msgabort();i++) {
489
490
491
492
493
494
495
496
497
498
499
					if(msg.total_hfields)
						smb_freemsgmem(&msg);
					msg.total_hfields=0;
					msg.idx.offset=mail[i].offset;
					if(!loadmsg(&msg,mail[i].number))
						continue;
					smb_unlockmsghdr(&smb,&msg);
					if(which==MAIL_ALL)
						bprintf(text[MailOnSystemLstFmt]
							,i+1,msg.from,msg.to
							,msg.hdr.attr&MSG_DELETE ? '-' : msg.hdr.attr&MSG_REPLIED ? 'R'
500
								: msg.hdr.attr&MSG_READ ? ' '
501
502
503
504
505
506
507
508
								: msg.from_net.type || msg.to_net.type ? 'N':'*'
							,msg.subj);
					else
						bprintf(text[MailWaitingLstFmt],i+1
							,which==MAIL_SENT ? msg.to
							: (msg.hdr.attr&MSG_ANONYMOUS) && !SYSOP
							? text[Anonymous] : msg.from
							,msg.hdr.attr&MSG_DELETE ? '-' : msg.hdr.attr&MSG_REPLIED ? 'R'
509
								: msg.hdr.attr&MSG_READ ? ' '
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
								: msg.from_net.type || msg.to_net.type ? 'N':'*'
							,msg.subj);
					smb_freemsgmem(&msg);
					msg.total_hfields=0; }
				break;
			case 'Q':
				done=1;
				break;
			case 'C':   /* Change attributes of last piece */
				i=chmsgattr(msg.hdr.attr);
				if(msg.hdr.attr==i)
					break;
				if(msg.total_hfields)
					smb_freemsgmem(&msg);
				msg.total_hfields=0;
				msg.idx.offset=0;
				if(loadmsg(&msg,msg.idx.number)) {
					msg.hdr.attr=msg.idx.attr=(ushort)i;
					if((i=smb_putmsg(&smb,&msg))!=0)
						errormsg(WHERE,ERR_WRITE,smb.file,i);
					smb_unlockmsghdr(&smb,&msg); }
				break;
			case '>':
533
				for(i=smb.curmsg+1;i<smb.msgs;i++)
534
535
					if(mail[i].subj==msg.idx.subj)
						break;
536
537
				if(i<smb.msgs)
					smb.curmsg=i;
538
539
540
541
				else
					domsg=0;
				break;
			case '<':   /* Search Title backward */
542
				for(i=smb.curmsg-1;i>-1;i--)
543
544
545
					if(mail[i].subj==msg.idx.subj)
						break;
				if(i>-1)
546
					smb.curmsg=i;
547
548
549
550
551
				else
					domsg=0;
				break;
			case '}':   /* Search Author forward */
				strcpy(str,msg.from);
552
				for(i=smb.curmsg+1;i<smb.msgs;i++)
553
554
					if(mail[i].from==msg.idx.from)
						break;
555
556
				if(i<smb.msgs)
					smb.curmsg=i;
557
558
559
560
				else
					domsg=0;
				break;
			case 'N':   /* Got to next un-read message */
561
				for(i=smb.curmsg+1;i<smb.msgs;i++)
562
563
					if(!(mail[i].attr&MSG_READ))
						break;
564
565
				if(i<smb.msgs)
					smb.curmsg=i;
566
567
568
569
570
				else
					domsg=0;
				break;
			case '{':   /* Search Author backward */
				strcpy(str,msg.from);
571
				for(i=smb.curmsg-1;i>-1;i--)
572
573
574
					if(mail[i].from==msg.idx.from)
						break;
				if(i>-1)
575
					smb.curmsg=i;
576
577
578
579
580
				else
					domsg=0;
				break;
			case ']':   /* Search To User forward */
				strcpy(str,msg.to);
581
				for(i=smb.curmsg+1;i<smb.msgs;i++)
582
583
					if(mail[i].to==msg.idx.to)
						break;
584
585
				if(i<smb.msgs)
					smb.curmsg=i;
586
587
588
589
590
				else
					domsg=0;
				break;
			case '[':   /* Search To User backward */
				strcpy(str,msg.to);
591
				for(i=smb.curmsg-1;i>-1;i--)
592
593
					if(mail[i].to==msg.idx.to)
						break;
rswindell's avatar
rswindell committed
594
				if(i>-1)
595
					smb.curmsg=i;
596
597
598
599
600
				else
					domsg=0;
				break;
			case 0:
			case '+':
601
				if(smb.curmsg<smb.msgs-1) smb.curmsg++;
602
603
604
				else done=1;
				break;
			case '-':
605
				if(smb.curmsg>0) smb.curmsg--;
606
607
608
609
610
611
612
613
				break;
			case 'S':
				domsg=0;
	/*
				if(!yesno(text[SaveMsgToFile]))
					break;
	*/
				bputs(text[FileToWriteTo]);
614
				if(getstr(str,40,K_LINE))
615
616
617
618
619
620
621
					msgtotxt(&msg,str,1,1);
				break;
			case 'E':
				editmsg(&msg,INVALID_SUB);
				break;
			case 'T':
				domsg=0;
622
				i=smb.curmsg;
623
624
				if(i) i++;
				j=i+10;
625
626
				if(j>smb.msgs)
					j=smb.msgs;
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645

				if(which==MAIL_SENT)
					bputs(text[MailSentLstHdr]);
				else if(which==MAIL_ALL)
					bputs(text[MailOnSystemLstHdr]);
				else
					bputs(text[MailWaitingLstHdr]);
				for(;i<j;i++) {
					if(msg.total_hfields)
						smb_freemsgmem(&msg);
					msg.total_hfields=0;
					msg.idx.offset=mail[i].offset;
					if(!loadmsg(&msg,mail[i].number))
						continue;
					smb_unlockmsghdr(&smb,&msg);
					if(which==MAIL_ALL)
						bprintf(text[MailOnSystemLstFmt]
							,i+1,msg.from,msg.to
							,msg.hdr.attr&MSG_DELETE ? '-' : msg.hdr.attr&MSG_REPLIED ? 'R'
646
								: msg.hdr.attr&MSG_READ ? ' ' 
647
648
649
650
651
652
653
654
								: msg.from_net.type || msg.to_net.type ? 'N':'*'
							,msg.subj);
					else
						bprintf(text[MailWaitingLstFmt],i+1
							,which==MAIL_SENT ? msg.to
							: (msg.hdr.attr&MSG_ANONYMOUS) && !SYSOP
							? text[Anonymous] : msg.from
							,msg.hdr.attr&MSG_DELETE ? '-' : msg.hdr.attr&MSG_REPLIED ? 'R'
655
								: msg.hdr.attr&MSG_READ ? ' '
656
657
658
659
								: msg.from_net.type || msg.to_net.type ? 'N':'*'
							,msg.subj);
					smb_freemsgmem(&msg);
					msg.total_hfields=0; }
660
				smb.curmsg=(i-1);
661
662
663
664
				break;
			case 'U':   /* user edit */
				msg.hdr.number=msg.idx.number;
				smb_getmsgidx(&smb,&msg);
665
				useredit(which==MAIL_SENT ? msg.idx.to : msg.idx.from);
666
667
668
669
670
671
672
				break;
			case 'P':   /* Purge author and all mail to/from */
				if(noyes(text[AreYouSureQ]))
					break;
				msg.hdr.number=msg.idx.number;
				smb_getmsgidx(&smb,&msg);
				purgeuser(msg.idx.from);
673
				if(smb.curmsg<smb.msgs-1) smb.curmsg++;
674
675
				break;
			case '?':
676
677
				strcpy(str,which==MAIL_YOUR ? "mailread" : which==MAIL_ALL
						? "allmail" : "sentmail");
678
679
				menu(str);
				if(SYSOP && which==MAIL_SENT)
680
					menu("syssmail");
681
				else if(SYSOP && which==MAIL_YOUR)
682
					menu("sysmailr");   /* Sysop Mail Read */
683
684
685
686
687
688
689
				domsg=0;
				break;
				} }

	if(msg.total_hfields)
		smb_freemsgmem(&msg);

690
	if(smb.msgs)
deuce's avatar
deuce committed
691
		free(mail);
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706

	/***************************************/
	/* Delete messages marked for deletion */
	/***************************************/

	if(cfg.sys_misc&SM_DELEMAIL) {
		if((i=smb_locksmbhdr(&smb))!=0) 			/* Lock the base, so nobody */
			errormsg(WHERE,ERR_LOCK,smb.file,i);	/* messes with the index */
		else
			delmail(usernumber,which); }

	smb_close(&smb);
	smb_stack(&smb,SMB_STACK_POP);
}