|
|
1.1 root 1: /* fido.cpp */
2:
3: /* Synchronet FidoNet-related routines */
4:
1.1.1.2 ! root 5: /* $Id: fido.cpp,v 1.49 2011/08/25 07:48:40 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 2010 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:
1.1.1.2 ! root 38: /* TODO: This file is made up almost *entirely* of copy/pasted crap and */
! 39: /* it needs to go away - FTN netmail should be handled by sbbsecho anyway. */
! 40:
1.1 root 41: #include "sbbs.h"
42: #include "qwk.h"
43:
44: faddr_t atofaddr(scfg_t* cfg, char *str);
45:
46: void pt_zone_kludge(fmsghdr_t hdr,int fido)
47: {
48: char str[256];
49:
50: sprintf(str,"\1INTL %hu:%hu/%hu %hu:%hu/%hu\r"
51: ,hdr.destzone,hdr.destnet,hdr.destnode
52: ,hdr.origzone,hdr.orignet,hdr.orignode);
53: write(fido,str,strlen(str));
54:
55: if(hdr.destpoint) {
56: sprintf(str,"\1TOPT %hu\r"
57: ,hdr.destpoint);
1.1.1.2 ! root 58: write(fido,str,strlen(str));
! 59: }
1.1 root 60:
61: if(hdr.origpoint) {
62: sprintf(str,"\1FMPT %hu\r"
63: ,hdr.origpoint);
1.1.1.2 ! root 64: write(fido,str,strlen(str));
! 65: }
1.1 root 66: }
67:
68: bool sbbs_t::lookup_netuser(char *into)
69: {
70: char to[128],name[26],str[256],q[128];
71: int i;
72: FILE *stream;
73:
74: if(strchr(into,'@'))
75: return(false);
76: strcpy(to,into);
77: strupr(to);
78: sprintf(str,"%sqnet/users.dat", cfg.data_dir);
79: if((stream=fnopen(&i,str,O_RDONLY))==NULL)
80: return(false);
81: while(!feof(stream)) {
82: if(!fgets(str,sizeof(str),stream))
83: break;
84: str[25]=0;
85: truncsp(str);
86: strcpy(name,str);
87: strupr(name);
88: str[35]=0;
89: truncsp(str+27);
90: sprintf(q,"Do you mean %s @%s",str,str+27);
91: if(strstr(name,to) && yesno(q)) {
92: fclose(stream);
93: sprintf(into,"%s@%s",str,str+27);
1.1.1.2 ! root 94: return(true);
! 95: }
1.1 root 96: if(sys_status&SS_ABORT)
1.1.1.2 ! root 97: break;
! 98: }
1.1 root 99: fclose(stream);
100: return(false);
101: }
102:
103: /****************************************************************************/
104: /* Send FidoNet/QWK/Internet NetMail from BBS */
105: /****************************************************************************/
1.1.1.2 ! root 106: bool sbbs_t::netmail(const char *into, const char *title, long mode)
1.1 root 107: {
108: char str[256],subj[128],to[256],fname[128],*buf,*p,ch;
109: char tmp[512];
110: int file,fido,x,cc_found,cc_sent;
111: uint i;
112: long length,l;
113: faddr_t addr;
114: fmsghdr_t hdr;
115: struct tm tm;
116:
1.1.1.2 ! root 117: if(useron.etoday>=cfg.level_emailperday[useron.level] && !SYSOP && !(useron.exempt&FLAG('M'))) {
1.1 root 118: bputs(text[TooManyEmailsToday]);
119: return(false);
120: }
121:
122: SAFECOPY(subj,title);
123:
124: strcpy(to,into);
125:
126: lookup_netuser(to);
127:
128: p=strrchr(to,'@'); /* Find '@' in name@addr */
129: if(p && !isdigit(*(p+1)) && !strchr(p,'.') && !strchr(p,':')) {
130: mode&=~WM_FILE;
131: qnetmail(to,title,mode|WM_NETMAIL);
1.1.1.2 ! root 132: return(false);
! 133: }
1.1 root 134: if(!cfg.total_faddrs || p==NULL || !strchr(p+1,'/')) {
135: if(!p && cfg.dflt_faddr.zone)
136: addr=cfg.dflt_faddr;
137: else if(cfg.inetmail_misc&NMAIL_ALLOW) {
138: if(mode&WM_FILE && !SYSOP && !(cfg.inetmail_misc&NMAIL_FILE))
139: mode&=~WM_FILE;
140: return(inetmail(into,title,mode|WM_NETMAIL));
141: }
142: else if(cfg.dflt_faddr.zone)
143: addr=cfg.dflt_faddr;
144: else {
145: bputs(text[InvalidNetMailAddr]);
146: return(false);
147: }
148: } else {
149: addr=atofaddr(&cfg,p+1); /* Get fido address */
150: *p=0; /* Chop off address */
151: }
152:
153: if(mode&WM_FILE && !SYSOP && !(cfg.netmail_misc&NMAIL_FILE))
154: mode&=~WM_FILE;
155:
156: if((!SYSOP && !(cfg.netmail_misc&NMAIL_ALLOW)) || useron.rest&FLAG('M')
157: || !cfg.total_faddrs) {
158: bputs(text[NoNetMailAllowed]);
159: return(false);
160: }
161:
162: truncsp(to); /* Truncate off space */
163:
164: memset(&hdr,0,sizeof(hdr)); /* Initialize header to null */
165: strcpy(hdr.from,cfg.netmail_misc&NMAIL_ALIAS ? useron.alias : useron.name);
166: SAFECOPY(hdr.to,to);
167:
168: /* Look-up in nodelist? */
169:
170: if(cfg.netmail_cost && !(useron.exempt&FLAG('S'))) {
171: if(useron.cdt+useron.freecdt<cfg.netmail_cost) {
172: bputs(text[NotEnoughCredits]);
173: return(false);
174: }
175: sprintf(str,text[NetMailCostContinueQ],cfg.netmail_cost);
176: if(noyes(str))
177: return(false);
178: }
179:
180: now=time(NULL);
181: if(localtime_r(&now,&tm)!=NULL)
182: sprintf(hdr.time,"%02u %3.3s %02u %02u:%02u:%02u"
183: ,tm.tm_mday,mon[tm.tm_mon],TM_YEAR(tm.tm_year)
184: ,tm.tm_hour,tm.tm_min,tm.tm_sec);
185:
186: hdr.destzone =addr.zone;
187: hdr.destnet =addr.net;
188: hdr.destnode =addr.node;
189: hdr.destpoint =addr.point;
190:
191: for(i=0;i<cfg.total_faddrs;i++)
192: if(addr.zone==cfg.faddr[i].zone && addr.net==cfg.faddr[i].net)
193: break;
194: if(i==cfg.total_faddrs) {
195: for(i=0;i<cfg.total_faddrs;i++)
196: if(addr.zone==cfg.faddr[i].zone)
197: break;
198: }
199: if(i==cfg.total_faddrs)
200: i=0;
201: hdr.origzone =cfg.faddr[i].zone;
202: hdr.orignet =cfg.faddr[i].net;
203: hdr.orignode =cfg.faddr[i].node;
204: hdr.origpoint =cfg.faddr[i].point;
205:
206: smb_faddrtoa(&cfg.faddr[i],str);
207: bprintf(text[NetMailing],hdr.to,smb_faddrtoa(&addr,tmp),hdr.from,str);
208:
209: hdr.attr=(FIDO_LOCAL|FIDO_PRIVATE);
210:
211: if(cfg.netmail_misc&NMAIL_CRASH) hdr.attr|=FIDO_CRASH;
212: if(cfg.netmail_misc&NMAIL_HOLD) hdr.attr|=FIDO_HOLD;
213: if(cfg.netmail_misc&NMAIL_KILL) hdr.attr|=FIDO_KILLSENT;
214: if(mode&WM_FILE) hdr.attr|=FIDO_FILE;
215:
216: sprintf(str,"%sNETMAIL.MSG", cfg.node_dir);
217: remove(str); /* Just incase it's already there */
218: // mode&=~WM_FILE;
219: if(!writemsg(str,nulstr,subj,WM_NETMAIL|mode,INVALID_SUB,into)) {
220: bputs(text[Aborted]);
221: return(false);
222: }
223:
224: if(mode&WM_FILE) {
225: strcpy(fname,subj);
226: sprintf(str,"%sfile/%04u.out", cfg.data_dir, useron.number);
227: MKDIR(str);
228: strcpy(tmp, cfg.data_dir);
229: if(tmp[0]=='.') /* Relative path */
230: sprintf(tmp,"%s%s", cfg.node_dir, cfg.data_dir);
231: sprintf(str,"%sfile/%04u.out/%s",tmp,useron.number,fname);
232: strcpy(subj,str);
233: if(fexistcase(str)) {
234: bputs(text[FileAlreadyThere]);
1.1.1.2 ! root 235: return(false);
! 236: }
1.1 root 237: { /* Remote */
238: xfer_prot_menu(XFER_UPLOAD);
239: mnemonics(text[ProtocolOrQuit]);
240: strcpy(str,"Q");
241: for(x=0;x<cfg.total_prots;x++)
1.1.1.2 ! root 242: if(cfg.prot[x]->ulcmd[0] && chk_ar(cfg.prot[x]->ar,&useron,&client)) {
1.1 root 243: sprintf(tmp,"%c",cfg.prot[x]->mnemonic);
1.1.1.2 ! root 244: strcat(str,tmp);
! 245: }
1.1 root 246: ch=(char)getkeys(str,0);
247: if(ch=='Q' || sys_status&SS_ABORT) {
248: bputs(text[Aborted]);
1.1.1.2 ! root 249: return(false);
! 250: }
1.1 root 251: for(x=0;x<cfg.total_prots;x++)
252: if(cfg.prot[x]->ulcmd[0] && cfg.prot[x]->mnemonic==ch
1.1.1.2 ! root 253: && chk_ar(cfg.prot[x]->ar,&useron,&client))
1.1 root 254: break;
255: if(x<cfg.total_prots) /* This should be always */
256: protocol(cfg.prot[x],XFER_UPLOAD,subj,nulstr,true);
257: }
258: sprintf(tmp,"%s%s",cfg.temp_dir,title);
259: if(!fexistcase(subj) && fexistcase(tmp))
260: mv(tmp,subj,0);
1.1.1.2 ! root 261: l=(long)flength(subj);
1.1 root 262: if(l>0)
263: bprintf(text[FileNBytesReceived],fname,ultoac(l,tmp));
264: else {
265: bprintf(text[FileNotReceived],fname);
266: return(false);
267: }
268: }
269:
270: p=subj;
271: if((SYSOP || useron.exempt&FLAG('F'))
272: && !strnicmp(p,"CR:",3)) { /* Crash over-ride by sysop */
273: p+=3; /* skip CR: */
274: if(*p==' ') p++; /* skip extra space if it exists */
1.1.1.2 ! root 275: hdr.attr|=FIDO_CRASH;
! 276: }
1.1 root 277:
278: if((SYSOP || useron.exempt&FLAG('F'))
279: && !strnicmp(p,"FR:",3)) { /* File request */
280: p+=3; /* skip FR: */
281: if(*p==' ') p++;
1.1.1.2 ! root 282: hdr.attr|=FIDO_FREQ;
! 283: }
1.1 root 284:
285: if((SYSOP || useron.exempt&FLAG('F'))
286: && !strnicmp(p,"RR:",3)) { /* Return receipt request */
287: p+=3; /* skip RR: */
288: if(*p==' ') p++;
1.1.1.2 ! root 289: hdr.attr|=FIDO_RRREQ;
! 290: }
1.1 root 291:
292: if((SYSOP || useron.exempt&FLAG('F'))
293: && !strnicmp(p,"FA:",3)) { /* File Attachment */
294: p+=3; /* skip FA: */
295: if(*p==' ') p++;
1.1.1.2 ! root 296: hdr.attr|=FIDO_FILE;
! 297: }
1.1 root 298:
299: SAFECOPY(hdr.subj,p);
300:
301: sprintf(str,"%sNETMAIL.MSG", cfg.node_dir);
302: if((file=nopen(str,O_RDONLY))==-1) {
303: errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
1.1.1.2 ! root 304: return(false);
! 305: }
! 306: length=(long)filelength(file);
1.1 root 307: if((buf=(char *)malloc(length))==NULL) {
308: close(file);
309: errormsg(WHERE,ERR_ALLOC,str,length);
1.1.1.2 ! root 310: return(false);
! 311: }
1.1 root 312: read(file,buf,length);
313: close(file);
314:
1.1.1.2 ! root 315: md(cfg.netmail_dir);
1.1 root 316: cc_sent=0;
317: while(1) {
318: for(i=1;i;i++) {
319: sprintf(str,"%s%u.msg", cfg.netmail_dir,i);
320: if(!fexistcase(str))
1.1.1.2 ! root 321: break;
! 322: }
1.1 root 323: if(!i) {
324: bputs(text[TooManyEmailsToday]);
1.1.1.2 ! root 325: return(false);
! 326: }
1.1 root 327: if((fido=nopen(str,O_WRONLY|O_CREAT|O_EXCL))==-1) {
328: errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_EXCL);
1.1.1.2 ! root 329: return(false);
! 330: }
1.1 root 331: write(fido,&hdr,sizeof(hdr));
332:
333: pt_zone_kludge(hdr,fido);
334:
335: if(cfg.netmail_misc&NMAIL_DIRECT) {
1.1.1.2 ! root 336: SAFECOPY(str,"\1FLAGS DIR\r\n");
! 337: write(fido,str,strlen(str));
! 338: }
1.1 root 339: if(mode&WM_FILE) {
1.1.1.2 ! root 340: SAFECOPY(str,"\1FLAGS KFS\r\n");
! 341: write(fido,str,strlen(str));
! 342: }
1.1 root 343:
344: if(cc_sent) {
1.1.1.2 ! root 345: SAFEPRINTF(str,"* Originally to: %s\r\n\r\n",into);
! 346: write(fido,str,strlen(str));
! 347: }
1.1 root 348:
349: l=0L;
350: while(l<length) {
1.1.1.2 ! root 351: if(buf[l]==CTRL_A) { /* Ctrl-A, so skip it and the next char */
1.1 root 352: l++;
1.1.1.2 ! root 353: if(l>=length || toupper(buf[l])=='Z') /* EOF */
! 354: break;
! 355: if((ch=ctrl_a_to_ascii_char(buf[l])) != 0)
! 356: write(fido,&ch,1);
! 357: }
1.1 root 358: else if(buf[l]!=LF) {
359: if((uchar)buf[l]==0x8d) /* r0dent i converted to normal i */
360: buf[l]='i';
1.1.1.2 ! root 361: write(fido,buf+l,1);
! 362: }
! 363: l++;
! 364: }
1.1 root 365: l=0;
366: write(fido,&l,1); /* Null terminator */
367: close(fido);
368:
369: useron.emails++;
370: logon_emails++;
371: putuserrec(&cfg,useron.number,U_EMAILS,5,ultoa(useron.emails,tmp,10));
372: useron.etoday++;
373: putuserrec(&cfg,useron.number,U_ETODAY,5,ultoa(useron.etoday,tmp,10));
374:
375: if(!(useron.exempt&FLAG('S')))
376: subtract_cdt(&cfg,&useron,cfg.netmail_cost);
377: if(mode&WM_FILE)
378: sprintf(str,"%s sent NetMail file attachment to %s (%s)"
379: ,useron.alias
380: ,hdr.to,smb_faddrtoa(&addr,tmp));
381: else
382: sprintf(str,"%s sent NetMail to %s (%s)"
383: ,useron.alias
384: ,hdr.to,smb_faddrtoa(&addr,tmp));
385: logline("EN",str);
386:
387: cc_found=0;
388: for(l=0;l<length && cc_found<=cc_sent;l++)
389: if(l+3<length && !strnicmp(buf+l,"CC:",3)) {
390: cc_found++;
1.1.1.2 ! root 391: l+=2;
! 392: }
1.1 root 393: else {
394: while(l<length && *(buf+l)!=LF)
1.1.1.2 ! root 395: l++;
! 396: }
1.1 root 397: if(!cc_found)
398: break;
399: while(l<length && *(buf+l)==' ') l++;
400: for(i=0;l<length && *(buf+l)!=LF && i<128;i++,l++)
401: str[i]=buf[l];
402: if(!i)
403: break;
404: str[i]=0;
405: p=strrchr(str,'@');
406: if(p) {
407: addr=atofaddr(&cfg,p+1);
408: *p=0;
1.1.1.2 ! root 409: SAFECOPY(hdr.to,str);
! 410: }
1.1 root 411: else {
412: atofaddr(&cfg,str);
1.1.1.2 ! root 413: strcpy(hdr.to,"Sysop");
! 414: }
1.1 root 415: hdr.destzone =addr.zone;
416: hdr.destnet =addr.net;
417: hdr.destnode =addr.node;
418: hdr.destpoint =addr.point;
1.1.1.2 ! root 419: cc_sent++;
! 420: }
1.1 root 421:
422: if(cfg.netmail_sem[0]) /* update semaphore file */
423: ftouch(cmdstr(cfg.netmail_sem,nulstr,nulstr,NULL));
424:
425: free(buf);
426: return(true);
427: }
428:
429: /****************************************************************************/
430: /* Send NetMail from QWK REP Packet */
431: /****************************************************************************/
432: void sbbs_t::qwktonetmail(FILE *rep, char *block, char *into, uchar fromhub)
433: {
434: char *qwkbuf,to[129],name[129],sender[129],senderaddr[129]
435: ,str[256],*p,*cp,*addr,fulladdr[129],ch;
436: char tmp[512];
437: int i,fido,inet=0,qnet=0;
1.1.1.2 ! root 438: ushort net;
! 439: uint16_t xlat;
1.1 root 440: long l,offset,length,m,n;
441: faddr_t fidoaddr;
442: fmsghdr_t hdr;
443: smbmsg_t msg;
444: struct tm tm;
445:
446: if(useron.rest&FLAG('M')) {
447: bputs(text[NoNetMailAllowed]);
1.1.1.2 ! root 448: return;
! 449: }
! 450:
! 451: to[0]=0;
! 452: name[0]=0;
! 453: sender[0]=0;
! 454: senderaddr[0]=0;
! 455: fulladdr[0]=0;
1.1 root 456:
457: sprintf(str,"%.6s",block+116);
458: n=atol(str); /* i = number of 128 byte records */
459:
460: if(n<2L || n>999999L) {
461: errormsg(WHERE,ERR_CHK,"QWK blocks",n);
1.1.1.2 ! root 462: return;
! 463: }
1.1 root 464: if((qwkbuf=(char *)malloc(n*QWK_BLOCK_LEN))==NULL) {
465: errormsg(WHERE,ERR_ALLOC,nulstr,n*QWK_BLOCK_LEN);
1.1.1.2 ! root 466: return;
! 467: }
1.1 root 468: memcpy((char *)qwkbuf,block,QWK_BLOCK_LEN);
469: fread(qwkbuf+QWK_BLOCK_LEN,n-1,QWK_BLOCK_LEN,rep);
470:
471: if(into==NULL)
472: sprintf(to,"%-128.128s",(char *)qwkbuf+QWK_BLOCK_LEN); /* To user on first line */
473: else
1.1.1.2 ! root 474: SAFECOPY(to,into);
1.1 root 475:
476: p=strchr(to,QWK_NEWLINE); /* chop off at first CR */
477: if(p) *p=0;
478:
1.1.1.2 ! root 479: SAFECOPY(name,to);
1.1 root 480: p=strchr(name,'@');
481: if(p) *p=0;
482: truncsp(name);
483:
484:
485: p=strrchr(to,'@'); /* Find '@' in name@addr */
486: if(p && !isdigit(*(p+1)) && !strchr(p,'.') && !strchr(p,':')) { /* QWKnet */
487: qnet=1;
1.1.1.2 ! root 488: *p=0;
! 489: }
1.1 root 490: else if(p==NULL || !isdigit(*(p+1)) || !cfg.total_faddrs) {
491: if(p==NULL && cfg.dflt_faddr.zone)
492: fidoaddr=cfg.dflt_faddr;
493: else if(cfg.inetmail_misc&NMAIL_ALLOW) { /* Internet */
494: inet=1;
495: }
496: else if(cfg.dflt_faddr.zone)
497: fidoaddr=cfg.dflt_faddr;
498: else {
499: bputs(text[InvalidNetMailAddr]);
500: free(qwkbuf);
1.1.1.2 ! root 501: return;
! 502: }
! 503: }
1.1 root 504: else {
505: fidoaddr=atofaddr(&cfg,p+1); /* Get fido address */
506: *p=0; /* Chop off address */
1.1.1.2 ! root 507: }
1.1 root 508:
509:
510: if(!inet && !qnet && /* FidoNet */
511: ((!SYSOP && !(cfg.netmail_misc&NMAIL_ALLOW)) || !cfg.total_faddrs)) {
512: bputs(text[NoNetMailAllowed]);
513: free(qwkbuf);
1.1.1.2 ! root 514: return;
! 515: }
1.1 root 516:
517: truncsp(to); /* Truncate off space */
518:
519: if(!stricmp(to,"SBBS") && !SYSOP && qnet) {
520: free(qwkbuf);
1.1.1.2 ! root 521: return;
! 522: }
1.1 root 523:
524: l=QWK_BLOCK_LEN; /* Start of message text */
525:
526: if(qnet || inet) {
527:
528: if(into==NULL) { /* If name@addr on first line, skip first line */
529: while(l<(n*QWK_BLOCK_LEN) && qwkbuf[l]!=QWK_NEWLINE) l++;
1.1.1.2 ! root 530: l++;
! 531: }
1.1 root 532:
533: memset(&msg,0,sizeof(smbmsg_t));
534: msg.hdr.version=smb_ver();
535: msg.hdr.when_imported.time=time(NULL);
536: msg.hdr.when_imported.zone=sys_timezone(&cfg);
537:
538: if(fromhub || useron.rest&FLAG('Q')) {
539: net=NET_QWK;
540: smb_hfield(&msg,SENDERNETTYPE,sizeof(net),&net);
541: if(!strncmp(qwkbuf+l,"@VIA:",5)) {
542: sprintf(str,"%.128s",qwkbuf+l+5);
543: cp=strchr(str,QWK_NEWLINE);
544: if(cp) *cp=0;
545: l+=strlen(str)+1;
546: cp=str;
547: while(*cp && *cp<=' ') cp++;
548: sprintf(senderaddr,"%s/%s"
549: ,fromhub ? cfg.qhub[fromhub-1]->id : useron.alias,cp);
550: strupr(senderaddr);
1.1.1.2 ! root 551: smb_hfield(&msg,SENDERNETADDR,strlen(senderaddr),senderaddr);
! 552: }
1.1 root 553: else {
554: if(fromhub)
1.1.1.2 ! root 555: SAFECOPY(senderaddr, cfg.qhub[fromhub-1]->id);
1.1 root 556: else
1.1.1.2 ! root 557: SAFECOPY(senderaddr, useron.alias);
1.1 root 558: strupr(senderaddr);
1.1.1.2 ! root 559: smb_hfield(&msg,SENDERNETADDR,strlen(senderaddr),senderaddr);
! 560: }
! 561: sprintf(sender,"%.25s",block+46); /* From name */
! 562: }
1.1 root 563: else { /* Not Networked */
564: msg.hdr.when_written.zone=sys_timezone(&cfg);
565: sprintf(str,"%u",useron.number);
566: smb_hfield(&msg,SENDEREXT,strlen(str),str);
1.1.1.2 ! root 567: SAFECOPY(sender,(qnet || cfg.inetmail_misc&NMAIL_ALIAS)
1.1 root 568: ? useron.alias : useron.name);
569: }
570: truncsp(sender);
571: smb_hfield(&msg,SENDER,strlen(sender),sender);
572: if(fromhub)
573: msg.idx.from=0;
574: else
575: msg.idx.from=useron.number;
576: if(!strncmp(qwkbuf+l,"@TZ:",4)) {
577: sprintf(str,"%.128s",qwkbuf+l);
578: cp=strchr(str,QWK_NEWLINE);
579: if(cp) *cp=0;
580: l+=strlen(str)+1;
581: cp=str+4;
582: while(*cp && *cp<=' ') cp++;
1.1.1.2 ! root 583: msg.hdr.when_written.zone=(short)ahtoul(cp);
! 584: }
1.1 root 585: else
586: msg.hdr.when_written.zone=sys_timezone(&cfg);
587: memset(&tm,0,sizeof(tm));
588: tm.tm_mon=((qwkbuf[8]&0xf)*10)+(qwkbuf[9]&0xf);
589: if(tm.tm_mon) tm.tm_mon--; /* 0 based */
590: tm.tm_mday=((qwkbuf[11]&0xf)*10)+(qwkbuf[12]&0xf);
591: tm.tm_year=((qwkbuf[14]&0xf)*10)+(qwkbuf[15]&0xf);
592: if(tm.tm_year<Y2K_2DIGIT_WINDOW)
593: tm.tm_year+=100;
594: tm.tm_hour=((qwkbuf[16]&0xf)*10)+(qwkbuf[17]&0xf);
595: tm.tm_min=((qwkbuf[19]&0xf)*10)+(qwkbuf[20]&0xf); /* From QWK time */
596: tm.tm_sec=0;
597:
598: tm.tm_isdst=-1; /* Do not adjust for DST */
599: msg.hdr.when_written.time=mktime(&tm);
600:
601: sprintf(str,"%.25s",block+71); /* Title */
602: smb_hfield(&msg,SUBJECT,strlen(str),str);
603: }
604:
605: if(qnet) {
606:
607: p++;
608: addr=p;
609: msg.idx.to=qwk_route(addr,fulladdr);
610: if(!fulladdr[0]) { /* Invalid address, so BOUNCE it */
611: /**
612: errormsg(WHERE,ERR_CHK,addr,0);
613: free(qwkbuf);
614: smb_freemsgmem(msg);
615: return;
616: **/
617: smb_hfield(&msg,SENDER,strlen(cfg.sys_id),cfg.sys_id);
618: msg.idx.from=0;
619: msg.idx.to=useron.number;
1.1.1.2 ! root 620: SAFECOPY(to,sender);
! 621: SAFECOPY(fulladdr,senderaddr);
! 622: SAFEPRINTF(str,"BADADDR: %s",addr);
1.1 root 623: smb_hfield(&msg,SUBJECT,strlen(str),str);
624: net=NET_NONE;
625: smb_hfield(&msg,SENDERNETTYPE,sizeof(net),&net);
626: }
627: /* This is required for fixsmb to be able to rebuild the index */
1.1.1.2 ! root 628: SAFEPRINTF(str,"%u",msg.idx.to);
1.1 root 629: smb_hfield_str(&msg,RECIPIENTEXT,str);
630:
631: smb_hfield(&msg,RECIPIENT,strlen(name),name);
632: net=NET_QWK;
633: smb_hfield(&msg,RECIPIENTNETTYPE,sizeof(net),&net);
634:
635: truncsp(fulladdr);
1.1.1.2 ! root 636: if(fulladdr[0])
! 637: smb_hfield(&msg,RECIPIENTNETADDR,strlen(fulladdr),fulladdr);
1.1 root 638:
1.1.1.2 ! root 639: bprintf(text[NetMailing],to,fulladdr,sender,cfg.sys_id);
! 640: }
1.1 root 641:
642: if(inet) { /* Internet E-mail */
643:
644: if(cfg.inetmail_cost && !(useron.exempt&FLAG('S'))) {
645: if(useron.cdt+useron.freecdt<cfg.inetmail_cost) {
646: bputs(text[NotEnoughCredits]);
647: free(qwkbuf);
648: smb_freemsgmem(&msg);
1.1.1.2 ! root 649: return;
! 650: }
1.1 root 651: sprintf(str,text[NetMailCostContinueQ],cfg.inetmail_cost);
652: if(noyes(str)) {
653: free(qwkbuf);
654: smb_freemsgmem(&msg);
1.1.1.2 ! root 655: return;
! 656: }
! 657: }
1.1 root 658:
659: net=NET_INTERNET;
660: smb_hfield(&msg,RECIPIENT,strlen(name),name);
661: msg.idx.to=0; /* Out-bound NetMail set to 0 */
662: smb_hfield(&msg,RECIPIENTNETTYPE,sizeof(net),&net);
663: smb_hfield(&msg,RECIPIENTNETADDR,strlen(to),to);
664:
665: bprintf(text[NetMailing],name,to
666: ,cfg.inetmail_misc&NMAIL_ALIAS ? useron.alias : useron.name
1.1.1.2 ! root 667: ,cfg.sys_inetaddr);
! 668: }
1.1 root 669:
670: if(qnet || inet) {
671:
672: bputs(text[WritingIndx]);
673:
674: if((i=smb_stack(&smb,SMB_STACK_PUSH))!=0) {
675: errormsg(WHERE,ERR_OPEN,"MAIL",i);
676: free(qwkbuf);
677: smb_freemsgmem(&msg);
1.1.1.2 ! root 678: return;
! 679: }
1.1 root 680: sprintf(smb.file,"%smail", cfg.data_dir);
681: smb.retry_time=cfg.smb_retry_time;
682: smb.subnum=INVALID_SUB;
683: if((i=smb_open(&smb))!=0) {
684: smb_stack(&smb,SMB_STACK_POP);
685: errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error);
686: free(qwkbuf);
687: smb_freemsgmem(&msg);
1.1.1.2 ! root 688: return;
! 689: }
1.1 root 690:
691: if(smb_fgetlength(smb.shd_fp)<1L) { /* Create it if it doesn't exist */
692: smb.status.max_crcs=cfg.mail_maxcrcs;
693: smb.status.max_msgs=0;
694: smb.status.max_age=cfg.mail_maxage;
695: smb.status.attr=SMB_EMAIL;
696: if((i=smb_create(&smb))!=0) {
697: smb_close(&smb);
698: smb_stack(&smb,SMB_STACK_POP);
699: errormsg(WHERE,ERR_CREATE,smb.file,i,smb.last_error);
700: free(qwkbuf);
701: smb_freemsgmem(&msg);
1.1.1.2 ! root 702: return;
! 703: }
! 704: }
1.1 root 705:
706: length=n*256L; // Extra big for CRLF xlat, was (n-1L)*256L (03/16/96)
707:
708:
709: if(length&0xfff00000UL || !length) {
710: smb_close(&smb);
711: smb_stack(&smb,SMB_STACK_POP);
712: sprintf(str,"REP msg (%ld)",n);
713: errormsg(WHERE,ERR_LEN,str,length);
714: free(qwkbuf);
715: smb_freemsgmem(&msg);
1.1.1.2 ! root 716: return;
! 717: }
1.1 root 718:
719: if((i=smb_open_da(&smb))!=0) {
720: smb_close(&smb);
721: smb_stack(&smb,SMB_STACK_POP);
722: errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error);
723: free(qwkbuf);
724: smb_freemsgmem(&msg);
1.1.1.2 ! root 725: return;
! 726: }
1.1 root 727: if(cfg.sys_misc&SM_FASTMAIL)
728: offset=smb_fallocdat(&smb,length,1);
729: else
730: offset=smb_allocdat(&smb,length,1);
731: smb_close_da(&smb);
732:
733: smb_fseek(smb.sdt_fp,offset,SEEK_SET);
734: xlat=XLAT_NONE;
735: smb_fwrite(&smb,&xlat,2,smb.sdt_fp);
736: m=2;
737: for(;l<n*QWK_BLOCK_LEN && m<length;l++) {
738: if(qwkbuf[l]==0 || qwkbuf[l]==LF)
739: continue;
740: if(qwkbuf[l]==QWK_NEWLINE) {
741: smb_fwrite(&smb,crlf,2,smb.sdt_fp);
742: m+=2;
1.1.1.2 ! root 743: continue;
! 744: }
1.1 root 745: smb_fputc(qwkbuf[l],smb.sdt_fp);
1.1.1.2 ! root 746: m++;
! 747: }
1.1 root 748:
749: for(ch=0;m<length;m++) /* Pad out with NULLs */
750: smb_fputc(ch,smb.sdt_fp);
751: smb_fflush(smb.sdt_fp);
752:
753: msg.hdr.offset=offset;
754:
755: smb_dfield(&msg,TEXT_BODY,length);
756:
757: i=smb_addmsghdr(&smb,&msg,SMB_SELFPACK);
758: smb_close(&smb);
759: smb_stack(&smb,SMB_STACK_POP);
760:
761: smb_freemsgmem(&msg);
762: if(i!=SMB_SUCCESS) {
763: errormsg(WHERE,ERR_WRITE,smb.file,i,smb.last_error);
764: smb_freemsgdat(&smb,offset,length,1);
765: }
766: else { /* Successful */
767: if(inet) {
768: if(cfg.inetmail_sem[0]) /* update semaphore file */
769: ftouch(cmdstr(cfg.inetmail_sem,nulstr,nulstr,NULL));
770: if(!(useron.exempt&FLAG('S')))
1.1.1.2 ! root 771: subtract_cdt(&cfg,&useron,cfg.inetmail_cost);
! 772: }
1.1 root 773:
774: useron.emails++;
775: logon_emails++;
776: putuserrec(&cfg,useron.number,U_EMAILS,5,ultoa(useron.emails,tmp,10));
777: useron.etoday++;
778: putuserrec(&cfg,useron.number,U_ETODAY,5,ultoa(useron.etoday,tmp,10));
779:
780: sprintf(str,"%s sent %s NetMail to %s (%s) via QWK"
781: ,useron.alias
782: ,qnet ? "QWK":"Internet",name,qnet ? fulladdr : to);
1.1.1.2 ! root 783: logline("EN",str);
! 784: }
1.1 root 785:
786: free((char *)qwkbuf);
1.1.1.2 ! root 787: return;
! 788: }
1.1 root 789:
790:
791: /****************************** FidoNet **********************************/
792:
793: if(!fidoaddr.zone || !cfg.netmail_dir[0]) { // No fido netmail allowed
794: bputs(text[InvalidNetMailAddr]);
795: free(qwkbuf);
796: return;
797: }
798:
799: memset(&hdr,0,sizeof(hdr)); /* Initialize header to null */
800:
801: if(fromhub || useron.rest&FLAG('Q')) {
802: sprintf(str,"%.25s",block+46); /* From */
803: truncsp(str);
804: sprintf(tmp,"@%s",fromhub ? cfg.qhub[fromhub-1]->id : useron.alias);
805: strupr(tmp);
1.1.1.2 ! root 806: strcat(str,tmp);
! 807: }
1.1 root 808: else
1.1.1.2 ! root 809: SAFECOPY(str,cfg.netmail_misc&NMAIL_ALIAS ? useron.alias : useron.name);
1.1 root 810: SAFECOPY(hdr.from,str);
811:
812: SAFECOPY(hdr.to,to);
813:
814: /* Look-up in nodelist? */
815:
816: if(cfg.netmail_cost && !(useron.exempt&FLAG('S'))) {
817: if(useron.cdt+useron.freecdt<cfg.netmail_cost) {
818: bputs(text[NotEnoughCredits]);
819: free(qwkbuf);
1.1.1.2 ! root 820: return;
! 821: }
1.1 root 822: sprintf(str,text[NetMailCostContinueQ],cfg.netmail_cost);
823: if(noyes(str)) {
824: free(qwkbuf);
1.1.1.2 ! root 825: return;
! 826: }
! 827: }
1.1 root 828:
829: hdr.destzone =fidoaddr.zone;
830: hdr.destnet =fidoaddr.net;
831: hdr.destnode =fidoaddr.node;
832: hdr.destpoint =fidoaddr.point;
833:
834: for(i=0;i<cfg.total_faddrs;i++)
835: if(fidoaddr.zone==cfg.faddr[i].zone && fidoaddr.net==cfg.faddr[i].net)
836: break;
837: if(i==cfg.total_faddrs) {
838: for(i=0;i<cfg.total_faddrs;i++)
839: if(fidoaddr.zone==cfg.faddr[i].zone)
1.1.1.2 ! root 840: break;
! 841: }
1.1 root 842: if(i==cfg.total_faddrs)
843: i=0;
844: hdr.origzone =cfg.faddr[i].zone;
845: hdr.orignet =cfg.faddr[i].net;
846: hdr.orignode =cfg.faddr[i].node;
847: hdr.origpoint =cfg.faddr[i].point;
848:
849: smb_faddrtoa(&cfg.faddr[i],str);
850: bprintf(text[NetMailing],hdr.to,smb_faddrtoa(&fidoaddr,tmp),hdr.from,str);
851: tm.tm_mon=((qwkbuf[8]&0xf)*10)+(qwkbuf[9]&0xf);
852: if (tm.tm_mon) tm.tm_mon--;
853: tm.tm_mday=((qwkbuf[11]&0xf)*10)+(qwkbuf[12]&0xf);
854: tm.tm_year=((qwkbuf[14]&0xf)*10)+(qwkbuf[15]&0xf)+1900;
855: tm.tm_hour=((qwkbuf[16]&0xf)*10)+(qwkbuf[17]&0xf);
856: tm.tm_min=((qwkbuf[19]&0xf)*10)+(qwkbuf[20]&0xf); /* From QWK time */
857: tm.tm_sec=0;
858: sprintf(hdr.time,"%02u %3.3s %02u %02u:%02u:%02u" /* To FidoNet */
859: ,tm.tm_mday,mon[tm.tm_mon],TM_YEAR(tm.tm_year)
860: ,tm.tm_hour,tm.tm_min,tm.tm_sec);
861: hdr.attr=(FIDO_LOCAL|FIDO_PRIVATE);
862:
863: if(cfg.netmail_misc&NMAIL_CRASH) hdr.attr|=FIDO_CRASH;
864: if(cfg.netmail_misc&NMAIL_HOLD) hdr.attr|=FIDO_HOLD;
865: if(cfg.netmail_misc&NMAIL_KILL) hdr.attr|=FIDO_KILLSENT;
866:
867: sprintf(str,"%.25s",block+71); /* Title */
868: truncsp(str);
869: p=str;
870: if((SYSOP || useron.exempt&FLAG('F'))
871: && !strnicmp(p,"CR:",3)) { /* Crash over-ride by sysop */
872: p+=3; /* skip CR: */
873: if(*p==' ') p++; /* skip extra space if it exists */
1.1.1.2 ! root 874: hdr.attr|=FIDO_CRASH;
! 875: }
1.1 root 876:
877: if((SYSOP || useron.exempt&FLAG('F'))
878: && !strnicmp(p,"FR:",3)) { /* File request */
879: p+=3; /* skip FR: */
880: if(*p==' ') p++;
1.1.1.2 ! root 881: hdr.attr|=FIDO_FREQ;
! 882: }
1.1 root 883:
884: if((SYSOP || useron.exempt&FLAG('F'))
885: && !strnicmp(p,"RR:",3)) { /* Return receipt request */
886: p+=3; /* skip RR: */
887: if(*p==' ') p++;
1.1.1.2 ! root 888: hdr.attr|=FIDO_RRREQ;
! 889: }
1.1 root 890:
891: if((SYSOP || useron.exempt&FLAG('F'))
892: && !strnicmp(p,"FA:",3)) { /* File attachment */
893: p+=3; /* skip FA: */
894: if(*p==' ') p++;
1.1.1.2 ! root 895: hdr.attr|=FIDO_FILE;
! 896: }
1.1 root 897:
898: SAFECOPY(hdr.subj,p);
899:
1.1.1.2 ! root 900: md(cfg.netmail_dir);
1.1 root 901: for(i=1;i;i++) {
902: sprintf(str,"%s%u.msg", cfg.netmail_dir,i);
903: if(!fexistcase(str))
1.1.1.2 ! root 904: break;
! 905: }
1.1 root 906: if(!i) {
907: bputs(text[TooManyEmailsToday]);
1.1.1.2 ! root 908: return;
! 909: }
1.1 root 910: if((fido=nopen(str,O_WRONLY|O_CREAT|O_EXCL))==-1) {
911: free(qwkbuf);
912: errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_EXCL);
1.1.1.2 ! root 913: return;
! 914: }
1.1 root 915: write(fido,&hdr,sizeof(hdr));
916:
917: pt_zone_kludge(hdr,fido);
918:
919: if(cfg.netmail_misc&NMAIL_DIRECT) {
920: sprintf(str,"\1FLAGS DIR\r\n");
1.1.1.2 ! root 921: write(fido,str,strlen(str));
! 922: }
1.1 root 923:
924: l=QWK_BLOCK_LEN;
925:
926: if(into==NULL) { /* If name@addr on first line, skip first line */
927: while(l<n*QWK_BLOCK_LEN && qwkbuf[l]!=QWK_NEWLINE) l++;
1.1.1.2 ! root 928: l++;
! 929: }
1.1 root 930:
1.1.1.2 ! root 931: length=n*QWK_BLOCK_LEN;
! 932: while(l<length) {
! 933: if(qwkbuf[l]==CTRL_A) { /* Ctrl-A, so skip it and the next char */
1.1 root 934: l++;
1.1.1.2 ! root 935: if(l>=length || toupper(qwkbuf[l])=='Z') /* EOF */
! 936: break;
! 937: if((ch=ctrl_a_to_ascii_char(qwkbuf[l])) != 0)
! 938: write(fido,&ch,1);
! 939: }
1.1 root 940: else if(qwkbuf[l]!=LF) {
941: if(qwkbuf[l]==QWK_NEWLINE) /* QWK cr/lf char converted to hard CR */
942: qwkbuf[l]=CR;
1.1.1.2 ! root 943: write(fido,(char *)qwkbuf+l,1);
! 944: }
! 945: l++;
! 946: }
1.1 root 947: l=0;
948: write(fido,&l,1); /* Null terminator */
949: close(fido);
950: free((char *)qwkbuf);
951: if(cfg.netmail_sem[0]) /* update semaphore file */
952: ftouch(cmdstr(cfg.netmail_sem,nulstr,nulstr,NULL));
953: if(!(useron.exempt&FLAG('S')))
954: subtract_cdt(&cfg,&useron,cfg.netmail_cost);
955:
956: useron.emails++;
957: logon_emails++;
958: putuserrec(&cfg,useron.number,U_EMAILS,5,ultoa(useron.emails,tmp,10));
959: useron.etoday++;
960: putuserrec(&cfg,useron.number,U_ETODAY,5,ultoa(useron.etoday,tmp,10));
961:
962: sprintf(str,"%s sent NetMail to %s @%s via QWK"
963: ,useron.alias
964: ,hdr.to,smb_faddrtoa(&fidoaddr,tmp));
965: logline("EN",str);
966: }
967:
968: /****************************************************************************/
969: /* Returns the FidoNet address kept in str as ASCII. */
970: /****************************************************************************/
971: faddr_t atofaddr(scfg_t* cfg, char *str)
972: {
973: char *p;
974: faddr_t addr;
975:
976: addr.zone=addr.net=addr.node=addr.point=0;
977: if((p=strchr(str,':'))!=NULL) {
978: addr.zone=atoi(str);
1.1.1.2 ! root 979: addr.net=atoi(p+1);
! 980: }
1.1 root 981: else {
982: if(cfg->total_faddrs)
983: addr.zone=cfg->faddr[0].zone;
984: else
985: addr.zone=1;
1.1.1.2 ! root 986: addr.net=atoi(str);
! 987: }
1.1 root 988: if(!addr.zone) /* no such thing as zone 0 */
989: addr.zone=1;
990: if((p=strchr(str,'/'))!=NULL)
991: addr.node=atoi(p+1);
992: else {
993: if(cfg->total_faddrs)
994: addr.net=cfg->faddr[0].net;
995: else
996: addr.net=1;
1.1.1.2 ! root 997: addr.node=atoi(str);
! 998: }
1.1 root 999: if((p=strchr(str,'.'))!=NULL)
1000: addr.point=atoi(p+1);
1001: return(addr);
1002: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.