|
|
1.1 root 1: /* qwktomsg.cpp */
2:
3: /* Synchronet QWK to SMB message conversion routine */
4:
5: /* $Id: qwktomsg.cpp,v 1.38 2006/04/05 09:45:21 rswindell Exp $ */
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: * *
11: * Copyright 2006 Rob Swindell - http://www.synchro.net/copyright.html *
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: /* Converts a QWK message packet into a message. */
43: /****************************************************************************/
44: bool sbbs_t::qwktomsg(FILE *qwk_fp, char *hdrblk, char fromhub, uint subnum
45: , uint touser)
46: {
47: char* body;
48: char* tail;
49: char* header;
50: char str[256],col=0,lastch=0,*p,qwkbuf[QWK_BLOCK_LEN+1];
51: uint i,j,k,lzh=0,skip=0;
52: long bodylen,taillen;
53: bool header_cont=false;
54: bool success=false;
55: ulong block,blocks;
56: smbmsg_t msg;
57: struct tm tm;
58: ushort xlat=XLAT_NONE;
59: int storage=SMB_SELFPACK;
60: long dupechk_hashes=SMB_HASH_SOURCE_ALL;
61:
62: memset(&msg,0,sizeof(smbmsg_t)); /* Initialize message header */
63: msg.hdr.version=smb_ver();
64:
65: blocks=atol(hdrblk+116);
66: if(blocks<2) {
67: errormsg(WHERE,ERR_CHK,"QWK packet header blocks",blocks);
68: return(false);
69: }
70:
71: if(subnum!=INVALID_SUB
72: && (hdrblk[0]=='*' || hdrblk[0]=='+' || cfg.sub[subnum]->misc&SUB_PONLY))
73: msg.hdr.attr|=MSG_PRIVATE;
74: if(subnum!=INVALID_SUB && cfg.sub[subnum]->misc&SUB_AONLY)
75: msg.hdr.attr|=MSG_ANONYMOUS;
76: if(subnum==INVALID_SUB && cfg.sys_misc&SM_DELREADM)
77: msg.hdr.attr|=MSG_KILLREAD;
78: if((fromhub || useron.rest&FLAG('Q')) &&
79: (hdrblk[0]=='*' || hdrblk[0]=='-' || hdrblk[0]=='`'))
80: msg.hdr.attr|=MSG_READ;
81:
82: if(subnum!=INVALID_SUB && !fromhub && cfg.sub[subnum]->mod_ar[0]
83: && chk_ar(cfg.sub[subnum]->mod_ar,&useron))
84: msg.hdr.attr|=MSG_MODERATED;
85: if(subnum!=INVALID_SUB && !fromhub && cfg.sub[subnum]->misc&SUB_SYSPERM
86: && sub_op(subnum))
87: msg.hdr.attr|=MSG_PERMANENT;
88:
89: memset(&tm,0,sizeof(tm));
90: tm.tm_mon = ((hdrblk[8]&0xf)*10)+(hdrblk[9]&0xf);
91: if(tm.tm_mon>0) tm.tm_mon--; /* zero based */
92: tm.tm_mday=((hdrblk[11]&0xf)*10)+(hdrblk[12]&0xf);
93: tm.tm_year=((hdrblk[14]&0xf)*10)+(hdrblk[15]&0xf);
94: if(tm.tm_year<Y2K_2DIGIT_WINDOW)
95: tm.tm_year+=100;
96: tm.tm_hour=((hdrblk[16]&0xf)*10)+(hdrblk[17]&0xf);
97: tm.tm_min=((hdrblk[19]&0xf)*10)+(hdrblk[20]&0xf);
98: tm.tm_sec=0;
99: tm.tm_isdst=-1; /* Do not adjust for DST */
100:
101: msg.hdr.when_written.time=mktime(&tm);
102: if(!(useron.rest&FLAG('Q')) && !fromhub)
103: msg.hdr.when_written.zone=sys_timezone(&cfg);
104: msg.hdr.when_imported.time=time(NULL);
105: msg.hdr.when_imported.zone=sys_timezone(&cfg);
106:
107: hdrblk[116]=0; // don't include number of blocks in "re: msg number"
108: if(!(useron.rest&FLAG('Q')) && !fromhub)
109: msg.hdr.thread_back=atol((char *)hdrblk+108);
110:
111: if(subnum==INVALID_SUB) { /* E-mail */
112: if(cfg.sys_misc&SM_FASTMAIL)
113: storage=SMB_FASTALLOC;
114:
115: /* duplicate message-IDs must be allowed in mail database */
116: dupechk_hashes&=~(1<<SMB_HASH_SOURCE_MSG_ID);
117:
118: username(&cfg,touser,str);
119: smb_hfield_str(&msg,RECIPIENT,str);
120: sprintf(str,"%u",touser);
121: smb_hfield_str(&msg,RECIPIENTEXT,str);
122: } else {
123: if(cfg.sub[subnum]->misc&SUB_HYPER)
124: storage = SMB_HYPERALLOC;
125: else if(cfg.sub[subnum]->misc&SUB_FAST)
126: storage = SMB_FASTALLOC;
127:
128: if(cfg.sub[subnum]->misc&SUB_LZH)
129: xlat=XLAT_LZH;
130:
131: sprintf(str,"%25.25s",(char *)hdrblk+21); /* To user */
132: truncsp(str);
133: smb_hfield_str(&msg,RECIPIENT,str);
134: if(cfg.sub[subnum]->misc&SUB_LZH)
135: xlat=XLAT_LZH;
136: }
137:
138: sprintf(str,"%25.25s",hdrblk+71); /* Subject */
139: truncsp(str);
140: smb_hfield_str(&msg,SUBJECT,str);
141:
142: /********************************/
143: /* Convert the QWK message text */
144: /********************************/
145:
146: if((header=(char *)calloc((blocks-1L)*QWK_BLOCK_LEN*2L,sizeof(char)))==NULL) {
147: smb_freemsgmem(&msg);
148: errormsg(WHERE,ERR_ALLOC,"QWK msg header",(blocks-1L)*QWK_BLOCK_LEN*2L);
149: return(false);
150: }
151:
152: bodylen=0;
153: if((body=(char *)malloc((blocks-1L)*QWK_BLOCK_LEN*2L))==NULL) {
154: free(header);
155: smb_freemsgmem(&msg);
156: errormsg(WHERE,ERR_ALLOC,"QWK msg body",(blocks-1L)*QWK_BLOCK_LEN*2L);
157: return(false);
158: }
159:
160: taillen=0;
161: if((tail=(char *)malloc((blocks-1L)*QWK_BLOCK_LEN*2L))==NULL) {
162: free(header);
163: free(body);
164: smb_freemsgmem(&msg);
165: errormsg(WHERE,ERR_ALLOC,"QWK msg tail",(blocks-1L)*QWK_BLOCK_LEN*2L);
166: return(false);
167: }
168:
169: memset(qwkbuf,0,sizeof(qwkbuf));
170:
171: for(block=1;block<blocks;block++) {
172: if(!fread(qwkbuf,1,QWK_BLOCK_LEN,qwk_fp))
173: break;
174: for(k=0;k<QWK_BLOCK_LEN;k++) {
175: if(qwkbuf[k]==0)
176: continue;
177: if(bodylen==0 && (qwkbuf[k]=='@' || header_cont)) {
178: if((p=strchr(qwkbuf+k, QWK_NEWLINE))!=NULL)
179: *p=0;
180: strcat(header, qwkbuf+k);
181: strcat(header, "\n");
182: if(p==NULL) {
183: header_cont=true;
184: break;
185: }
186: k+=strlen(qwkbuf+k);
187: header_cont=false;
188: continue;
189: }
190: if(!taillen && qwkbuf[k]==' ' && col==3 && bodylen>=3
191: && body[bodylen-3]=='-' && body[bodylen-2]=='-'
192: && body[bodylen-1]=='-') {
193: bodylen-=3;
194: strcpy(tail,"--- ");
195: taillen=4;
196: col++;
197: continue;
198: }
199: if(qwkbuf[k]==QWK_NEWLINE) { /* expand QWK_NEWLINE to crlf */
200: if(!taillen && col==3 && bodylen>=3 && body[bodylen-3]=='-'
201: && body[bodylen-2]=='-' && body[bodylen-1]=='-') {
202: bodylen-=3;
203: strcpy(tail,"---");
204: taillen=3;
205: }
206: col=0;
207: if(taillen) {
208: tail[taillen++]=CR;
209: tail[taillen++]=LF;
210: }
211: else {
212: body[bodylen++]=CR;
213: body[bodylen++]=LF;
214: }
215: continue;
216: }
217: /* beep restrict */
218: if(!fromhub && qwkbuf[k]==BEL && useron.rest&FLAG('B'))
219: continue;
220: /* ANSI restriction */
221: if(!fromhub && (qwkbuf[k]==1 || qwkbuf[k]==ESC)
222: && useron.rest&FLAG('A'))
223: continue;
224: if(qwkbuf[k]!=1 && lastch!=1)
225: col++;
226: if(lastch==CTRL_A && !validattr(qwkbuf[k])) {
227: if(taillen) taillen--;
228: else bodylen--;
229: lastch=0;
230: continue;
231: }
232: lastch=qwkbuf[k];
233: if(taillen)
234: tail[taillen++]=qwkbuf[k];
235: else
236: body[bodylen++]=qwkbuf[k];
237: }
238: }
239:
240: while(bodylen && body[bodylen-1]==' ') bodylen--; /* remove trailing spaces */
241: if(bodylen>=2 && body[bodylen-2]==CR && body[bodylen-1]==LF)
242: bodylen-=2;
243:
244: while(taillen && tail[taillen-1]<=' ') taillen--; /* remove trailing garbage */
245:
246: skip=0;
247: if(useron.rest&FLAG('Q') || fromhub) { /* QWK Net */
248: if(!strnicmp(header,"@VIA:",5)) {
249: if(!fromhub)
250: set_qwk_flag(QWK_VIA);
251: p=strchr(header, '\n');
252: if(p) {
253: *p=0;
254: skip=strlen(header)+1;
255: }
256: truncsp(header);
257: p=header+5; /* Skip "@VIA:" */
258: while(*p && *p<=' ') p++; /* Skip any spaces */
259: if(route_circ(p,cfg.sys_id)) {
260: free(header);
261: free(body);
262: free(tail);
263: smb_freemsgmem(&msg);
264: bprintf("\r\nCircular message path: %s\r\n",p);
265: sprintf(str,"Circular message path: %s from %s"
266: ,p,fromhub ? cfg.qhub[fromhub-1]->id:useron.alias);
267: errorlog(str);
268: return(false);
269: }
270: sprintf(str,"%s/%s"
271: ,fromhub ? cfg.qhub[fromhub-1]->id : useron.alias,p);
272: strupr(str);
273: update_qwkroute(str);
274: }
275: else {
276: if(fromhub)
277: strcpy(str,cfg.qhub[fromhub-1]->id);
278: else
279: strcpy(str,useron.alias);
280: }
281: strupr(str);
282: j=NET_QWK;
283: smb_hfield(&msg,SENDERNETTYPE,2,&j);
284: smb_hfield_str(&msg,SENDERNETADDR,str);
285: sprintf(str,"%25.25s",hdrblk+46); /* From user */
286: truncsp(str);
287: } else {
288: sprintf(str,"%u",useron.number);
289: smb_hfield_str(&msg,SENDEREXT,str);
290: if((uint)subnum!=INVALID_SUB && cfg.sub[subnum]->misc&SUB_NAME)
291: strcpy(str,useron.name);
292: else
293: strcpy(str,useron.alias);
294: }
295: smb_hfield_str(&msg,SENDER,str);
296:
297: if(!strnicmp(header+skip,"@MSGID:",7)) {
298: if(!fromhub)
299: set_qwk_flag(QWK_MSGID);
300: p=strchr(header+skip, '\n');
301: i=skip;
302: if(p) {
303: *p=0;
304: skip+=strlen(header+i)+1;
305: }
306: p=header+i+7; /* Skip "@MSGID:" */
307: while(*p && *p<=' ') p++; /* Skip any spaces */
308: truncstr(p," "); /* Truncate at first space char */
309: smb_hfield_str(&msg,RFC822MSGID,p);
310: }
311: if(!strnicmp(header+skip,"@REPLY:",7)) {
312: if(!fromhub)
313: set_qwk_flag(QWK_MSGID);
314: p=strchr(header+skip, '\n');
315: i=skip;
316: if(p) {
317: *p=0;
318: skip+=strlen(header+i)+1;
319: }
320: p=header+i+7; /* Skip "@REPLY:" */
321: while(*p && *p<=' ') p++; /* Skip any spaces */
322: truncstr(p," "); /* Truncate at first space char */
323: smb_hfield_str(&msg,RFC822REPLYID,p);
324: }
325: if(!strnicmp(header+skip,"@TZ:",4)) {
326: if(!fromhub)
327: set_qwk_flag(QWK_TZ);
328: p=strchr(header+skip, '\n');
329: i=skip;
330: if(p) {
331: *p=0;
332: skip+=strlen(header+i)+1;
333: }
334: p=header+i+4; /* Skip "@TZ:" */
335: while(*p && *p<=' ') p++; /* Skip any spaces */
336: msg.hdr.when_written.zone=(short)ahtoul(p);
337: }
338: if(!strnicmp(header+skip,"@REPLYTO:",9)) {
339: p=strchr(header+skip, '\n');
340: i=skip;
341: if(p) {
342: *p=0;
343: skip+=strlen(header+i)+1;
344: }
345: p=header+i+9; /* Skip "@REPLYTO:" */
346: while(*p && *p<=' ') p++; /* Skip any spaces */
347: smb_hfield_str(&msg,REPLYTO,p);
348: }
349: free(header);
350:
351: /* smb_addmsg required ASCIIZ strings */
352: body[bodylen]=0;
353: tail[taillen]=0;
354:
355: if(online==ON_REMOTE)
356: bputs(text[WritingIndx]);
357:
358: if(smb.status.max_crcs==0) /* no CRC checking means no body text dupe checking */
359: dupechk_hashes&=~(1<<SMB_HASH_SOURCE_BODY);
360:
361: if((i=smb_addmsg(&smb,&msg,storage,dupechk_hashes,xlat,(uchar*)body,(uchar*)tail))==SMB_SUCCESS)
362: success=true;
363: else if(i==SMB_DUPE_MSG) {
364: bprintf("\r\n!%s\r\n",smb.last_error);
365: if(!fromhub) {
366: if(subnum==INVALID_SUB) {
367: sprintf(str,"%s duplicate e-mail attempt (%s)",useron.alias,smb.last_error);
368: logline("E!",str);
369: } else {
370: sprintf(str,"%s duplicate message attempt in %s %s (%s)"
371: ,useron.alias
372: ,cfg.grp[cfg.sub[subnum]->grp]->sname
373: ,cfg.sub[subnum]->lname
374: ,smb.last_error);
375: logline("P!",str);
376: }
377: }
378: }
379: else
380: errormsg(WHERE,ERR_WRITE,smb.file,i,smb.last_error);
381:
382: smb_freemsgmem(&msg);
383:
384: free(body);
385: free(tail);
386:
387: return(success);
388: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.