|
|
1.1 root 1: /* msgtoqwk.cpp */
2:
3: /* Synchronet message to QWK format conversion routine */
4:
1.1.1.2 ! root 5: /* $Id: msgtoqwk.cpp,v 1.23 2004/10/27 21:16:59 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"
39: #include "qwk.h"
40:
41: #define MAX_MSGNUM 0x7FFFFFUL // only 7 (decimal) digits allowed for msg num
42:
43: /****************************************************************************/
44: /* Converts message 'msg' to QWK format, writing to file 'qwk_fp'. */
45: /* mode determines how to handle Ctrl-A codes */
46: /****************************************************************************/
47: ulong sbbs_t::msgtoqwk(smbmsg_t* msg, FILE *qwk_fp, long mode, int subnum
48: , int conf)
49: {
1.1.1.2 ! root 50: char str[512],from[512],to[512],ch=0,tear=0,tearwatch=0,HUGE16 *buf,*p;
1.1 root 51: char tmp[512];
52: long l,size=0,offset;
53: int i;
54: struct tm tm;
1.1.1.2 ! root 55: smbmsg_t remsg;
1.1 root 56:
57: offset=ftell(qwk_fp);
1.1.1.2 ! root 58: memset(str,' ',QWK_BLOCK_LEN);
! 59: fwrite(str,QWK_BLOCK_LEN,1,qwk_fp); /* Init header to space */
1.1 root 60:
61: if(msg->from_net.addr && (uint)subnum==INVALID_SUB) {
1.1.1.2 ! root 62: if(mode&QM_TO_QNET)
1.1 root 63: sprintf(from,"%.128s",msg->from);
64: else if(msg->from_net.type==NET_FIDO)
65: sprintf(from,"%.128s@%.128s"
1.1.1.2 ! root 66: ,msg->from,smb_faddrtoa((faddr_t *)msg->from_net.addr,tmp));
1.1 root 67: else if(msg->from_net.type==NET_INTERNET)
1.1.1.2 ! root 68: sprintf(from,"%.128s",(char*)msg->from_net.addr);
1.1 root 69: else
1.1.1.2 ! root 70: sprintf(from,"%.128s@%.128s",msg->from,(char*)msg->from_net.addr);
1.1 root 71: if(strlen(from)>25) {
1.1.1.2 ! root 72: sprintf(str,"From: %.128s%c%c",from,QWK_NEWLINE,QWK_NEWLINE);
1.1 root 73: fwrite(str,strlen(str),1,qwk_fp);
74: size+=strlen(str);
75: sprintf(from,"%.128s",msg->from); } }
76: else {
77: sprintf(from,"%.128s",msg->from);
78: if(msg->hdr.attr&MSG_ANONYMOUS && !SYSOP) /* from user */
79: strcpy(from,text[Anonymous]); }
80:
81: if(msg->to_net.addr && (uint)subnum==INVALID_SUB) {
82: if(msg->to_net.type==NET_FIDO)
1.1.1.2 ! root 83: sprintf(to,"%.128s@%s",msg->to,smb_faddrtoa((faddr_t *)msg->to_net.addr,tmp));
1.1 root 84: else if(msg->to_net.type==NET_INTERNET)
1.1.1.2 ! root 85: sprintf(to,"%.128s",(char*)msg->to_net.addr);
1.1 root 86: else if(msg->to_net.type==NET_QWK) {
1.1.1.2 ! root 87: if(mode&QM_TO_QNET) {
1.1 root 88: p=strchr((char *)msg->to_net.addr,'/');
89: if(p) { /* Another hop */
90: p++;
91: strcpy(to,"NETMAIL");
1.1.1.2 ! root 92: sprintf(str,"%.128s@%.128s%c",msg->to,p,QWK_NEWLINE);
1.1 root 93: fwrite(str,strlen(str),1,qwk_fp);
94: size+=strlen(str); }
95: else
96: sprintf(to,"%.128s",msg->to); }
97: else
1.1.1.2 ! root 98: sprintf(to,"%.128s@%.128s",msg->to,(char*)msg->to_net.addr); }
1.1 root 99: else
1.1.1.2 ! root 100: sprintf(to,"%.128s@%.128s",msg->to,(char*)msg->to_net.addr);
1.1 root 101: if(strlen(to)>25) {
1.1.1.2 ! root 102: sprintf(str,"To: %.128s%c%c",to,QWK_NEWLINE,QWK_NEWLINE);
1.1 root 103: fwrite(str,strlen(str),1,qwk_fp);
104: size+=strlen(str);
105: if(msg->to_net.type==NET_QWK)
106: strcpy(to,"NETMAIL");
107: else
108: sprintf(to,"%.128s",msg->to); } }
109: else
110: sprintf(to,"%.128s",msg->to);
111:
1.1.1.2 ! root 112: if(msg->from_net.type==NET_QWK && mode&QM_VIA && !msg->forwarded) {
! 113: sprintf(str,"@VIA: %.*s%c"
! 114: ,(int)(sizeof(str)-12),(char*)msg->from_net.addr,QWK_NEWLINE);
1.1 root 115: fwrite(str,strlen(str),1,qwk_fp);
116: size+=strlen(str); }
1.1.1.2 ! root 117:
! 118: if(mode&QM_MSGID && (uint)subnum!=INVALID_SUB) {
! 119: sprintf(str,"@MSGID: %.*s%c"
! 120: ,(int)(sizeof(str)-12),get_msgid(&cfg,subnum,msg),QWK_NEWLINE);
! 121: fwrite(str,strlen(str),1,qwk_fp);
! 122: size+=strlen(str);
1.1 root 123:
1.1.1.2 ! root 124: str[0]=0;
! 125: if(msg->reply_id) {
! 126: SAFECOPY(tmp,msg->reply_id);
! 127: truncstr(tmp," ");
! 128: sprintf(str,"@REPLY: %.*s%c"
! 129: ,(int)(sizeof(str)-12),tmp,QWK_NEWLINE);
! 130: } else if(msg->hdr.thread_back) {
! 131: memset(&remsg,0,sizeof(remsg));
! 132: remsg.hdr.number=msg->hdr.thread_back;
! 133: if(smb_getmsgidx(&smb, &remsg))
! 134: sprintf(str,"@REPLY: <%s>%c",smb.last_error,QWK_NEWLINE);
! 135: else
! 136: sprintf(str,"@REPLY: %s%c"
! 137: ,get_msgid(&cfg,subnum,&remsg)
! 138: ,QWK_NEWLINE);
! 139: }
! 140: if(str[0]) {
! 141: fwrite(str,strlen(str),1,qwk_fp);
! 142: size+=strlen(str);
! 143: }
! 144: }
! 145:
! 146: if(msg->hdr.when_written.zone && mode&QM_TZ) {
! 147: sprintf(str,"@TZ: %04x%c",msg->hdr.when_written.zone,QWK_NEWLINE);
1.1 root 148: fwrite(str,strlen(str),1,qwk_fp);
1.1.1.2 ! root 149: size+=strlen(str);
! 150: }
! 151:
! 152: if(msg->replyto!=NULL && mode&QM_REPLYTO) {
! 153: sprintf(str,"@REPLYTO: %.*s%c"
! 154: ,(int)(sizeof(str)-12),msg->replyto,QWK_NEWLINE);
! 155: fwrite(str,strlen(str),1,qwk_fp);
! 156: size+=strlen(str);
! 157: }
1.1 root 158:
159: p=0;
160: for(i=0;i<msg->total_hfields;i++) {
161: if(msg->hfield[i].type==SENDER)
162: p=(char *)msg->hfield_dat[i];
163: if(msg->hfield[i].type==FORWARDED && p) {
1.1.1.2 ! root 164: sprintf(str,"Forwarded from %s on %s%c",p
! 165: ,timestr((time_t *)msg->hfield_dat[i])
! 166: ,QWK_NEWLINE);
1.1 root 167: fwrite(str,strlen(str),1,qwk_fp);
1.1.1.2 ! root 168: size+=strlen(str);
! 169: }
! 170: }
1.1 root 171:
1.1.1.2 ! root 172: buf=smb_getmsgtxt(&smb,msg,GETMSGTXT_ALL);
1.1 root 173: if(!buf)
174: return(0);
175:
176: for(l=0;buf[l];l++) {
177: ch=buf[l];
178:
179: if(ch==LF) {
180: if(tear)
181: tear++; /* Count LFs after tearline */
182: if(tear>3) /* more than two LFs after the tear */
183: tear=0;
184: if(tearwatch==4) { /* watch for LF---LF */
185: tear=1;
186: tearwatch=0; }
187: else if(!tearwatch)
188: tearwatch=1;
189: else
190: tearwatch=0;
1.1.1.2 ! root 191: ch=QWK_NEWLINE;
1.1 root 192: fputc(ch,qwk_fp); /* Replace LF with funky char */
193: size++;
194: continue; }
195:
196: if(ch==CR) { /* Ignore CRs */
197: if(tearwatch<4) /* LF---CRLF is okay */
198: tearwatch=0; /* LF-CR- is not okay */
199: continue; }
200:
1.1.1.2 ! root 201: if(ch==' ' && tearwatch==4) { /* watch for "LF--- " */
1.1 root 202: tear=1;
203: tearwatch=0; }
204:
205: if(ch=='-') { /* watch for "LF---" */
206: if(l==0 || (tearwatch && tearwatch<4))
207: tearwatch++;
208: else
209: tearwatch=0; }
210: else
211: tearwatch=0;
212:
213: if((uint)subnum!=INVALID_SUB && cfg.sub[subnum]->misc&SUB_ASCII) {
1.1.1.2 ! root 214: if(ch<' ' && ch!=1)
1.1 root 215: ch='.';
216: else if((uchar)ch>0x7f)
217: ch='*'; }
218:
1.1.1.2 ! root 219: if(ch==QWK_NEWLINE) /* funky char */
1.1 root 220: ch='*';
221:
1.1.1.2 ! root 222: if(ch==CTRL_A) {
1.1 root 223: ch=buf[++l];
224: if(!ch)
225: break;
226: if(mode&A_EXPAND) {
227: str[0]=0;
228: switch(toupper(ch)) { /* non-color codes */
229: case 'L':
230: strcpy(str,"\x1b[2J\x1b[H");
231: break;
232: case 'W':
233: strcpy(str,ansi(LIGHTGRAY));
234: break;
235: case 'K':
236: strcpy(str,ansi(BLACK));
237: break;
238: case 'H':
239: strcpy(str,ansi(HIGH));
240: break;
241: case 'I':
242: strcpy(str,ansi(BLINK));
243: break;
244: case 'N': /* Normal */
1.1.1.2 ! root 245: strcpy(str,ansi(ANSI_NORMAL));
1.1 root 246: break;
247: case 'R': /* Color codes */
248: strcpy(str,ansi(RED));
249: break;
250: case 'G':
251: strcpy(str,ansi(GREEN));
252: break;
253: case 'B':
254: strcpy(str,ansi(BLUE));
255: break;
256: case 'C':
257: strcpy(str,ansi(CYAN));
258: break;
259: case 'M':
260: strcpy(str,ansi(MAGENTA));
261: break;
262: case 'Y': /* Yellow */
263: strcpy(str,ansi(BROWN));
264: break;
1.1.1.2 ! root 265: case '0':
! 266: strcpy(str,ansi(BG_BLACK));
! 267: break;
1.1 root 268: case '1':
1.1.1.2 ! root 269: strcpy(str,ansi(BG_RED));
1.1 root 270: break;
271: case '2':
1.1.1.2 ! root 272: strcpy(str,ansi(BG_GREEN));
1.1 root 273: break;
274: case '3':
1.1.1.2 ! root 275: strcpy(str,ansi(BG_BROWN));
1.1 root 276: break;
277: case '4':
1.1.1.2 ! root 278: strcpy(str,ansi(BG_BLUE));
1.1 root 279: break;
280: case '5':
1.1.1.2 ! root 281: strcpy(str,ansi(BG_MAGENTA));
1.1 root 282: break;
283: case '6':
1.1.1.2 ! root 284: strcpy(str,ansi(BG_CYAN));
! 285: break;
! 286: case '7':
! 287: strcpy(str,ansi(BG_LIGHTGRAY));
! 288: break;
! 289: }
1.1 root 290: if(str[0]) {
291: fwrite(str,strlen(str),1,qwk_fp);
1.1.1.2 ! root 292: size+=strlen(str);
! 293: }
! 294: continue;
! 295: } /* End Expand */
1.1 root 296:
297: if(mode&A_LEAVE) {
298: fputc(1,qwk_fp);
299: fputc(ch,qwk_fp);
300: size+=2L; }
301: else /* Strip */
302: if(toupper(ch)=='L') {
303: fputc(FF,qwk_fp);
304: size++; }
305: continue; } /* End of Ctrl-A shit */
306: fputc(ch,qwk_fp);
307: size++; }
308:
309: LFREE(buf);
1.1.1.2 ! root 310: if(ch!=QWK_NEWLINE) {
! 311: fputc(QWK_NEWLINE,qwk_fp); /* make sure it ends in CRLF */
1.1 root 312: size++; }
313:
1.1.1.2 ! root 314: if(mode&QM_TAGLINE && !(cfg.sub[subnum]->misc&SUB_NOTAG)) {
1.1 root 315: if(!tear) /* no tear line */
1.1.1.2 ! root 316: sprintf(str,"\1n---%c",QWK_NEWLINE); /* so add one */
1.1 root 317: else
318: strcpy(str,"\1n");
319: if(cfg.sub[subnum]->misc&SUB_ASCII) ch='*';
320: else ch='�';
1.1.1.2 ! root 321: sprintf(tmp," %c \1g%.10s\1n %c %.127s%c"
! 322: ,ch,VERSION_NOTICE,ch,cfg.sub[subnum]->tagline,QWK_NEWLINE);
1.1 root 323: strcat(str,tmp);
324: if(!(mode&A_LEAVE))
1.1.1.2 ! root 325: remove_ctrl_a(str,NULL);
1.1 root 326: fwrite(str,strlen(str),1,qwk_fp);
327: size+=strlen(str); }
328:
1.1.1.2 ! root 329: while(size%QWK_BLOCK_LEN) { /* Pad with spaces */
1.1 root 330: size++;
1.1.1.2 ! root 331: fputc(' ',qwk_fp); }
1.1 root 332:
1.1.1.2 ! root 333: if(localtime_r((time_t *)&msg->hdr.when_written.time,&tm)==NULL)
1.1 root 334: memset(&tm,0,sizeof(tm));
335:
336: sprintf(tmp,"%02u-%02u-%02u%02u:%02u"
337: ,tm.tm_mon+1,tm.tm_mday,TM_YEAR(tm.tm_year)
338: ,tm.tm_hour,tm.tm_min);
339:
340: if(msg->hdr.attr&MSG_PRIVATE) {
341: if(msg->hdr.attr&MSG_READ)
342: ch='*'; /* private, read */
343: else
344: ch='+'; /* private, unread */ }
345: else {
346: if(msg->hdr.attr&MSG_READ)
347: ch='-'; /* public, read */
348: else
349: ch=' '; /* public, unread */ }
350:
351:
352: sprintf(str,"%c%-7lu%-13.13s%-25.25s"
353: "%-25.25s%-25.25s%12s%-8lu%-6lu\xe1%c%c%c%c%c"
354: ,ch /* message status flag */
1.1.1.2 ! root 355: ,mode&QM_REP ? (ulong)conf /* conference or */
1.1 root 356: : msg->hdr.number&MAX_MSGNUM /* message number */
357: ,tmp /* date and time */
358: ,to /* To: */
359: ,from /* From: */
360: ,msg->subj /* Subject */
361: ,nulstr /* Password */
1.1.1.2 ! root 362: ,msg->hdr.thread_back&MAX_MSGNUM /* Message Re: Number */
! 363: ,(size/QWK_BLOCK_LEN)+1 /* Number of blocks */
1.1 root 364: ,(char)conf&0xff /* Conference number lo byte */
365: ,(ushort)conf>>8 /* hi byte */
1.1.1.2 ! root 366: ,' ' /* not used */
! 367: ,' ' /* not used */
! 368: ,useron.rest&FLAG('Q') ? '*' : ' ' /* Net tag line */
1.1 root 369: );
370:
371: fseek(qwk_fp,offset,SEEK_SET);
1.1.1.2 ! root 372: fwrite(str,QWK_BLOCK_LEN,1,qwk_fp);
1.1 root 373: fseek(qwk_fp,size,SEEK_CUR);
374:
375: return(size);
376: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.