/*****************************************************************************
* AreaFix for HTICK (FTN Ticker / Request Processor)
*****************************************************************************
* Copyright (C) 1998-2000
*
* Max Levenkov
*
* Fido: 2:5000/117
* Internet: sackett@mail.ru
*
* Novosibirsk, West Siberia, Russia
*
* This file is part of HTICK, which is based on HPT by Matthias Tichy,
* 2:2432/605.14 2:2433/1245, mtt@tichy.de
*
* HTICK 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.
*
* HTICK 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 HTICK; see the file COPYING. If not, write to the Free
* Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*****************************************************************************
* $Id: areafix.c,v 1.70.2.5 2003/02/04 19:18:16 stas_degteff Exp $
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#if ((!(defined(_MSC_VER) && (_MSC_VER >= 1200)) ) && (!defined(__TURBOC__)))
#include <unistd.h>
#endif
#include <fidoconf/fidoconf.h>
#include <fidoconf/common.h>
#include <fidoconf/xstr.h>
#include <fidoconf/afixcmd.h>
#include <fidoconf/arealist.h>
#include <smapi/prog.h>
#include <smapi/patmat.h>
#include <fcommon.h>
#include <global.h>
#include <version.h>
#include <toss.h>
#include <areafix.h>
#include <hatch.h>
#include <scan.h>
#include <add_desc.h>
unsigned char RetFix;
char *hpt_stristr(char *str, char *find);
char *errorRQ(char *line)
{
char *report = NULL, err[] = "Error line";
xscatprintf(&report,"%s %s\r", line, err);
return report;
}
int subscribeCheck(s_filearea area, s_message *msg, s_link *link)
{
unsigned int i;
int found = 0;
for (i = 0; i<area.downlinkCount;i++)
{
if (addrComp(msg->origAddr, area.downlinks[i]->link->hisAka)==0) return 0;
}
if (area.group)
{
if (link->numAccessGrp > 0)
{
for (i = 0; i < link->numAccessGrp; i++)
if (strcmp(area.group, link->AccessGrp[i]) == 0) found = 1;
}
if (config->numPublicGroup > 0)
{
for (i = 0; i < config->numPublicGroup; i++)
if (strcmp(area.group, config->PublicGroup[i]) == 0) found = 1;
}
}
else found = 1;
if (found == 0) return 2;
if (area.hide) return 3;
return 1;
}
int subscribeAreaCheck(s_filearea *area, s_message *msg, char *areaname, s_link *link) {
int rc=4;
if (!areaname) return rc;
if (patimat(area->areaName,areaname)==1) {
rc=subscribeCheck(*area, msg, link);
// 0 - already subscribed
// 1 - need subscribe
// 2 - no access group
// 3 - area is hidden
if (area->mandatory) rc = 2;
} else rc = 4; // this is another area
return rc;
}
void addlink(s_link *link, s_filearea *area) {
s_arealink *arealink;
area->downlinks = srealloc(area->downlinks, sizeof(s_arealink*)*(area->downlinkCount+1));
area->downlinks[area->downlinkCount] = (s_arealink*)scalloc(1, sizeof(s_arealink));
area->downlinks[area->downlinkCount]->link = link;
arealink = area->downlinks[area->downlinkCount];
if (link->numOptGrp > 0) {
// default set export on, import on, mandatory off
arealink->export = 1;
arealink->import = 1;
arealink->mandatory = 0;
if (grpInArray(area->group,link->optGrp,link->numOptGrp)) {
arealink->export = link->export;
arealink->import = link->import;
arealink->mandatory = link->mandatory;
}
} else {
arealink->export = link->export;
arealink->import = link->import;
arealink->mandatory = link->mandatory;
}
if (area->mandatory) arealink->mandatory = 1;
if (link->level < area->levelread) arealink->export=0;
if (link->level < area->levelwrite) arealink->import=0;
// paused link can't receive mail
if ((link->Pause & FPAUSE) == FPAUSE) arealink->export = 0;
area->downlinkCount++;
}
void removelink(s_link *link, s_filearea *area) {
unsigned int i;
s_link *links;
for (i=0; i < area->downlinkCount; i++) {
links = area->downlinks[i]->link;
if (addrComp(link->hisAka, links->hisAka)==0) break;
}
free(area->downlinks[i]);
area->downlinks[i] = area->downlinks[area->downlinkCount-1];
area->downlinkCount--;
}
char *unlinked(s_message *msg, s_link *link)
{
unsigned int i, rc, n;
char *report=NULL;
s_filearea *area;
area=config->fileAreas;
xscatprintf(&report, "Unlinked areas to %s\r\r", aka2str(link->hisAka));
for (i=n=0; i<config->fileAreaCount; i++) {
rc=subscribeCheck(area[i], msg, link);
if (rc == 1) {
xscatprintf(&report, " %s\r", area[i].areaName);
n++;
}
}
xscatprintf(&report, "\r%u areas unlinked\r", n);
w_log( '8', "FileFix: unlinked fileareas list sent to %s", aka2str(link->hisAka));
return report;
}
char *list(s_message *msg, s_link *link) {
unsigned int i,j,active,avail,rc,desclen;
unsigned int *areaslen;
unsigned int maxlen;
char *report=NULL;
int readdeny, writedeny;
areaslen = smalloc(config->fileAreaCount * sizeof(int));
maxlen = 0;
for (i=0; i< config->fileAreaCount; i++) {
areaslen[i]=strlen(config->fileAreas[i].areaName);
if (areaslen[i]>maxlen) maxlen = areaslen[i];
}
xscatprintf(&report, "Available fileareas for %s\r\r", aka2str(link->hisAka));
for (i=active=avail=0; i< config->fileAreaCount; i++) {
rc=subscribeCheck(config->fileAreas[i],msg, link);
if (rc < 2) {
if (config->fileAreas[i].description!=NULL)
desclen=strlen(config->fileAreas[i].description);
else
desclen=0;
if (rc==0) {
readdeny = readCheck(&config->fileAreas[i], link);
writedeny = writeCheck(&config->fileAreas[i], &(link->hisAka));
if (!readdeny && !writedeny)
xstrcat(&report,"& ");
else if (writedeny)
xstrcat(&report,"+ ");
else xstrcat(&report,"* ");
active++;
avail++;
} else {
xstrcat(&report," ");
avail++;
}
xstrcat(&report, config->fileAreas[i].areaName);
if (desclen!=0) {
xstrcat(&report," ");
for (j=0;j<(maxlen)-areaslen[i];j++)
xstrcat(&report,".");
xstrcat(&report," ");
xstrcat(&report,config->fileAreas[i].description);
}
xstrcat(&report,"\r");
}
}
xscatprintf(&report, "\r '+' You are receiving files from this area.\r '*' You can send files to this file echo.\r '&' You can send and receive files.\r\r%i areas available for %s, %i areas active\r", avail, aka2str(link->hisAka), active);
w_log( LL_AREAFIX, "FileFix: list sent to %s", aka2str(link->hisAka));
nfree(areaslen);
return report;
}
char *linked(s_message *msg, s_link *link, int action)
{
unsigned int i, n, rc;
char *report=NULL;
int readdeny, writedeny;
if ((link->Pause & FPAUSE) == FPAUSE)
xscatprintf(&report, "\rPassive fileareas on %s\r\r", aka2str(link->hisAka));
else
xscatprintf(&report, "\rActive fileareas on %s\r\r", aka2str(link->hisAka));
for (i=n=0; i<config->fileAreaCount; i++) {
rc=subscribeCheck(config->fileAreas[i], msg, link);
if (rc==0) {
if (action == 1) {
readdeny = readCheck(&config->fileAreas[i], link);
writedeny = writeCheck(&config->fileAreas[i], &(link->hisAka));
if (!readdeny && !writedeny)
xstrcat(&report,"& ");
else if (writedeny)
xstrcat(&report,"+ ");
else
xstrcat(&report,"* ");
} else {
xstrcat(&report," ");
}
xstrcat(&report, config->fileAreas[i].areaName);
xstrcat(&report, "\r");
n++;
}
}
if (action == 1)
xscatprintf(&report, "\r '+' You are receiving files from this area.\r '*' You can send files to this file echo.\r '&' You can send and receive files.\r\r%u areas linked for %s\r", n, aka2str(link->hisAka));
else
xscatprintf(&report, "\r%u areas linked\r", n);
return report;
}
char *help(s_link *link) {
FILE *f;
int i=1;
char *help = NULL;
long endpos;
if (config->filefixhelp!=NULL) {
if ((f=fopen(config->filefixhelp,"r")) == NULL)
{
if (!quiet) fprintf(stderr,"FileFix: cannot open help file \"%s\"\n",
config->filefixhelp);
return NULL;
}
fseek(f,0l,SEEK_END);
endpos=ftell(f);
help=(char*) scalloc((size_t) endpos + 1,sizeof(char));
fseek(f,0l,SEEK_SET);
endpos = fread(help,1,(size_t) endpos,f);
for (i=0; i<endpos; i++) {
if (help[i]=='\r' && (i+1)<endpos && help[i+1]=='\n') help[i]=' ';
if (help[i]=='\n') help[i]='\r';
}
fclose(f);
w_log( LL_AREAFIX, "FileFix: help sent to %s", aka2str(link->hisAka));
return help;
}
return NULL;
}
char *available(s_link *link) {
FILE *f;
unsigned int j=0, found;
unsigned int k;
char *report = NULL, *line, *token, *running, linkAka[SIZE_aka2str];
s_link *uplink=NULL;
ps_arealist al;
for (j = 0; j < config->linkCount; j++) {
uplink = &(config->links[j]);
found = 0;
for (k = 0; k < link->numAccessGrp && uplink->LinkGrp; k++)
if (strcmp(link->AccessGrp[k], uplink->LinkGrp) == 0)
found = 1;
if ((uplink->forwardFileRequests && uplink->forwardFileRequestFile) &&
((uplink->LinkGrp == NULL) || (found != 0))) {
if ((f=fopen(uplink->forwardFileRequestFile,"r")) == NULL) {
w_log(LL_AREAFIX, "Filefix: cannot open forwardFileRequestFile \"%s\": %s",
uplink->forwardFileRequestFile, strerror(errno));
return report;
}
xscatprintf(&report, "Available File List from %s:\r",
aka2str(uplink->hisAka));
al = newAreaList();
while ((line = readLine(f)) != NULL) {
line = trimLine(line);
if (line[0] != '\0') {
running = line;
token = strseparate(&running, " \t\r\n");
addAreaListItem(al,0,token,running);
}
nfree(line);
}
fclose(f);
if(al->count) {
sortAreaList(al);
line = formatAreaList(al,78,NULL);
xstrcat(&report,"\r");
xstrcat(&report,line);
nfree(line);
}
freeAreaList(al);
xscatprintf(&report, " %s\r\r",print_ch(77,'-'));
// warning! do not ever use aka2str twice at once!
sprintf(linkAka, "%s", aka2str(link->hisAka));
w_log(LL_AREAFIX, "Filefix: Available File List from %s sent to %s", aka2str(uplink->hisAka), linkAka);
}
}
if (report==NULL) {
xstrcat(&report, "\r no links for creating Available File List\r");
w_log(LL_AREAFIX, "Filefix: no links for creating Available File List");
}
return report;
}
int changeconfig(char *fileName, s_filearea *area, s_link *link, int action) {
FILE *f_conf;
char *cfgline = NULL, *line = NULL, *token = NULL, *areaName = NULL, *tmpPtr =NULL;
long endpos, cfglen;
long strbeg = 0, strend = -1;
areaName = area->areaName;
if (init_conf(fileName))
return 1;
while ((cfgline = configline()) != NULL) {
line = sstrdup(cfgline);
line = trimLine(line);
line = stripComment(line);
if (line[0] != 0) {
tmpPtr = line = shell_expand(line);
token = strseparate(&tmpPtr, " \t");
if (stricmp(token, "filearea")==0) {
token = strseparate(&tmpPtr, " \t");
if (stricmp(token, areaName)==0) {
fileName = sstrdup(getCurConfName());
strend = get_hcfgPos();
break;
}
}
}
strbeg = get_hcfgPos();
nfree(cfgline);
nfree(line);
}
close_conf();
nfree(line);
if (strend == -1) {
nfree(cfgline);
nfree(fileName);
return 1; // impossible
}
if ((f_conf=fopen(fileName,"r+b")) == NULL)
{
if (!quiet) fprintf(stderr, "FileFix: cannot open config file %s \n", fileName);
nfree(cfgline);
nfree(fileName);
return 1;
}
nfree(fileName);
fseek(f_conf, 0L, SEEK_END);
endpos = ftell(f_conf);
cfglen = endpos - strend;
line = (char*) smalloc((size_t) cfglen+1);
fseek(f_conf, strend, SEEK_SET);
cfglen = fread(line, sizeof(char), cfglen, f_conf);
line[cfglen]='\0';
fseek(f_conf, strbeg, SEEK_SET);
setfsize( fileno(f_conf), strbeg );
switch (action) {
case 0:
xstrscat(&cfgline, " ", aka2str(link->hisAka), NULL);
break;
case 1:
DelLinkFromString(cfgline, link->hisAka);
break;
default: break;
}
fprintf(f_conf, "%s%s%s", cfgline, cfgEol(), line);
fclose(f_conf);
nfree(line);
nfree(cfgline);
return 0;
}
// subscribe if (act==0), unsubscribe if (act==1)
int forwardRequestToLink( char *areatag, char *descr,
s_link *uplink, s_link *dwlink,
int act)
{
s_message *msg;
char *base, pass[]="passthrough";
if (uplink->msg == NULL) {
msg = makeMessage(uplink->ourAka, &(uplink->hisAka), config->sysop,
uplink->RemoteFileRobotName ? uplink->RemoteFileRobotName : "filefix",
uplink->fileFixPwd ? uplink->fileFixPwd : "\x00", 1,
config->filefixKillReports);
msg->text = createKludges(config->disableTID,NULL,
uplink->ourAka, &(uplink->hisAka),
versionStr);
uplink->msg = msg;
} else msg = uplink->msg;
if (act==0) {
if (getFileArea(config, areatag) == NULL) {
base = uplink->fileBaseDir;
if (config->createFwdNonPass == 0) uplink->fileBaseDir = pass;
// create from own address
if (isOurAka(config,dwlink->hisAka)) {
uplink->fileBaseDir = base;
}
autoCreate(areatag, descr, &(uplink->hisAka), &(dwlink->hisAka));
uplink->fileBaseDir = base;
}
xstrscat(&msg->text, "+", areatag, "\r", NULL);
} else {
xscatprintf(&(msg->text), "-%s\r", areatag);
}
return 0;
}
static int compare_links_priority(const void *a, const void *b) {
int ia = *((int*)a);
int ib = *((int*)b);
if(config->links[ia].forwardFilePriority < config->links[ib].forwardFilePriority) return -1;
else if(config->links[ia].forwardFilePriority > config->links[ib].forwardFilePriority) return 1;
else return 0;
}
int forwardRequest(char *areatag, s_link *dwlink) {
unsigned int i, rc = 1;
s_link *uplink;
int *Indexes;
unsigned int Requestable = 0;
/* From Lev Serebryakov -- sort Links by priority */
Indexes = smalloc(sizeof(int)*config->linkCount);
for (i = 0; i < config->linkCount; i++) {
if (config->links[i].forwardFileRequests) Indexes[Requestable++] = i;
}
qsort(Indexes,Requestable,sizeof(Indexes[0]),compare_links_priority);
for (i = 0; i < Requestable; i++) {
uplink = &(config->links[Indexes[i]]);
if (uplink->forwardFileRequests && (uplink->LinkGrp) ?
grpInArray(uplink->LinkGrp,dwlink->AccessGrp,dwlink->numAccessGrp) : 1)
{
char *descr = NULL;
if (uplink->forwardFileRequestFile!=NULL) {
// first try to find the areatag in forwardRequestFile
if (IsAreaAvailable(areatag,uplink->forwardFileRequestFile,&descr,1))
{
forwardRequestToLink(areatag,descr,uplink,dwlink,0);
rc = 0;
}
else
{ rc = 2; }// found link with freqfile, but there is no areatag
nfree(descr);
} else {
forwardRequestToLink(areatag,descr,uplink,dwlink,0);
rc = 0;
}//(uplink->forwardRequestFile!=NULL)
if (rc==0) {
nfree(Indexes);
return rc;
}
} // if (uplink->forwardFileRequests && (uplink->LinkGrp) ?
} // for (i = 0; i < Requestable; i++) {
// link with "forwardFileRequests on" not found
nfree(Indexes);
return rc;
}
char *subscribe(s_link *link, s_message *msg, char *cmd) {
unsigned int i, c, rc=4,found=0;
char *line, *report = NULL;
s_filearea *area;
line = cmd;
if (line[0]=='+') line++;
report=(char*)scalloc(1, sizeof(char));
for (i=0; i<config->fileAreaCount; i++) {
rc=subscribeAreaCheck(&(config->fileAreas[i]),msg,line, link);
if (rc == 4) continue;
area = &(config->fileAreas[i]);
for (c = 0; c<area->downlinkCount; c++) {
if (link == area->downlinks[c]->link) {
if (area->downlinks[c]->mandatory) rc=5;
break;
}
}
found = 1;
switch (rc) {
case 0:
xscatprintf(&report, "%s Already linked\r", area->areaName);
w_log( LL_AREAFIX, "FileFix: %s already linked to %s", aka2str(link->hisAka), area->areaName);
break;
case 1:
case 3:
changeconfig (getConfigFileName(), area, link, 0);
addlink(link, area);
xscatprintf(&report, "%s Added\r",area->areaName);
w_log( LL_AREAFIX, "FileFix: %s subscribed to %s",aka2str(link->hisAka),area->areaName);
break;
case 5:
xscatprintf(&report, "%s Link is not possible\r", area->areaName);
w_log( LL_AREAFIX, "FileFix: area %s -- link is not possible for %s", area->areaName, aka2str(link->hisAka));
break;
default :
xscatprintf(&report, "%s No access\r", area->areaName);
w_log( LL_AREAFIX, "FileFix: filearea %s -- no access for %s", area->areaName, aka2str(link->hisAka));
continue;
}
}
if(rc == 4 && link->denyFRA==0 && !found)
{
// try to forward request
if ((rc=forwardRequest(line, link))==2) {
xscatprintf(&report, "%s no uplinks to forward\r", line);
w_log( LL_AREAFIX, "Filefix: %s - no uplinks to forward", line);
}
else if (rc==0) {
xscatprintf(&report, "%s request forwarded\r", line);
w_log( LL_AREAFIX, "Filefix: %s - request forwarded", line);
}
}
if (*report == '\0') {
xscatprintf(&report,"%s Not found\r",line);
w_log( LL_AREAFIX, "FileFix: filearea %s is not found",line);
}
return report;
}
char *unsubscribe(s_link *link, s_message *msg, char *cmd) {
unsigned int i, c, rc = 2;
char *line;
char *report=NULL;
s_filearea *area;
line = cmd;
if (line[1]=='-') return NULL;
line++;
for (i = 0; i< config->fileAreaCount; i++) {
rc=subscribeAreaCheck(&(config->fileAreas[i]),msg,line, link);
if ( rc==4 ) continue;
area = &(config->fileAreas[i]);
for (c = 0; c<area->downlinkCount; c++) {
if (link == area->downlinks[c]->link) {
if (area->downlinks[c]->mandatory) rc=5;
break;
}
}
switch (rc) {
case 0: removelink(link, area);
changeconfig (getConfigFileName(), area, link, 1);
xscatprintf(&report, "%s Unlinked\r",area->areaName);
w_log( '8', "FileFix: %s unlinked from %s",aka2str(link->hisAka),area->areaName);
break;
case 1: if (strstr(line, "*")) continue;
xscatprintf(&report, "%s Not linked\r",line);
w_log( '8', "FileFix: area %s is not linked to %s", area->areaName, aka2str(link->hisAka));
break;
case 5:
xscatprintf(&report, "%s Unlink is not possible\r", area->areaName);
w_log( '8', "FileFix: area %s -- unlink is not possible for %s", area->areaName, aka2str(link->hisAka));
break;
default: w_log( '8', "FileFix: area %s -- no access for %s", area->areaName, aka2str(link->hisAka));
continue;
}
}
if (!report) {
xscatprintf(&report, "%s Not found\r",line);
w_log( '8', "FileFix: area %s is not found", line);
}
return report;
}
char *resend(s_link *link, s_message *msg, char *cmd)
{
unsigned int rc, i;
char *line;
char *report=NULL, *token = NULL, *filename=NULL, *filearea=NULL;
s_filearea *area = NULL;
line = cmd;
line=stripLeadingChars(line, " \t");
token = strtok(line, " \t\0");
if (token == NULL)
{
xscatprintf(&report, "Error in line! Format: %%Resend <file> <filearea>\r");
return report;
}
filename = sstrdup(token);
token=stripLeadingChars(strtok(NULL, "\0"), " ");
if (token == NULL)
{
nfree(filename);
xscatprintf(&report, "Error in line! Format: %%Resend <file> <filearea>\r");
return report;
}
filearea = sstrdup(token);
area = getFileArea(config,filearea);
if (area != NULL) {
rc = 1;
for (i = 0; i<area->downlinkCount;i++)
if (addrComp(msg->origAddr, area->downlinks[i]->link->hisAka)==0)
rc = 0;
if (rc == 1 && area->mandatory == 1) rc = 5;
else rc = send(filename,filearea,aka2str(link->hisAka));
switch (rc) {
case 0: xscatprintf(&report, "Send %s from %s for %s\r",
filename,filearea,aka2str(link->hisAka));
break;
case 1: xscatprintf(&report, "Error: Passthrough filearea %s!\r",filearea);
w_log( '8', "FileFix %%Resend: Passthrough filearea %s", filearea);
break;
case 2: xscatprintf(&report, "Error: Filearea %s not found!\r",filearea);
w_log( '8', "FileFix %%Resend: Filearea %s not found", filearea);
break;
case 3: xscatprintf(&report, "Error: File %s not found!\r",filename);
w_log( '8', "FileFix %%Resend: File %s not found", filename);
break;
case 5: xscatprintf(&report, "Error: You don't have access for filearea %s!\r",filearea);
w_log( '8', "FileFix %%Resend: Link don't have access for filearea %s", filearea);
break;
}
} else {
xscatprintf(&report, "Error: filearea %s not found!\r",filearea);
w_log( '8', "FileFix %%Resend: Filearea %s not found", filearea);
}
nfree(filearea);
nfree(filename);
return report;
}
char *pause_link(s_message *msg, s_link *link)
{
char *tmp = NULL;
char *report=NULL;
if ((link->Pause & FPAUSE) != FPAUSE) {
if (Changepause(getConfigFileName(), link,0,FPAUSE) == 0)
return NULL;
}
xstrcat(&report, " System switched to passive\r");
tmp = linked (msg, link, 0);
xstrcat(&report, tmp);
nfree(tmp);
return report;
}
char *resume_link(s_message *msg, s_link *link)
{
char *tmp = NULL, *report=NULL;
if ((link->Pause & FPAUSE) == FPAUSE) {
if (Changepause(getConfigFileName(), link,0,FPAUSE) == 0)
return NULL;
}
xstrcat(&report, " System switched to active\r");
tmp = linked(msg, link, 0);
xstrcat(&report, tmp);
nfree(tmp);
return report;
}
int tellcmd(char *cmd) {
char *line = NULL;
if (strncasecmp(cmd, "* Origin:", 9) == 0) return NOTHING;
line = strpbrk(cmd, " \t");
if (line && *cmd != '%') *line = 0;
line = cmd;
switch (line[0]) {
case '%':
line++;
if (*line == 0) return ERROR;
if (stricmp(line,"list")==0) return LIST;
if (stricmp(line,"help")==0) return HELP;
if (stricmp(line,"unlinked")==0) return UNLINK;
if (stricmp(line,"linked")==0) return LINKED;
if (stricmp(line,"avail")==0) return AVAIL;
if (stricmp(line,"query")==0) return LINKED;
if (stricmp(line,"pause")==0) return PAUSE;
if (stricmp(line,"resume")==0) return RESUME;
if (stricmp(line,"info")==0) return INFO;
if (strncasecmp(line, "resend", 6)==0)
if (line[6] != 0) return RESEND;
return ERROR;
case '\001': return NOTHING;
case '\000': return NOTHING;
case '-' : return DEL;
case '+': line++; if (line[0]=='\000') return ERROR;
default: return ADD;
}
return 0;
}
char *processcmd(s_link *link, s_message *msg, char *line, int cmd) {
char *report = NULL;
switch (cmd) {
case NOTHING: return NULL;
case LIST: report = list (msg, link);
RetFix=LIST;
break;
case HELP: report = help (link);
RetFix=HELP;
break;
case ADD: report = subscribe (link,msg,line);
RetFix=ADD;
break;
case DEL: report = unsubscribe (link,msg,line);
RetFix=DEL;
break;
case UNLINK: report = unlinked (msg, link);
RetFix=UNLINK;
break;
case LINKED: report = linked (msg, link, 1);
RetFix=LINKED;
break;
case AVAIL: report = available (link);
RetFix=AVAIL;
break;
case PAUSE: report = pause_link (msg, link);
RetFix=PAUSE;
break;
case RESUME: report = resume_link (msg, link);
RetFix=RESUME;
break;
/* case INFO: report = info_link(msg, link);
RetFix=INFO;
break;*/
case RESEND: report = resend(link, msg, line+7);
RetFix=RESEND;
break;
case ERROR: report = errorRQ(line);
RetFix=ERROR;
break;
default: return NULL;
}
return report;
}
char *areastatus(char *preport, char *text)
{
char *pth = NULL, *ptmp = NULL, *tmp = NULL, *report = NULL, tmpBuff[256];
pth = (char*)scalloc(1, sizeof(char));
tmp = preport;
ptmp = strchr(tmp, '\r');
while (ptmp) {
*ptmp=0;
ptmp++;
report=strchr(tmp, ' ');
*report=0;
report++;
if (strlen(tmp) > 50) tmp[50] = 0;
if (50-strlen(tmp) == 0) sprintf(tmpBuff, " %s %s\r", tmp, report);
else if (50-strlen(tmp) == 1) sprintf(tmpBuff, " %s %s\r", tmp, report);
else sprintf(tmpBuff, " %s %s %s\r", tmp, print_ch(50-strlen(tmp)-1, '.'), report);
pth=(char*)srealloc(pth, strlen(tmpBuff)+strlen(pth)+1);
strcat(pth, tmpBuff);
tmp=ptmp;
ptmp = strchr(tmp, '\r');
}
tmp = (char*)scalloc(strlen(pth)+strlen(text)+1, sizeof(char));
strcpy(tmp, text);
strcat(tmp, pth);
free(text);
free(pth);
return tmp;
}
void preprocText(char *preport, s_message *msg)
{
msg->text = createKludges(config->disableTID,
NULL, &msg->origAddr, &msg->destAddr,
versionStr);
xstrcat(&msg->text, "\001FLAGS NPD\r");
xstrcat(&msg->text, preport);
xscatprintf(&msg->text, " \r--- %s FileFix\r", versionStr);
msg->textLength=(int)strlen(msg->text);
}
char *textHead(void)
{
char *text_head=NULL;
xscatprintf(&text_head, " FileArea%sStatus\r", print_ch(44,' '));
xscatprintf(&text_head, " %s -------------------------\r",print_ch(50, '-'));
return text_head;
}
void RetMsg(s_message *msg, s_link *link, char *report, char *subj)
{
s_message *tmpmsg;
tmpmsg = makeMessage(link->ourAka, &(link->hisAka), msg->toUserName, msg->fromUserName,
subj, 1,config->filefixKillReports);
preprocText(report, tmpmsg);
writeNetmail(tmpmsg, config->robotsArea);
freeMsgBuffers(tmpmsg);
free(tmpmsg);
}
void sendFilefixMessages()
{
s_link *link = NULL;
s_message *linkmsg;
unsigned int i;
for (i = 0; i < config->linkCount; i++) {
if (config->links[i].msg == NULL) continue;
link = &(config->links[i]);
linkmsg = link->msg;
xscatprintf(&(linkmsg->text), " \r--- %s Filefix\r", versionStr);
linkmsg->textLength = strlen(linkmsg->text);
w_log(LL_AREAFIX, "Filefix: write netmail msg for %s", aka2str(link->hisAka));
writeNetmail(linkmsg, config->robotsArea);
freeMsgBuffers(linkmsg);
nfree(linkmsg);
link->msg = NULL;
}
}
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
int processFileFix(s_message *msg)
{
int security=1, notforme = 0;
s_link *link = NULL;
s_link *tmplink = NULL;
char *textBuff = NULL, *report=NULL, *preport = NULL, *token = NULL;
// find link
link=getLinkFromAddr(config, msg->origAddr);
// this is for me?
if (link!=NULL) notforme=addrComp(msg->destAddr, *link->ourAka);
// ignore msg for other link (maybe this is transit...)
if (notforme) {
return 2;
}
// security ckeck. link,araefixing & password.
if (link != NULL) {
if (link->FileFix==1) {
if (link->fileFixPwd!=NULL) {
if (stricmp(link->fileFixPwd,msg->subjectLine)==0) security=0;
else security=3;
}
} else security=2;
} else security=1;
if (!security) {
textBuff = msg->text;
token = strseparate (&textBuff, "\n\r");
while(token != NULL) {
preport = processcmd( link, msg, stripLeadingChars(token, " \t"), tellcmd (token) );
if (preport != NULL) {
switch (RetFix) {
case LIST:
RetMsg(msg, link, preport, "FileFix reply: list request");
break;
case HELP:
RetMsg(msg, link, preport, "FileFix reply: help request");
break;
case ADD: case DEL:
if (report == NULL) report = textHead();
report = areastatus(preport, report);
break;
case UNLINK:
RetMsg(msg, link, preport, "FileFix reply: unlinked request");
break;
case LINKED:
RetMsg(msg, link, preport, "FileFix reply: linked request");
w_log( '8', "FileFix: linked fileareas list sent to %s", aka2str(link->hisAka));
break;
case AVAIL:
RetMsg(msg, link, preport, "FileFix reply: avail request");
break;
case PAUSE: case RESUME:
RetMsg(msg, link, preport, "FileFix reply: node change request");
break;
case INFO:
RetMsg(msg, link, preport, "FileFix reply: link information");
break;
case RESEND:
RetMsg(msg, link, preport, "FileFix reply: resend request");
break;
case ERROR:
if (report == NULL) report = textHead();
report = areastatus(preport, report);
break;
default: break;
}
free(preport);
}
token = strseparate (&textBuff, "\n\r");
}
} else {
if (link == NULL) {
tmplink = (s_link*)scalloc(1, sizeof(s_link));
tmplink->ourAka = &(msg->destAddr);
tmplink->hisAka.zone = msg->origAddr.zone;
tmplink->hisAka.net = msg->origAddr.net;
tmplink->hisAka.node = msg->origAddr.node;
tmplink->hisAka.point = msg->origAddr.point;
link = tmplink;
}
// security problem
switch (security) {
case 1:
report = sstrdup(" \r your system is unknown\r");
break;
case 2:
report = sstrdup(" \r filefix is turned off\r");
break;
case 3:
report = sstrdup(" \r password error\r");
break;
default:
report = sstrdup(" \r unknown error. mail to sysop.\r");
break;
}
RetMsg(msg, link, report, "security violation");
free(report);
w_log( '8', "FileFix: security violation from %s", aka2str(link->hisAka));
free(tmplink);
return 0;
}
if ( report != NULL ) {
preport=linked(msg, link, 0);
xstrcat(&report, preport);
free(preport);
RetMsg(msg, link, report, "node change request");
free(report);
}
w_log( '8', "FileFix: sucessfully done for %s",aka2str(link->hisAka));
// send msg to the links (forward requests to areafix)
sendFilefixMessages();
return 1;
}
void ffix(s_addr addr, char *cmd)
{
s_link *link = NULL;
s_message *tmpmsg = NULL;
if (cmd) {
link = getLinkFromAddr(config, addr);
if (link) {
tmpmsg = makeMessage(&addr, link->ourAka, link->name,
link->RemoteRobotName ?
link->RemoteRobotName : "Filefix",
link->fileFixPwd ?
link->fileFixPwd : "", 1,
config->areafixKillReports);
tmpmsg->text = cmd;
processFileFix(tmpmsg);
tmpmsg->text=NULL;
freeMsgBuffers(tmpmsg);
} else w_log(LL_ERR, "FileFix: no such link in config: %s!", aka2str(addr));
}
else scan();
}
/* file echo autocreation */
int autoCreate(char *c_area, char *descr, s_addr* pktOrigAddr, s_addr* dwLink)
{
FILE *f;
char *NewAutoCreate = NULL;
char *fileName = NULL;
char *bDir = NULL;
char *fileechoFileName = NULL;
char *buff= NULL, hisaddr[20];
s_link *creatingLink;
s_message *msg;
s_filearea *area;
FILE *echotosslog;
creatingLink = getLinkFromAddr(config, *pktOrigAddr);
fileechoFileName = makeMsgbFileName(config, c_area);
// translating name of the area to lowercase/uppercase
if (config->createAreasCase == eUpper) strUpper(c_area);
else strLower(c_area);
// translating filename of the area to lowercase/uppercase
if (config->areasFileNameCase == eUpper) strUpper(fileechoFileName);
else strLower(fileechoFileName);
bDir = (creatingLink->fileBaseDir) ?
creatingLink->fileBaseDir : config->fileAreaBaseDir;
if (creatingLink->autoFileCreateSubdirs &&
strcasecmp(bDir,"passthrough"))
{
if (creatingLink->autoFileCreateSubdirs)
{
char *cp;
for (cp = fileechoFileName; *cp; cp++)
{
if (*cp == '.')
{
*cp = PATH_DELIM;
}
}
}
xscatprintf(&buff,"%s%s",bDir,fileechoFileName);
if (_createDirectoryTree(buff))
{
if (!quiet) fprintf(stderr, "cannot make all subdirectories for %s\n",
fileechoFileName);
nfree(buff);
return 1;
}
nfree(buff);
}
fileName = creatingLink->autoFileCreateFile;
if (fileName == NULL) fileName = getConfigFileName();
f = fopen(fileName, "a");
if (f == NULL) {
f = fopen(getConfigFileName(), "a");
if (f == NULL)
{
if (!quiet) fprintf(stderr,"autocreate: cannot open config file\n");
return 1;
}
}
/* making address of uplink */
strcpy(hisaddr,aka2str(*pktOrigAddr));
/* write new line in config file */
xscatprintf(&buff, "FileArea %s %s%s -a %s ",
c_area, bDir,
(strcasecmp(bDir,"passthrough") == 0) ? "" : fileechoFileName,
aka2str(*(creatingLink->ourAka))
);
if ( creatingLink->LinkGrp &&
!(creatingLink->autoFileCreateDefaults && (hpt_stristr(creatingLink->autoFileCreateDefaults, "-g ")!=NULL))
)
{
xscatprintf(&buff,"-g %s ",creatingLink->LinkGrp);
}
if (creatingLink->autoFileCreateDefaults) {
NewAutoCreate = sstrdup(creatingLink->autoFileCreateDefaults);
if ((fileName=strstr(NewAutoCreate,"-d ")) !=NULL ) {
if (descr) {
*fileName = '\0';
xscatprintf(&buff,"%s -d \"%s\"",NewAutoCreate,descr);
} else {
xstrcat(&buff, NewAutoCreate);
}
} else if (descr) {
xscatprintf(&buff,"%s -d \"%s\"",NewAutoCreate,descr);
}
nfree(NewAutoCreate);
}
else if (descr)
{
xscatprintf(&buff,"-d \"%s\"",descr);
}
xscatprintf(&buff," %s",hisaddr);
if(dwLink) xscatprintf(&buff," %s",aka2str(*dwLink));
if( fseek (f, -2L, SEEK_END) == 0)
{
char CR;
CR = getc (f); /* may be it is CR aka '\r' */
if (getc(f) != '\n') {
fseek (f, 0L, SEEK_END); /* not neccesary, but looks better ;) */
fputs (cfgEol(), f);
} else {
fseek (f, 0L, SEEK_END);
}
/* correct EOL in memory */
if(CR == '\r')
xstrcat(&buff,"\r\n"); /* DOS EOL */
else
xstrcat(&buff,"\n"); /* UNIX EOL */
} else {
xstrcat(&buff,(char*)cfgEol()); /* config depended EOL */
}
fprintf(f, "%s", buff);
fclose(f);
/* add new created echo to config in memory */
parseLine(buff,config);
w_log( '8', "FileArea '%s' autocreated by %s", c_area, hisaddr);
/* report about new filearea */
if (config->ReportTo && !cmAnnNewFileecho && (area = getFileArea(config, c_area)) != NULL) {
if (getNetMailArea(config, config->ReportTo) != NULL) {
msg = makeMessage(area->useAka,
area->useAka,
versionStr,
config->sysop,
"Created new fileareas", 1,
config->filefixKillReports);
msg->text = createKludges(config->disableTID,NULL, area->useAka,area->useAka,versionStr);
} else {
msg = makeMessage(area->useAka,
area->useAka,
versionStr,
"All", "Created new fileareas", 0,
config->filefixKillReports);
msg->text = createKludges(config->disableTID,config->ReportTo, area->useAka, area->useAka,versionStr);
} /* endif */
xstrcat(&msg->text, "\001FLAGS NPD\r");
sprintf(buff, "\r \rNew filearea: %s\r\rDescription : %s\r", area->areaName,
(area->description) ? area->description : "");
msg->text = (char*)srealloc(msg->text, strlen(msg->text)+strlen(buff)+1);
strcat(msg->text, buff);
writeMsgToSysop(msg, config->ReportTo);
freeMsgBuffers(msg);
nfree(msg);
if (config->echotosslog != NULL) {
echotosslog = fopen (config->echotosslog, "a");
fprintf(echotosslog,"%s\n",config->ReportTo);
fclose(echotosslog);
}
} else {
} /* endif */
if (cmAnnNewFileecho) announceNewFileecho (announcenewfileecho, c_area, hisaddr);
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1