--- sbbs/src/sbbs3/msgtoqwk.cpp 2018/04/24 16:41:23 1.1.1.1 +++ sbbs/src/sbbs3/msgtoqwk.cpp 2018/04/24 16:43:20 1.1.1.2 @@ -2,13 +2,13 @@ /* Synchronet message to QWK format conversion routine */ -/* $Id: msgtoqwk.cpp,v 1.1.1.1 2018/04/24 16:41:23 root Exp $ */ +/* $Id: msgtoqwk.cpp,v 1.1.1.2 2018/04/24 16:43:20 root Exp $ */ /**************************************************************************** * @format.tab-size 4 (Plain Text/Source Code File Header) * * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * * * - * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html * + * Copyright 2011 Rob Swindell - http://www.synchro.net/copyright.html * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License * @@ -45,39 +45,147 @@ /* mode determines how to handle Ctrl-A codes */ /****************************************************************************/ ulong sbbs_t::msgtoqwk(smbmsg_t* msg, FILE *qwk_fp, long mode, int subnum - , int conf) + , int conf, FILE* hdrs) { char str[512],from[512],to[512],ch=0,tear=0,tearwatch=0,*buf,*p; + char asc; + char msgid[256]; char tmp[512]; long l,size=0,offset; int i; + ushort hfield_type; struct tm tm; smbmsg_t remsg; + time_t tt; - offset=ftell(qwk_fp); - memset(str,' ',QWK_BLOCK_LEN); - fwrite(str,QWK_BLOCK_LEN,1,qwk_fp); /* Init header to space */ - - if(msg->from_net.addr && (uint)subnum==INVALID_SUB) { - if(mode&QM_TO_QNET) - sprintf(from,"%.128s",msg->from); - else if(msg->from_net.type==NET_FIDO) + offset=(long)ftell(qwk_fp); + if(hdrs!=NULL) { + fprintf(hdrs,"[%x]\n",offset); + + /* Message-IDs */ + fprintf(hdrs,"Message-ID: %s\n",get_msgid(&cfg,subnum,msg,msgid,sizeof(msgid))); + if(msg->reply_id!=NULL) + fprintf(hdrs,"In-Reply-To: %s\n",msg->reply_id); + + /* Time/Date/Zone info */ + fprintf(hdrs,"WhenWritten: %-20s %04hx\n" + ,xpDateTime_to_isoDateTimeStr( + time_to_xpDateTime(msg->hdr.when_written.time,smb_tzutc(msg->hdr.when_written.zone)) + ,/* separators: */"","","", /* precision: */0 + ,str,sizeof(str)) + ,msg->hdr.when_written.zone + ); + fprintf(hdrs,"WhenImported: %-20s %04hx\n" + ,xpDateTime_to_isoDateTimeStr( + time_to_xpDateTime(msg->hdr.when_imported.time,smb_tzutc(msg->hdr.when_imported.zone)) + ,/* separators: */"","","", /* precision: */0 + ,str,sizeof(str)) + ,msg->hdr.when_imported.zone + ); + fprintf(hdrs,"WhenExported: %-20s %04hx\n" + ,xpDateTime_to_isoDateTimeStr( + xpDateTime_now() + ,/* separators: */"","","", /* precision: */0 + ,str,sizeof(str)) + ,sys_timezone(&cfg) + ); + fprintf(hdrs,"ExportedFrom: %s %s %lu\n" + ,cfg.sys_id + ,subnum==INVALID_SUB ? "mail":cfg.sub[subnum]->code + ,msg->hdr.number + ); + + /* SENDER */ + fprintf(hdrs,"%s: %s\n",smb_hfieldtype(SENDER),msg->from); + if(msg->from_net.type) + fprintf(hdrs,"%s: %s\n",smb_hfieldtype(SENDERNETADDR),smb_netaddrstr(&msg->from_net,tmp)); + if((p=(char*)smb_get_hfield(msg,hfield_type=SENDERIPADDR,NULL))!=NULL) + fprintf(hdrs,"%s: %s\n",smb_hfieldtype(hfield_type),p); + if((p=(char*)smb_get_hfield(msg,hfield_type=SENDERHOSTNAME,NULL))!=NULL) + fprintf(hdrs,"%s: %s\n",smb_hfieldtype(hfield_type),p); + if((p=(char*)smb_get_hfield(msg,hfield_type=SENDERPROTOCOL,NULL))!=NULL) + fprintf(hdrs,"%s: %s\n",smb_hfieldtype(hfield_type),p); + if(msg->from_org!=NULL) + fprintf(hdrs,"Organization: %s\n",msg->from_org); + else if(msg->from_net.type==NET_NONE) + fprintf(hdrs,"Organization: %s\n",cfg.sys_name); + + /* Reply-To */ + if((p=(char*)smb_get_hfield(msg,RFC822REPLYTO,NULL))==NULL) { + if(msg->replyto_net.type==NET_INTERNET) + p=(char*)msg->replyto_net.addr; + else if(msg->replyto!=NULL) + p=msg->replyto; + } + if(p!=NULL) + fprintf(hdrs,"Reply-To: %s\n",p); /* use original RFC822 header field */ + + /* SUBJECT */ + fprintf(hdrs,"%s: %s\n",smb_hfieldtype(SUBJECT),msg->subj); + + /* RECIPIENT */ + fprintf(hdrs,"%s: %s\n",smb_hfieldtype(RECIPIENT),msg->to); + if(msg->to_net.type) + fprintf(hdrs,"%s: %s\n",smb_hfieldtype(RECIPIENTNETADDR),smb_netaddrstr(&msg->to_net,tmp)); + + /* FidoNet */ + if((p=(char*)smb_get_hfield(msg,hfield_type=FIDOAREA,NULL))!=NULL) + fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); + if((p=(char*)smb_get_hfield(msg,hfield_type=FIDOSEENBY,NULL))!=NULL) + fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); + if((p=(char*)smb_get_hfield(msg,hfield_type=FIDOPATH,NULL))!=NULL) + fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); + if((p=(char*)smb_get_hfield(msg,hfield_type=FIDOMSGID,NULL))!=NULL) + fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); + if((p=(char*)smb_get_hfield(msg,hfield_type=FIDOREPLYID,NULL))!=NULL) + fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); + if((p=(char*)smb_get_hfield(msg,hfield_type=FIDOPID,NULL))!=NULL) + fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); + if((p=(char*)smb_get_hfield(msg,hfield_type=FIDOFLAGS,NULL))!=NULL) + fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); + if((p=(char*)smb_get_hfield(msg,hfield_type=FIDOTID,NULL))!=NULL) + fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); + + /* Synchronet */ + if((p=(char*)smb_get_hfield(msg,hfield_type=SMB_EDITOR,NULL))!=NULL) + fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); + + /* USENET */ + if((p=(char*)smb_get_hfield(msg,hfield_type=USENETPATH,NULL))!=NULL) + fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); + if((p=(char*)smb_get_hfield(msg,hfield_type=USENETNEWSGROUPS,NULL))!=NULL) + fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); + + /* RFC822 header fields: */ + for(i=0;itotal_hfields;i++) + if(msg->hfield[i].type==RFC822HEADER) + fprintf(hdrs,"%s\n",truncsp_lines((char*)msg->hfield_dat[i])); + + /* Blank line: */ + fprintf(hdrs,"\n"); + } + + fprintf(qwk_fp,"%*s",QWK_BLOCK_LEN,""); /* Init header to space */ + + /* QWKE compatible kludges */ + SAFECOPY(from,msg->from); + if(msg->from_net.addr && (uint)subnum==INVALID_SUB && !(mode&QM_TO_QNET)) { + if(msg->from_net.type==NET_FIDO) sprintf(from,"%.128s@%.128s" ,msg->from,smb_faddrtoa((faddr_t *)msg->from_net.addr,tmp)); - else if(msg->from_net.type==NET_INTERNET) + else if(msg->from_net.type==NET_INTERNET || strchr((char*)msg->from_net.addr,'@')!=NULL) sprintf(from,"%.128s",(char*)msg->from_net.addr); else sprintf(from,"%.128s@%.128s",msg->from,(char*)msg->from_net.addr); - if(strlen(from)>25) { - sprintf(str,"From: %.128s%c%c",from,QWK_NEWLINE,QWK_NEWLINE); - fwrite(str,strlen(str),1,qwk_fp); - size+=strlen(str); - sprintf(from,"%.128s",msg->from); } } - else { - sprintf(from,"%.128s",msg->from); - if(msg->hdr.attr&MSG_ANONYMOUS && !SYSOP) /* from user */ - strcpy(from,text[Anonymous]); } + } + if(msg->hdr.attr&MSG_ANONYMOUS && !SYSOP) + SAFECOPY(from,text[Anonymous]); + else if((subnum==INVALID_SUB || (useron.qwk&QWK_EXT)) && strlen(from) > QWK_HFIELD_LEN) { + size+=fprintf(qwk_fp,"From: %.128s%c", from, QWK_NEWLINE); + SAFECOPY(from,msg->from); + } + SAFECOPY(to,msg->to); if(msg->to_net.addr && (uint)subnum==INVALID_SUB) { if(msg->to_net.type==NET_FIDO) sprintf(to,"%.128s@%s",msg->to,smb_faddrtoa((faddr_t *)msg->to_net.addr,tmp)); @@ -88,84 +196,68 @@ ulong sbbs_t::msgtoqwk(smbmsg_t* msg, FI p=strchr((char *)msg->to_net.addr,'/'); if(p) { /* Another hop */ p++; - strcpy(to,"NETMAIL"); - sprintf(str,"%.128s@%.128s%c",msg->to,p,QWK_NEWLINE); - fwrite(str,strlen(str),1,qwk_fp); - size+=strlen(str); } + SAFECOPY(to,"NETMAIL"); + size+=fprintf(qwk_fp,"%.128s@%.128s%c",msg->to,p,QWK_NEWLINE); + } else - sprintf(to,"%.128s",msg->to); } + sprintf(to,"%.128s",msg->to); + } else - sprintf(to,"%.128s@%.128s",msg->to,(char*)msg->to_net.addr); } + sprintf(to,"%.128s@%.128s",msg->to,(char*)msg->to_net.addr); + } else sprintf(to,"%.128s@%.128s",msg->to,(char*)msg->to_net.addr); - if(strlen(to)>25) { - sprintf(str,"To: %.128s%c%c",to,QWK_NEWLINE,QWK_NEWLINE); - fwrite(str,strlen(str),1,qwk_fp); - size+=strlen(str); - if(msg->to_net.type==NET_QWK) - strcpy(to,"NETMAIL"); - else - sprintf(to,"%.128s",msg->to); } } - else - sprintf(to,"%.128s",msg->to); - - if(msg->from_net.type==NET_QWK && mode&QM_VIA && !msg->forwarded) { - sprintf(str,"@VIA: %.*s%c" - ,(int)(sizeof(str)-12),(char*)msg->from_net.addr,QWK_NEWLINE); - fwrite(str,strlen(str),1,qwk_fp); - size+=strlen(str); } + } + if((subnum==INVALID_SUB || (useron.qwk&QWK_EXT)) && strlen(to) > QWK_HFIELD_LEN) { + size+=fprintf(qwk_fp,"To: %.128s%c", to, QWK_NEWLINE); + if(msg->to_net.type==NET_QWK) + SAFECOPY(to,"NETMAIL"); + else + SAFECOPY(to,msg->to); + } + if((useron.qwk&QWK_EXT) && strlen(msg->subj) > QWK_HFIELD_LEN) + size+=fprintf(qwk_fp,"Subject: %.128s%c", msg->subj, QWK_NEWLINE); + + if(msg->from_net.type==NET_QWK && mode&QM_VIA && !msg->forwarded) + size+=fprintf(qwk_fp,"@VIA: %s%c" + ,(char*)msg->from_net.addr,QWK_NEWLINE); if(mode&QM_MSGID && (uint)subnum!=INVALID_SUB) { - sprintf(str,"@MSGID: %.*s%c" - ,(int)(sizeof(str)-12),get_msgid(&cfg,subnum,msg),QWK_NEWLINE); - fwrite(str,strlen(str),1,qwk_fp); - size+=strlen(str); + size+=fprintf(qwk_fp,"@MSGID: %s%c" + ,get_msgid(&cfg,subnum,msg,msgid,sizeof(msgid)),QWK_NEWLINE); - str[0]=0; if(msg->reply_id) { SAFECOPY(tmp,msg->reply_id); truncstr(tmp," "); - sprintf(str,"@REPLY: %.*s%c" - ,(int)(sizeof(str)-12),tmp,QWK_NEWLINE); + size+=fprintf(qwk_fp,"@REPLY: %s%c" + ,tmp,QWK_NEWLINE); } else if(msg->hdr.thread_back) { memset(&remsg,0,sizeof(remsg)); remsg.hdr.number=msg->hdr.thread_back; if(smb_getmsgidx(&smb, &remsg)) - sprintf(str,"@REPLY: <%s>%c",smb.last_error,QWK_NEWLINE); + size+=fprintf(qwk_fp,"@REPLY: <%s>%c",smb.last_error,QWK_NEWLINE); else - sprintf(str,"@REPLY: %s%c" - ,get_msgid(&cfg,subnum,&remsg) + size+=fprintf(qwk_fp,"@REPLY: %s%c" + ,get_msgid(&cfg,subnum,&remsg,msgid,sizeof(msgid)) ,QWK_NEWLINE); } - if(str[0]) { - fwrite(str,strlen(str),1,qwk_fp); - size+=strlen(str); - } } - if(msg->hdr.when_written.zone && mode&QM_TZ) { - sprintf(str,"@TZ: %04x%c",msg->hdr.when_written.zone,QWK_NEWLINE); - fwrite(str,strlen(str),1,qwk_fp); - size+=strlen(str); - } + if(msg->hdr.when_written.zone && mode&QM_TZ) + size+=fprintf(qwk_fp,"@TZ: %04hx%c",msg->hdr.when_written.zone,QWK_NEWLINE); - if(msg->replyto!=NULL && mode&QM_REPLYTO) { - sprintf(str,"@REPLYTO: %.*s%c" - ,(int)(sizeof(str)-12),msg->replyto,QWK_NEWLINE); - fwrite(str,strlen(str),1,qwk_fp); - size+=strlen(str); - } + if(msg->replyto!=NULL && mode&QM_REPLYTO) + size+=fprintf(qwk_fp,"@REPLYTO: %s%c" + ,msg->replyto,QWK_NEWLINE); p=0; for(i=0;itotal_hfields;i++) { if(msg->hfield[i].type==SENDER) p=(char *)msg->hfield_dat[i]; if(msg->hfield[i].type==FORWARDED && p) { - sprintf(str,"Forwarded from %s on %s%c",p - ,timestr((time_t *)msg->hfield_dat[i]) + size+=fprintf(qwk_fp,"Forwarded from %s on %s%c",p + ,timestr(*(time32_t *)msg->hfield_dat[i]) ,QWK_NEWLINE); - fwrite(str,strlen(str),1,qwk_fp); - size+=strlen(str); } } @@ -176,37 +268,43 @@ ulong sbbs_t::msgtoqwk(smbmsg_t* msg, FI for(l=0;buf[l];l++) { ch=buf[l]; - if(ch==LF) { + if(ch=='\n') { if(tear) tear++; /* Count LFs after tearline */ if(tear>3) /* more than two LFs after the tear */ tear=0; if(tearwatch==4) { /* watch for LF---LF */ tear=1; - tearwatch=0; } + tearwatch=0; + } else if(!tearwatch) tearwatch=1; else tearwatch=0; - ch=QWK_NEWLINE; - fputc(ch,qwk_fp); /* Replace LF with funky char */ + if(l && buf[l-1]=='\r') /* Replace CRLF with funky char */ + ch=QWK_NEWLINE; /* but leave sole LF (soft-NL) alone */ + fputc(ch,qwk_fp); size++; - continue; } + continue; + } - if(ch==CR) { /* Ignore CRs */ + if(ch=='\r') { /* Ignore CRs */ if(tearwatch<4) /* LF---CRLF is okay */ tearwatch=0; /* LF-CR- is not okay */ - continue; } + continue; + } if(ch==' ' && tearwatch==4) { /* watch for "LF--- " */ tear=1; - tearwatch=0; } + tearwatch=0; + } if(ch=='-') { /* watch for "LF---" */ if(l==0 || (tearwatch && tearwatch<4)) tearwatch++; else - tearwatch=0; } + tearwatch=0; + } else tearwatch=0; @@ -214,126 +312,130 @@ ulong sbbs_t::msgtoqwk(smbmsg_t* msg, FI if(ch<' ' && ch!=1) ch='.'; else if((uchar)ch>0x7f) - ch='*'; } + ch=exascii_to_ascii_char(ch); + } if(ch==QWK_NEWLINE) /* funky char */ ch='*'; if(ch==CTRL_A) { ch=buf[++l]; - if(!ch) + if(ch==0 || toupper(ch)=='Z') /* EOF */ break; + if((asc=ctrl_a_to_ascii_char(ch)) != 0) { + fputc(asc,qwk_fp); + size++; + continue; + } if(mode&A_EXPAND) { str[0]=0; - switch(toupper(ch)) { /* non-color codes */ - case 'L': - strcpy(str,"\x1b[2J\x1b[H"); - break; + switch(toupper(ch)) { case 'W': - strcpy(str,ansi(LIGHTGRAY)); + SAFECOPY(str,ansi(LIGHTGRAY)); break; case 'K': - strcpy(str,ansi(BLACK)); + SAFECOPY(str,ansi(BLACK)); break; case 'H': - strcpy(str,ansi(HIGH)); + SAFECOPY(str,ansi(HIGH)); break; case 'I': - strcpy(str,ansi(BLINK)); + SAFECOPY(str,ansi(BLINK)); break; + case '-': + case '_': case 'N': /* Normal */ - strcpy(str,ansi(ANSI_NORMAL)); + SAFECOPY(str,ansi(ANSI_NORMAL)); break; - case 'R': /* Color codes */ - strcpy(str,ansi(RED)); + case 'R': + SAFECOPY(str,ansi(RED)); break; case 'G': - strcpy(str,ansi(GREEN)); + SAFECOPY(str,ansi(GREEN)); break; case 'B': - strcpy(str,ansi(BLUE)); + SAFECOPY(str,ansi(BLUE)); break; case 'C': - strcpy(str,ansi(CYAN)); + SAFECOPY(str,ansi(CYAN)); break; case 'M': - strcpy(str,ansi(MAGENTA)); + SAFECOPY(str,ansi(MAGENTA)); break; case 'Y': /* Yellow */ - strcpy(str,ansi(BROWN)); + SAFECOPY(str,ansi(BROWN)); break; case '0': - strcpy(str,ansi(BG_BLACK)); + SAFECOPY(str,ansi(BG_BLACK)); break; case '1': - strcpy(str,ansi(BG_RED)); + SAFECOPY(str,ansi(BG_RED)); break; case '2': - strcpy(str,ansi(BG_GREEN)); + SAFECOPY(str,ansi(BG_GREEN)); break; case '3': - strcpy(str,ansi(BG_BROWN)); + SAFECOPY(str,ansi(BG_BROWN)); break; case '4': - strcpy(str,ansi(BG_BLUE)); + SAFECOPY(str,ansi(BG_BLUE)); break; case '5': - strcpy(str,ansi(BG_MAGENTA)); + SAFECOPY(str,ansi(BG_MAGENTA)); break; case '6': - strcpy(str,ansi(BG_CYAN)); + SAFECOPY(str,ansi(BG_CYAN)); break; case '7': - strcpy(str,ansi(BG_LIGHTGRAY)); + SAFECOPY(str,ansi(BG_LIGHTGRAY)); break; } - if(str[0]) { - fwrite(str,strlen(str),1,qwk_fp); - size+=strlen(str); - } + if(str[0]) + size+=fwrite(str,sizeof(char),strlen(str),qwk_fp); continue; } /* End Expand */ - - if(mode&A_LEAVE) { - fputc(1,qwk_fp); + if(mode&A_LEAVE && valid_ctrl_a_code(ch)) { + fputc(CTRL_A,qwk_fp); fputc(ch,qwk_fp); - size+=2L; } - else /* Strip */ - if(toupper(ch)=='L') { - fputc(FF,qwk_fp); - size++; } - continue; } /* End of Ctrl-A shit */ + size+=2L; + } + continue; + } /* End of Ctrl-A shit */ fputc(ch,qwk_fp); - size++; } + size++; + } free(buf); if(ch!=QWK_NEWLINE) { fputc(QWK_NEWLINE,qwk_fp); /* make sure it ends in CRLF */ - size++; } + size++; + } if(mode&QM_TAGLINE && !(cfg.sub[subnum]->misc&SUB_NOTAG)) { if(!tear) /* no tear line */ - sprintf(str,"\1n---%c",QWK_NEWLINE); /* so add one */ + SAFEPRINTF(str,"\1n---%c",QWK_NEWLINE); /* so add one */ else - strcpy(str,"\1n"); + SAFECOPY(str,"\1n"); if(cfg.sub[subnum]->misc&SUB_ASCII) ch='*'; else ch='þ'; - sprintf(tmp," %c \1g%.10s\1n %c %.127s%c" + safe_snprintf(tmp,sizeof(tmp)," %c \1g%.10s\1n %c %.127s%c" ,ch,VERSION_NOTICE,ch,cfg.sub[subnum]->tagline,QWK_NEWLINE); strcat(str,tmp); if(!(mode&A_LEAVE)) - remove_ctrl_a(str,NULL); - fwrite(str,strlen(str),1,qwk_fp); - size+=strlen(str); } + remove_ctrl_a(str,str); + size+=fwrite(str,sizeof(char),strlen(str),qwk_fp); + } while(size%QWK_BLOCK_LEN) { /* Pad with spaces */ size++; - fputc(' ',qwk_fp); } + fputc(' ',qwk_fp); + } - if(localtime_r((time_t *)&msg->hdr.when_written.time,&tm)==NULL) + tt=msg->hdr.when_written.time; + if(localtime_r(&tt,&tm)==NULL) memset(&tm,0,sizeof(tm)); - sprintf(tmp,"%02u-%02u-%02u%02u:%02u" + safe_snprintf(tmp,sizeof(tmp),"%02u-%02u-%02u%02u:%02u" ,tm.tm_mon+1,tm.tm_mday,TM_YEAR(tm.tm_year) ,tm.tm_hour,tm.tm_min); @@ -349,7 +451,7 @@ ulong sbbs_t::msgtoqwk(smbmsg_t* msg, FI ch=' '; /* public, unread */ } - sprintf(str,"%c%-7lu%-13.13s%-25.25s" + safe_snprintf(str,sizeof(str),"%c%-7lu%-13.13s%-25.25s" "%-25.25s%-25.25s%12s%-8lu%-6lu\xe1%c%c%c%c%c" ,ch /* message status flag */ ,mode&QM_REP ? (ulong)conf /* conference or */