|
|
1.1 root 1: /* netmail.cpp */
2:
3: /* Synchronet network mail-related functions */
4:
1.1.1.2 ! root 5: /* $Id: netmail.cpp,v 1.42 2011/08/30 22:51:21 rswindell Exp $ */
1.1 root 6:
7: /****************************************************************************
8: * @format.tab-size 4 (Plain Text/Source Code File Header) *
9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
10: * *
1.1.1.2 ! root 11: * Copyright 2011 Rob Swindell - http://www.synchro.net/copyright.html *
1.1 root 12: * *
13: * This program is free software; you can redistribute it and/or *
14: * modify it under the terms of the GNU General Public License *
15: * as published by the Free Software Foundation; either version 2 *
16: * of the License, or (at your option) any later version. *
17: * See the GNU General Public License for more details: gpl.txt or *
18: * http://www.fsf.org/copyleft/gpl.html *
19: * *
20: * Anonymous FTP access to the most recent released source is available at *
21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
22: * *
23: * Anonymous CVS access to the development source and modification history *
24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
26: * (just hit return, no password is necessary) *
27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
28: * *
29: * For Synchronet coding style and modification guidelines, see *
30: * http://www.synchro.net/source.html *
31: * *
32: * You are encouraged to submit any modifications (preferably in Unix diff *
33: * format) via e-mail to [email protected] *
34: * *
35: * Note: If this box doesn't appear square, then you need to fix your tabs. *
36: ****************************************************************************/
37:
38: #include "sbbs.h"
39: #include "qwk.h"
40:
41: /****************************************************************************/
42: /****************************************************************************/
1.1.1.2 ! root 43: bool sbbs_t::inetmail(const char *into, const char *subj, long mode)
1.1 root 44: {
45: char str[256],str2[256],msgpath[256],title[256],name[256],ch
46: ,buf[SDT_BLOCK_LEN],*p,addr[256];
47: char tmp[512];
1.1.1.2 ! root 48: char pid[128];
! 49: char* editor=NULL;
1.1 root 50: char your_addr[128];
51: ushort xlat=XLAT_NONE,net=NET_INTERNET;
52: int i,j,x,file;
53: long l;
54: ulong length,offset;
55: FILE *instream;
56: smbmsg_t msg;
57:
1.1.1.2 ! root 58: if(useron.etoday>=cfg.level_emailperday[useron.level] && !SYSOP && !(useron.exempt&FLAG('M'))) {
1.1 root 59: bputs(text[TooManyEmailsToday]);
60: return(false);
61: }
62:
1.1.1.2 ! root 63: SAFECOPY(name,into);
! 64: SAFECOPY(addr,into);
! 65: SAFECOPY(title,subj);
1.1 root 66:
67: if((!SYSOP && !(cfg.inetmail_misc&NMAIL_ALLOW)) || useron.rest&FLAG('M')) {
68: bputs(text[NoNetMailAllowed]);
1.1.1.2 ! root 69: return(false);
! 70: }
1.1 root 71:
72: if(cfg.inetmail_cost && !(useron.exempt&FLAG('S'))) {
73: if(useron.cdt+useron.freecdt<cfg.inetmail_cost) {
74: bputs(text[NotEnoughCredits]);
1.1.1.2 ! root 75: return(false);
! 76: }
1.1 root 77: sprintf(str,text[NetMailCostContinueQ],cfg.inetmail_cost);
78: if(noyes(str))
1.1.1.2 ! root 79: return(false);
! 80: }
1.1 root 81:
82: /* Get destination user name */
83: p=strrchr(name,'@');
84: if(!p)
85: p=strrchr(name,'!');
86: if(p) {
87: *p=0;
1.1.1.2 ! root 88: truncsp(name);
! 89: }
1.1 root 90:
91: /* Get this user's internet mailing address */
92: usermailaddr(&cfg,your_addr
93: ,cfg.inetmail_misc&NMAIL_ALIAS ? useron.alias : useron.name);
94:
95: bprintf(text[InternetMailing],addr,your_addr);
96: action=NODE_SMAL;
97: nodesync();
98:
99: sprintf(msgpath,"%snetmail.msg",cfg.node_dir);
1.1.1.2 ! root 100: if(!writemsg(msgpath,nulstr,title,mode,INVALID_SUB,into,&editor)) {
1.1 root 101: bputs(text[Aborted]);
1.1.1.2 ! root 102: return(false);
! 103: }
1.1 root 104:
105: if(mode&WM_FILE) {
106: sprintf(str2,"%sfile/%04u.out",cfg.data_dir,useron.number);
107: MKDIR(str2);
108: sprintf(str2,"%sfile/%04u.out/%s",cfg.data_dir,useron.number,title);
109: if(fexistcase(str2)) {
110: bputs(text[FileAlreadyThere]);
111: remove(msgpath);
1.1.1.2 ! root 112: return(false);
! 113: }
1.1 root 114: { /* Remote */
115: xfer_prot_menu(XFER_UPLOAD);
116: mnemonics(text[ProtocolOrQuit]);
117: strcpy(str,"Q");
118: for(x=0;x<cfg.total_prots;x++)
1.1.1.2 ! root 119: if(cfg.prot[x]->ulcmd[0] && chk_ar(cfg.prot[x]->ar,&useron,&client)) {
1.1 root 120: sprintf(tmp,"%c",cfg.prot[x]->mnemonic);
1.1.1.2 ! root 121: strcat(str,tmp);
! 122: }
1.1 root 123: ch=(char)getkeys(str,0);
124: if(ch=='Q' || sys_status&SS_ABORT) {
125: bputs(text[Aborted]);
126: remove(msgpath);
1.1.1.2 ! root 127: return(false);
! 128: }
1.1 root 129: for(x=0;x<cfg.total_prots;x++)
130: if(cfg.prot[x]->ulcmd[0] && cfg.prot[x]->mnemonic==ch
1.1.1.2 ! root 131: && chk_ar(cfg.prot[x]->ar,&useron,&client))
1.1 root 132: break;
133: if(x<cfg.total_prots) /* This should be always */
134: protocol(cfg.prot[x],XFER_UPLOAD,str2,nulstr,true);
135: }
136: sprintf(tmp,"%s%s",cfg.temp_dir,title);
137: if(!fexistcase(str2) && fexistcase(tmp))
138: mv(tmp,str2,0);
1.1.1.2 ! root 139: l=(long)flength(str2);
1.1 root 140: if(l>0)
141: bprintf(text[FileNBytesReceived],title,ultoac(l,tmp));
142: else {
143: bprintf(text[FileNotReceived],title);
144: remove(msgpath);
1.1.1.2 ! root 145: return(false);
! 146: }
! 147: }
1.1 root 148:
149: if((i=smb_stack(&smb,SMB_STACK_PUSH))!=SMB_SUCCESS) {
150: errormsg(WHERE,ERR_OPEN,"MAIL",i);
1.1.1.2 ! root 151: return(false);
! 152: }
1.1 root 153: sprintf(smb.file,"%smail",cfg.data_dir);
154: smb.retry_time=cfg.smb_retry_time;
155: smb.subnum=INVALID_SUB;
156: if((i=smb_open(&smb))!=SMB_SUCCESS) {
157: smb_stack(&smb,SMB_STACK_POP);
158: errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error);
1.1.1.2 ! root 159: return(false);
! 160: }
1.1 root 161:
162: if(filelength(fileno(smb.shd_fp))<1) { /* Create it if it doesn't exist */
163: smb.status.max_crcs=cfg.mail_maxcrcs;
164: smb.status.max_age=cfg.mail_maxage;
165: smb.status.max_msgs=0;
166: smb.status.attr=SMB_EMAIL;
167: if((i=smb_create(&smb))!=SMB_SUCCESS) {
168: smb_close(&smb);
169: smb_stack(&smb,SMB_STACK_POP);
1.1.1.2 ! root 170: errormsg(WHERE,ERR_CREATE,smb.file,i,smb.last_error);
! 171: return(false);
! 172: }
! 173: }
1.1 root 174:
175: if((i=smb_locksmbhdr(&smb))!=SMB_SUCCESS) {
176: smb_close(&smb);
177: smb_stack(&smb,SMB_STACK_POP);
1.1.1.2 ! root 178: errormsg(WHERE,ERR_LOCK,smb.file,i,smb.last_error);
! 179: return(false);
! 180: }
1.1 root 181:
1.1.1.2 ! root 182: length=(long)flength(msgpath)+2; /* +2 for translation string */
1.1 root 183:
184: if(length&0xfff00000UL) {
185: smb_unlocksmbhdr(&smb);
186: smb_close(&smb);
187: smb_stack(&smb,SMB_STACK_POP);
188: errormsg(WHERE,ERR_LEN,msgpath,length);
1.1.1.2 ! root 189: return(false);
! 190: }
1.1 root 191:
192: if((i=smb_open_da(&smb))!=SMB_SUCCESS) {
193: smb_unlocksmbhdr(&smb);
194: smb_close(&smb);
195: smb_stack(&smb,SMB_STACK_POP);
196: errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error);
1.1.1.2 ! root 197: return(false);
! 198: }
1.1 root 199: if(cfg.sys_misc&SM_FASTMAIL)
200: offset=smb_fallocdat(&smb,length,1);
201: else
202: offset=smb_allocdat(&smb,length,1);
203: smb_close_da(&smb);
204:
205: if((file=open(msgpath,O_RDONLY|O_BINARY))==-1
206: || (instream=fdopen(file,"rb"))==NULL) {
207: smb_freemsgdat(&smb,offset,length,1);
208: smb_unlocksmbhdr(&smb);
209: smb_close(&smb);
210: smb_stack(&smb,SMB_STACK_POP);
211: errormsg(WHERE,ERR_OPEN,msgpath,O_RDONLY|O_BINARY);
1.1.1.2 ! root 212: return(false);
! 213: }
1.1 root 214:
215: setvbuf(instream,NULL,_IOFBF,2*1024);
216: fseek(smb.sdt_fp,offset,SEEK_SET);
217: xlat=XLAT_NONE;
218: fwrite(&xlat,2,1,smb.sdt_fp);
219: x=SDT_BLOCK_LEN-2; /* Don't read/write more than 255 */
220: while(!feof(instream)) {
221: memset(buf,0,x);
222: j=fread(buf,1,x,instream);
223: if(j<1)
224: break;
225: if(j>1 && (j!=x || feof(instream)) && buf[j-1]==LF && buf[j-2]==CR)
226: buf[j-1]=buf[j-2]=0;
227: fwrite(buf,j,1,smb.sdt_fp);
1.1.1.2 ! root 228: x=SDT_BLOCK_LEN;
! 229: }
1.1 root 230: fflush(smb.sdt_fp);
231: fclose(instream);
232:
233: memset(&msg,0,sizeof(smbmsg_t));
234: msg.hdr.version=smb_ver();
235: if(mode&WM_FILE)
236: msg.hdr.auxattr|=MSG_FILEATTACH;
237: msg.hdr.when_written.time=msg.hdr.when_imported.time=time(NULL);
238: msg.hdr.when_written.zone=msg.hdr.when_imported.zone=sys_timezone(&cfg);
239:
240: msg.hdr.offset=offset;
241:
242: net=NET_INTERNET;
243: smb_hfield_str(&msg,RECIPIENT,name);
244: smb_hfield(&msg,RECIPIENTNETTYPE,sizeof(net),&net);
245: smb_hfield_str(&msg,RECIPIENTNETADDR,addr);
246:
1.1.1.2 ! root 247: smb_hfield_str(&msg,SENDER,cfg.inetmail_misc&NMAIL_ALIAS ? useron.alias : useron.name);
1.1 root 248:
249: sprintf(str,"%u",useron.number);
250: smb_hfield_str(&msg,SENDEREXT,str);
251:
252: /*
253: smb_hfield(&msg,SENDERNETTYPE,sizeof(net),&net);
254: smb_hfield(&msg,SENDERNETADDR,strlen(sys_inetaddr),sys_inetaddr);
255: */
256:
257: /* Security logging */
258: msg_client_hfields(&msg,&client);
1.1.1.2 ! root 259: smb_hfield_str(&msg,SENDERSERVER,startup->host_name);
1.1 root 260:
261: smb_hfield_str(&msg,SUBJECT,title);
1.1.1.2 ! root 262:
! 263: /* Generate FidoNet Program Identifier */
! 264: smb_hfield_str(&msg,FIDOPID,msg_program_id(pid));
! 265:
! 266: if(editor!=NULL)
! 267: smb_hfield_str(&msg,SMB_EDITOR,editor);
1.1 root 268:
269: smb_dfield(&msg,TEXT_BODY,length);
270:
271: i=smb_addmsghdr(&smb,&msg,SMB_SELFPACK); // calls smb_unlocksmbhdr()
272: smb_close(&smb);
273: smb_stack(&smb,SMB_STACK_POP);
274:
275: smb_freemsgmem(&msg);
276: if(i!=SMB_SUCCESS) {
277: errormsg(WHERE,ERR_WRITE,smb.file,i,smb.last_error);
278: smb_freemsgdat(&smb,offset,length,1);
279: return(false);
280: }
281:
282: if(mode&WM_FILE && online==ON_REMOTE)
283: autohangup();
284:
285: if(cfg.inetmail_sem[0]) /* update semaphore file */
286: ftouch(cmdstr(cfg.inetmail_sem,nulstr,nulstr,NULL));
287: if(!(useron.exempt&FLAG('S')))
288: subtract_cdt(&cfg,&useron,cfg.inetmail_cost);
289:
290: useron.emails++;
291: logon_emails++;
292: putuserrec(&cfg,useron.number,U_EMAILS,5,ultoa(useron.emails,tmp,10));
293: useron.etoday++;
294: putuserrec(&cfg,useron.number,U_ETODAY,5,ultoa(useron.etoday,tmp,10));
295:
296: sprintf(str,"%s sent Internet Mail to %s (%s)"
297: ,useron.alias
298: ,name,addr);
299: logline("EN",str);
300: return(true);
301: }
302:
1.1.1.2 ! root 303: bool sbbs_t::qnetmail(const char *into, const char *subj, long mode)
1.1 root 304: {
305: char str[256],msgpath[128],title[128],to[128],fulladdr[128]
306: ,buf[SDT_BLOCK_LEN],*addr;
307: char tmp[512];
1.1.1.2 ! root 308: char pid[128];
! 309: char* editor=NULL;
1.1 root 310: ushort xlat=XLAT_NONE,net=NET_QWK,touser;
311: int i,j,x,file;
312: ulong length,offset;
313: FILE *instream;
314: smbmsg_t msg;
315:
1.1.1.2 ! root 316: if(useron.etoday>=cfg.level_emailperday[useron.level] && !SYSOP && !(useron.exempt&FLAG('M'))) {
1.1 root 317: bputs(text[TooManyEmailsToday]);
318: return(false);
319: }
320:
1.1.1.2 ! root 321: SAFECOPY(to,into);
! 322: SAFECOPY(title,subj);
1.1 root 323:
324: if(useron.rest&FLAG('M')) {
325: bputs(text[NoNetMailAllowed]);
1.1.1.2 ! root 326: return(false);
! 327: }
1.1 root 328:
329: addr=strrchr(to,'@');
330: if(!addr) {
331: bputs(text[InvalidNetMailAddr]);
332: return(false);
333: }
334: *addr=0;
335: addr++;
336: strupr(addr);
337: truncsp(addr);
338: touser=qwk_route(addr,fulladdr);
339: if(!fulladdr[0]) {
340: bputs(text[InvalidNetMailAddr]);
341: return(false);
342: }
343:
344: truncsp(to);
345: if(!stricmp(to,"SBBS") && !SYSOP) {
346: bputs(text[InvalidNetMailAddr]);
347: return(false);
348: }
349: bprintf(text[NetMailing],to,fulladdr
350: ,useron.alias,cfg.sys_id);
351: action=NODE_SMAL;
352: nodesync();
353:
354: sprintf(msgpath,"%snetmail.msg",cfg.node_dir);
1.1.1.2 ! root 355: if(!writemsg(msgpath,nulstr,title,mode|WM_QWKNET,INVALID_SUB,to,&editor)) {
1.1 root 356: bputs(text[Aborted]);
1.1.1.2 ! root 357: return(false);
! 358: }
1.1 root 359:
360: if((i=smb_stack(&smb,SMB_STACK_PUSH))!=SMB_SUCCESS) {
361: errormsg(WHERE,ERR_OPEN,"MAIL",i);
1.1.1.2 ! root 362: return(false);
! 363: }
1.1 root 364: sprintf(smb.file,"%smail",cfg.data_dir);
365: smb.retry_time=cfg.smb_retry_time;
366: smb.subnum=INVALID_SUB;
367: if((i=smb_open(&smb))!=SMB_SUCCESS) {
368: smb_stack(&smb,SMB_STACK_POP);
369: errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error);
1.1.1.2 ! root 370: return(false);
! 371: }
1.1 root 372:
373: if(filelength(fileno(smb.shd_fp))<1) { /* Create it if it doesn't exist */
374: smb.status.max_crcs=cfg.mail_maxcrcs;
375: smb.status.max_msgs=0;
376: smb.status.max_age=cfg.mail_maxage;
377: smb.status.attr=SMB_EMAIL;
378: if((i=smb_create(&smb))!=SMB_SUCCESS) {
379: smb_close(&smb);
380: smb_stack(&smb,SMB_STACK_POP);
381: errormsg(WHERE,ERR_CREATE,smb.file,i,smb.last_error);
1.1.1.2 ! root 382: return(false);
! 383: }
! 384: }
1.1 root 385:
386: if((i=smb_locksmbhdr(&smb))!=SMB_SUCCESS) {
387: smb_close(&smb);
388: smb_stack(&smb,SMB_STACK_POP);
389: errormsg(WHERE,ERR_LOCK,smb.file,i,smb.last_error);
1.1.1.2 ! root 390: return(false);
! 391: }
1.1 root 392:
1.1.1.2 ! root 393: length=(long)flength(msgpath)+2; /* +2 for translation string */
1.1 root 394:
395: if(length&0xfff00000UL) {
396: smb_unlocksmbhdr(&smb);
397: smb_close(&smb);
398: smb_stack(&smb,SMB_STACK_POP);
399: errormsg(WHERE,ERR_LEN,msgpath,length);
1.1.1.2 ! root 400: return(false);
! 401: }
1.1 root 402:
403: if((i=smb_open_da(&smb))!=SMB_SUCCESS) {
404: smb_unlocksmbhdr(&smb);
405: smb_close(&smb);
406: smb_stack(&smb,SMB_STACK_POP);
407: errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error);
1.1.1.2 ! root 408: return(false);
! 409: }
1.1 root 410: if(cfg.sys_misc&SM_FASTMAIL)
411: offset=smb_fallocdat(&smb,length,1);
412: else
413: offset=smb_allocdat(&smb,length,1);
414: smb_close_da(&smb);
415:
416: if((file=open(msgpath,O_RDONLY|O_BINARY))==-1
417: || (instream=fdopen(file,"rb"))==NULL) {
418: smb_freemsgdat(&smb,offset,length,1);
419: smb_unlocksmbhdr(&smb);
420: smb_close(&smb);
421: smb_stack(&smb,SMB_STACK_POP);
422: errormsg(WHERE,ERR_OPEN,msgpath,O_RDONLY|O_BINARY);
1.1.1.2 ! root 423: return(false);
! 424: }
1.1 root 425:
426: setvbuf(instream,NULL,_IOFBF,2*1024);
427: fseek(smb.sdt_fp,offset,SEEK_SET);
428: xlat=XLAT_NONE;
429: fwrite(&xlat,2,1,smb.sdt_fp);
430: x=SDT_BLOCK_LEN-2; /* Don't read/write more than 255 */
431: while(!feof(instream)) {
432: memset(buf,0,x);
433: j=fread(buf,1,x,instream);
434: if(j<1)
435: break;
436: if(j>1 && (j!=x || feof(instream)) && buf[j-1]==LF && buf[j-2]==CR)
437: buf[j-1]=buf[j-2]=0;
438: fwrite(buf,j,1,smb.sdt_fp);
1.1.1.2 ! root 439: x=SDT_BLOCK_LEN;
! 440: }
1.1 root 441: fflush(smb.sdt_fp);
442: fclose(instream);
443:
444: memset(&msg,0,sizeof(smbmsg_t));
445: msg.hdr.version=smb_ver();
446: if(mode&WM_FILE)
447: msg.hdr.auxattr|=MSG_FILEATTACH;
448: msg.hdr.when_written.time=msg.hdr.when_imported.time=time(NULL);
449: msg.hdr.when_written.zone=msg.hdr.when_imported.zone=sys_timezone(&cfg);
450:
451: msg.hdr.offset=offset;
452:
453: net=NET_QWK;
454: smb_hfield_str(&msg,RECIPIENT,to);
455: sprintf(str,"%u",touser);
456: smb_hfield_str(&msg,RECIPIENTEXT,str);
457: smb_hfield(&msg,RECIPIENTNETTYPE,sizeof(net),&net);
458: smb_hfield_str(&msg,RECIPIENTNETADDR,fulladdr);
459:
460: smb_hfield_str(&msg,SENDER,useron.alias);
461:
462: sprintf(str,"%u",useron.number);
463: smb_hfield_str(&msg,SENDEREXT,str);
464:
465: /* Security logging */
466: msg_client_hfields(&msg,&client);
1.1.1.2 ! root 467: smb_hfield_str(&msg,SENDERSERVER,startup->host_name);
1.1 root 468:
469: smb_hfield_str(&msg,SUBJECT,title);
470:
1.1.1.2 ! root 471: /* Generate FidoNet Program Identifier */
! 472: smb_hfield_str(&msg,FIDOPID,msg_program_id(pid));
! 473:
! 474: if(editor!=NULL)
! 475: smb_hfield_str(&msg,SMB_EDITOR,editor);
! 476:
1.1 root 477: smb_dfield(&msg,TEXT_BODY,length);
478:
479: i=smb_addmsghdr(&smb,&msg,SMB_SELFPACK); // calls smb_unlocksmbhdr()
480: smb_close(&smb);
481: smb_stack(&smb,SMB_STACK_POP);
482:
483: smb_freemsgmem(&msg);
484: if(i!=SMB_SUCCESS) {
485: errormsg(WHERE,ERR_WRITE,smb.file,i,smb.last_error);
486: smb_freemsgdat(&smb,offset,length,1);
487: return(false);
488: }
489:
490: useron.emails++;
491: logon_emails++;
492: putuserrec(&cfg,useron.number,U_EMAILS,5,ultoa(useron.emails,tmp,10));
493: useron.etoday++;
494: putuserrec(&cfg,useron.number,U_ETODAY,5,ultoa(useron.etoday,tmp,10));
495:
496: sprintf(str,"%s sent QWK NetMail to %s (%s)"
497: ,useron.alias
498: ,to,fulladdr);
499: logline("EN",str);
500: return(true);
501: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.