/******************************************************************************
* HPT --- FTN NetMail/EchoMail Tosser
******************************************************************************
* carbon.c : functions for making carbon copy
*
* by Max Chernogor <mihz@ua.fm>, 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 <stdlib.h>
#include <string.h>
#include <smapi/compiler.h>
#ifdef HAS_PROCESS_H
# include <process.h>
#endif
#ifdef HAS_IO_H
#include <io.h>
#endif
#ifdef HAS_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAS_DOS_H
#include <dos.h>
#endif
#include <fidoconf/fidoconf.h>
#include <fidoconf/common.h>
#include <fidoconf/recode.h>
#include <fidoconf/temp.h>
#include <fidoconf/xstr.h>
#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; i<config->carbonCount; 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; i<config->carbonCount; 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;
}
syntax highlighted by Code2HTML, v. 0.9.1