/****************************************************************************** * HPT --- FTN NetMail/EchoMail Tosser ****************************************************************************** * carbon.c : functions for making carbon copy * * by Max Chernogor , 2:464/108@fidonet * * This file is part of HPT. * * HPT is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * HPT is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HPT; see the file COPYING. If not, write to the Free * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ***************************************************************************** * $Id: carbon.c,v 1.21.2.4 2004/05/31 19:26:37 d_sergienko Exp $ */ #include #include #include #ifdef HAS_PROCESS_H # include #endif #ifdef HAS_IO_H #include #endif #ifdef HAS_UNISTD_H #include #endif #ifdef HAS_DOS_H #include #endif #include #include #include #include #include #include "global.h" #include "toss.h" extern s_statToss statToss; s_message* MessForCC(s_message *msg) { s_message* CCmsg; if(config->carbonCount == 0) return NULL; CCmsg = (s_message*) safe_calloc(1,sizeof(s_message)); CCmsg->origAddr.zone = msg->origAddr.zone; CCmsg->origAddr.net = msg->origAddr.net; CCmsg->origAddr.node = msg->origAddr.node; CCmsg->origAddr.point = msg->origAddr.point; CCmsg->destAddr.zone = msg->destAddr.zone; CCmsg->destAddr.net = msg->destAddr.net ; CCmsg->destAddr.node = msg->destAddr.node; CCmsg->destAddr.point = msg->destAddr.point; xstrcat(&(CCmsg->fromUserName), msg->fromUserName); xstrcat(&(CCmsg->toUserName), msg->toUserName); xstrcat(&(CCmsg->subjectLine), msg->subjectLine); xstrcat(&(CCmsg->text), msg->text); strcpy( (char*)CCmsg->datetime, (char*)msg->datetime ); CCmsg->attributes = msg->attributes; CCmsg->textLength = msg->textLength; CCmsg->netMail = msg->netMail; CCmsg->recode = msg->recode; return CCmsg; } int processExternal (s_area *echo, s_message *msg,s_carbon carbon) { FILE *msgfp = NULL; char *fname = NULL; char *progname = NULL, *execstr = NULL, *p = NULL; int rc; progname = carbon.areaName; #ifdef HAS_popen_close if (*progname == '|') { msgfp = popen(progname + 1, "w"); } else #endif msgfp = createTempTextFile(config, &fname); if (!msgfp) { w_log(LL_ERR, "external process %s: cannot create file", progname); return 1; } else w_log(LL_FILE,"toss.c:processExternal() opened %s %s", fname?"file":"pipe", fname?fname:progname); /* Output header info */ if (!msg->netMail) fprintf(msgfp, "Area: %s\n", echo->areaName); fprintf(msgfp, "From: \"%s\" %s\n", msg->fromUserName, aka2str(msg->origAddr)); fprintf(msgfp, "To: \"%s\" %s\n", msg->toUserName, aka2str(msg->destAddr)); fprintf(msgfp, "Date: \"%s\"\n", msg->datetime); fprintf(msgfp, "Subject: \"%s\"\n\n", msg->subjectLine); /* Output msg text */ for (p = msg->text; *p ; p++) if (*p == '\r') fputc('\n', msgfp); else fputc(*p, msgfp); fputc('\n', msgfp); #ifdef HAS_popen_close if (*progname == '|') { pclose(msgfp); rc = 0; } else #endif { /* Execute external program */ fclose(msgfp); execstr = safe_malloc(strlen(progname)+strlen(fname)+3); if (*progname == '|') sprintf(execstr, "%s < %s", progname+1, fname); else sprintf(execstr, "%s %s", progname, fname); #ifdef __NT__ CharToOem(execstr, execstr); /* this is really need? */ #endif rc = cmdcall(execstr); nfree(execstr); unlink(fname); nfree(fname); } /* if (rc == -1 || rc == 127) */ if (rc) /* system() return exit status returned by shell */ w_log(LL_ERR, "Execution of external program failed. Cmd is: %s", execstr); return 0; } /* area - area to carbon messages, echo - original echo area */ int processCarbonCopy (s_area *area, s_area *echo, s_message *msg, s_carbon carbon) { char *p, *text, *line, *old_text, *reason = carbon.reason; int i, old_textLength, export = carbon.export, rc = 0; statToss.CC++; old_textLength = msg->textLength; old_text = msg->text; i = old_textLength; /* recoding from internal to transport charSet if needed */ if (config->outtab) { if (msg->recode & REC_TXT) { recodeToTransportCharset((CHAR*)msg->text); msg->recode &= ~REC_TXT; } if (msg->recode & REC_HDR) { recodeToTransportCharset((CHAR*)msg->fromUserName); recodeToTransportCharset((CHAR*)msg->toUserName); recodeToTransportCharset((CHAR*)msg->subjectLine); msg->recode &= ~REC_HDR; } if (reason) recodeToTransportCharset((CHAR*)reason); } msg->text = NULL; msg->textLength = 0; line = old_text; if (!msg->netMail) { xstrscat(&msg->text, (export) ? "AREA:" : "", (export) ? area->areaName : "", (export) ? "\r" : "", "\001AREA:", echo->areaName, "\r" , NULL); } if (strncmp(line, "AREA:", 5) == 0) { /* jump over AREA:xxxxx\r */ line+=5; while (*line && *line != '\r') line++; if (*line) line++; } while(*line == '\001') { p = strchr(line, '\r'); if(!p) break; /* Temporary make it \0 terminated string */ *p = '\0'; xstrcat(&msg->text,line); /* and then we *must* put '\r' back. */ xstrcat(&msg->text, "\r"); *p = '\r'; line = p+1; } text = line; /* may be old_test or old_text w/o begining kluges */ if (!msg->netMail) { if ((!config->carbonKeepSb) && (!area->keepsb)) { line = strrstr(text, " * Origin:"); if (NULL != (p = strstr(line ? line : text,"\rSEEN-BY:"))) i = (size_t) (p - text) + 1; } xstrscat(&msg->text, msg->text ? (msg->text[strlen(msg->text)-1] == '\r' ?"":"\r") : "" , (config->carbonExcludeFwdFrom) ? "" : " * Forwarded from area '", (config->carbonExcludeFwdFrom) ? "" : echo->areaName, (config->carbonExcludeFwdFrom) ? "" : "'\r", (reason) ? reason : "", (reason) ? "\r" : "", NULL); msg->textLength = strlen(msg->text); } xstralloc(&msg->text,i); /* add i bytes */ strncat(msg->text,text,i); /* copy rest of msg */ msg->textLength += i; if (!export) { if (msg->netMail) rc = putMsgInArea(area,msg,0,MSGSENT); else rc = putMsgInArea(area,msg,0,0); area->imported++; /* area has got new messages */ } else if (!msg->netMail) { rc = processEMMsg(msg, *area->useAka, 1, 0); } else rc = processNMMsg(msg, NULL, area, 1, 0); nfree(msg->text); msg->textLength = old_textLength; msg->text = old_text; msg->recode &= ~REC_TXT; /* old text is always in Transport Charset */ if (config->intab && reason) recodeToInternalCharset((CHAR*)reason); return rc; } /* Does carbon copying */ /* Return value: 0 if nothing happend, 1 if there was a carbon copy, > 1 if there was a carbon move or carbon delete*/ int carbonCopy(s_message *msg, XMSG *xmsg, s_area *echo) { unsigned int i, rc = 0, result=0; char *testptr = NULL, *testptr2 = NULL, *pattern = NULL; s_area *area = NULL; s_carbon *cb=&(config->carbons[0]); s_area **copiedTo = NULL; int copiedToCount = 0; int ncop; if(!msg) return 0; if (echo->ccoff==1) return 0; if (echo->msgbType==MSGTYPE_PASSTHROUGH && config->exclPassCC) return 0; for (i=0; icarbonCount; i++,++cb) { /* Dont come to use netmail on echomail and vise verse */ if (cb->move!=2 && ((msg->netMail && !cb->netMail) || (!msg->netMail && cb->netMail))) continue; area = cb->area; if(!cb->rule&CC_AND) /* not AND & not AND-NOT */ { if (!cb->extspawn && /* fix for extspawn */ cb->areaName != NULL && /* fix for carbonDelete */ /* dont CC to the echo the mail comes from */ !sstricmp(echo->areaName,area->areaName) ) continue; } switch (cb->ctype) { case ct_to: result=patimat(msg->toUserName,cb->str); break; case ct_from: result=patimat(msg->fromUserName,cb->str); break; case ct_kludge: case ct_msgtext: testptr=msg->text; /* skip area: kludge */ if (strncmp(testptr, "AREA:", 5) == 0) { if ((testptr = strchr(testptr, '\r')) != NULL) testptr++; } /* cb->str is substring, so pattern must be "*str*" */ pattern=safe_malloc(strlen(cb->str)+3); *pattern='*'; sstrcpy(pattern+1, cb->str); strcat(pattern, "*"); result=0; /* check the message line by line */ while (testptr) { testptr2 = strchr(testptr, '\r'); if ((*testptr == '\001' && cb->ctype == ct_kludge) || (*testptr != '\001' && cb->ctype == ct_msgtext)) { if (testptr2) *testptr2 = '\0'; result = patimat(testptr, pattern); if (testptr2) *testptr2 = '\r'; if (result) break; } if (testptr2) testptr = testptr2+1; else break; } nfree(pattern); break; case ct_subject: result=patimat(msg->subjectLine,cb->str); break; case ct_addr: result=!addrComp(msg->origAddr, cb->addr); break; case ct_fromarea: result=patimat(echo->areaName,cb->str); break; case ct_group: if(echo->group!=NULL){ /* cb->str for example Fido,xxx,.. */ testptr=cb->str; do{ if(NULL==(testptr=fc_stristr(echo->group,testptr))) break; testptr+=strlen(echo->group); result=(*testptr==',' || *testptr==' ' || !*testptr); testptr-=strlen(echo->group); ++testptr; }while(!result); } break; } if(cb->rule&CC_NOT) /* NOT on/off */ result=!result; switch(cb->rule&CC_AND){ /* what operation with next result */ case CC_OR: /* OR */ if (result && area && cb->move!=2 && !config->carbonAndQuit) { /* check if we've done cc to dest area already */ for (ncop=0; ncop < copiedToCount && result; ncop++) if (area == copiedTo[ncop]) result = 0; if (result) { copiedTo = safe_realloc (copiedTo, (copiedToCount+1) * sizeof (s_area *)); copiedTo[copiedToCount] = area; copiedToCount++; } } if(result){ /* make cc */ /* Set value: 1 if copy 3 if move */ rc = cb->move ? 3 : 1; if(cb->extspawn) processExternal(echo,msg,*cb); else if (cb->areaName && cb->move!=2) { if (!processCarbonCopy(area,echo,msg,*cb)) rc &= 1; } /* delete CarbonMove and CarbonDelete messages */ if (cb->move && xmsg) xmsg->attr |= MSGKILL; if (config->carbonAndQuit) /* not skip quit or delete */ if ((cb->areaName && *cb->areaName!='*') || cb->move==2) { return rc; } } break; case CC_AND: /* AND & AND-NOT */ if(!result){ /* following expressions can be skipped until OR */ for (++i,++cb; icarbonCount; i++,++cb) if(!(cb->rule&CC_AND)) /* AND & AND-NOT */ break; /* this is the last in the AND expr. chain */ } /* else result==TRUE, so continue with next expr. */ break; } } /* end for() */ if (copiedTo) nfree (copiedTo); return rc; }