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