/********************************************************
* File: mb_jam.c
* Created at Sun Jan 28 22:10:30 MSK 2001 by raorn // raorn@binec.ru
* JAM support
* $Id: mb_jam.c,v 1.23 2002/02/11 13:25:30 raorn Exp $
*******************************************************/
#include "crashecho.h"
#ifdef MSGBASE_JAM
#define MIN(a,b) ((a)<(b)? (a):(b))
struct openbase {
ulong lastuse;
s_JamBase *Base_PS;
struct jam_Area *area;
};
struct jam_Area {
struct jam_Area *Next;
struct Area *area;
s_JamBase *Base_PS;
ulong BaseNum;
ulong OldNum;
ulong OldHighWater;
ulong HighWater;
bool newmsg;
};
struct jbList jam_AreaList;
struct openbase *jam_openbases;
ulong jam_lastnum;
long jam_utcoffset;
s_JamBase *jam_openbase(struct jam_Area *area)
{
int c;
struct openbase *thisbase;
mode_t oldumask;
/* See if that area is already open */
for (c = 0; c < config.cfg_jam_MaxOpen; c++)
if (jam_openbases[c].area == area && jam_openbases[c].lastuse) {
jam_openbases[c].lastuse = jam_lastnum++;
return (jam_openbases[c].Base_PS);
}
/* We must open it now */
/* Try to get an empty slot */
thisbase = NULL;
for (c = 0; c < config.cfg_jam_MaxOpen && !thisbase; c++)
if (jam_openbases[c].lastuse == 0)
thisbase = &jam_openbases[c];
/* Otherwise, remove a slot that hasn't been used for a long time */
if (!thisbase) {
thisbase = &jam_openbases[0];
for (c = 0; c < config.cfg_jam_MaxOpen; c++)
if (jam_openbases[c].lastuse < thisbase->lastuse)
thisbase = &jam_openbases[c];
thisbase->lastuse = 0;
JAM_CloseMB(thisbase->Base_PS);
}
/* Open area */
if (JAM_OpenMB(area->area->Path, &thisbase->Base_PS)) {
LogWrite(2, SYSTEMINFO, "Creating JAM messagebase \"%s\"", area->area->Path);
oldumask = umask(config.cfg_MsgbaseUmask);
if (JAM_CreateMB(area->area->Path, 1, &thisbase->Base_PS)) {
umask(oldumask);
LogWrite(1, SYSTEMERR, "Failed to create JAM messagebase \"%s\"", area->area->Path);
return (NULL);
}
umask(oldumask);
}
/* Set the rest */
thisbase->lastuse = jam_lastnum++;
thisbase->area = area;
return (thisbase->Base_PS);
}
struct jam_Area *jam_getarea(struct Area *area)
{
struct jam_Area *ja;
ulong num;
s_JamBaseHeader Header_S;
/* Check if area already exists */
for (ja = (struct jam_Area *) jam_AreaList.First; ja; ja = ja->Next)
if (ja->area == area) {
if (!(ja->Base_PS = jam_openbase(ja)))
return (NULL);
return (ja);
}
/* This is the first time we use this area */
if (!(ja = calloc(1, sizeof(struct jam_Area)))) {
nomem = TRUE;
return (FALSE);
}
jbAddNode(&jam_AreaList, (struct jbNode *) ja);
ja->area = area;
if (!(ja->Base_PS = jam_openbase(ja)))
return (NULL);
if (JAM_GetMBSize(ja->Base_PS, &num)) {
LogWrite(1, TOSSINGERR, "Failed to get size of JAM area \"%s\"", area->Path);
return (NULL);
}
ja->OldNum = num;
if (JAM_ReadMBHeader(ja->Base_PS, &Header_S)) {
LogWrite(1, TOSSINGERR, "Failed to read header of JAM area \"%s\"", area->Path);
return (NULL);
}
ja->BaseNum = Header_S.BaseMsgNum;
ja->OldHighWater = 0;
ja->HighWater = 0;
return (ja);
}
void jam_gethighwater(struct jam_Area *ja)
{
uchar buf[200];
FILE *fh;
ulong num;
snprintf(buf, 200, "%s.cmhw", ja->area->Path);
if ((fh = fopen(buf, "rb"))) {
if (fread(&num, sizeof(ulong), 1, fh)) {
ja->HighWater = num;
ja->OldHighWater = num;
}
fclose(fh);
}
}
void jam_writehighwater(struct jam_Area *ja)
{
uchar buf[200];
FILE *fh;
ulong num;
mode_t oldumask;
snprintf(buf, 200, "%s.cmhw", ja->area->Path);
num = ja->HighWater;
oldumask = umask(config.cfg_MsgbaseUmask);
if ((fh = fopen(buf, "wb"))) {
fwrite(&num, sizeof(ulong), 1, fh);
fclose(fh);
}
umask(oldumask);
}
bool jam_beforefunc(void)
{
time_t t1, t2;
struct tm *tp;
jbNewList(&jam_AreaList);
if (config.cfg_jam_MaxOpen == 0)
config.cfg_jam_MaxOpen = 5;
if (!(jam_openbases=calloc(1, config.cfg_jam_MaxOpen * sizeof(struct openbase)))) {
nomem = TRUE;
return (FALSE);
}
/* Some timezone tricks */
t1 = time(NULL);
tp = gmtime(&t1);
tp->tm_isdst = -1;
t2 = mktime(tp);
jam_utcoffset = t2 - t1;
jam_lastnum = 1;
return (TRUE);
}
bool jam_afterfunc(bool success)
{
int c;
struct jam_Area *ja;
if (success && (config.cfg_jam_Flags & CFG_JAM_HIGHWATER))
for (ja = (struct jam_Area *) jam_AreaList.First; ja; ja = ja->Next)
if (ja->HighWater != ja->OldHighWater)
jam_writehighwater(ja);
for (c = 0; c < config.cfg_jam_MaxOpen; c++)
if (jam_openbases[c].lastuse)
JAM_CloseMB(jam_openbases[c].Base_PS);
free(jam_openbases);
if (success && config.cfg_jam_FlagsDir[0]) {
FILE *fh;
uchar buf[100];
MakeFullPath(config.cfg_jam_FlagsDir, "import.jam", buf, 100);
if((fh=fopen(buf, "ab")) == NULL){
fprintf(stderr, "Failed to open %s\n", buf);
fprintf(stderr, "Error: %s\n", strerror(errno));
return (FALSE);
}
for (ja = (struct jam_Area *) jam_AreaList.First; ja; ja = ja->Next)
if (ja->newmsg)
fprintf(fh, "%s\n", ja->area->Tagname);
fclose(fh);
}
jbFreeList(&jam_AreaList);
return (TRUE);
}
bool jam_nomem;
void jam_addfield(s_JamSubPacket * SubPacket_PS, ulong fieldnum,
uchar * fielddata)
{
s_JamSubfield Subfield_S;
Subfield_S.LoID = fieldnum;
Subfield_S.HiID = 0;
Subfield_S.DatLen = strlen(fielddata);
Subfield_S.Buffer = fielddata;
if (JAM_PutSubfield(SubPacket_PS, &Subfield_S) == JAM_NO_MEMORY)
jam_nomem = TRUE;
}
struct flag {
uchar *name;
ulong jamflagbit;
ulong fidoflagbit;
};
struct flag jam_flagarray[] = {
{"PVT", MSG_PRIVATE, FLAG_PVT},
{"HLD", MSG_HOLD, FLAG_HOLD},
{"CRA", MSG_CRASH, FLAG_CRASH},
{"K/S", MSG_KILLSENT, FLAG_KILLSENT},
{"SNT", MSG_SENT, FLAG_SENT},
{"RCV", MSG_READ, FLAG_RECD},
{"A/S", MSG_ARCHIVESENT, 0,},
{"DIR", MSG_DIRECT, 0},
/*{"ZON", MSG_GATE, 0},*/
/*{"HUB", 0, 0},*/
{"FIL", MSG_FILEATTACH, FLAG_FILEATTACH},
{"FRQ", MSG_FILEREQUEST, FLAG_FILEREQ},
{"IMM", MSG_IMMEDIATE, 0},
/*{"XMA", 0, 0},*/
{"KFS", MSG_KILLFILE, 0},
{"TFS", MSG_TRUNCFILE, 0},
{"LOK", MSG_LOCKED, 0},
{"RRQ", MSG_RECEIPTREQ, FLAG_RREQ},
{"CFM", MSG_CONFIRMREQ, 0},
/*{"HIR", 0, 0},*/
/*{"COV", 0, 0},*/
/*{"SIG", 0, 0},*/
/*{"LET", 0, 0},*/
/*{"FAX", 0, 0},*/
{"FPU", MSG_FPU, 0},
{"", MSG_LOCAL, FLAG_LOCAL},
{"", MSG_INTRANSIT, FLAG_INTRANSIT},
{"", MSG_ORPHAN, FLAG_ORPHAN},
{NULL, 0, 0}
};
ulong mmAttr2JAM(ulong mm_attr)
{
int c;
ulong jam_attr = 0;
for (c = 0; jam_flagarray[c].name; c++)
if (mm_attr & jam_flagarray[c].fidoflagbit)
jam_attr |= jam_flagarray[c].jamflagbit;
return jam_attr;
}
/*ulong JAM2mmAttr(ulong jam_attr)*/
/*{*/
/*}*/
ulong jam_findflag(uchar * name)
{
int c;
for (c = 0; jam_flagarray[c].name; c++)
if (stricmp(jam_flagarray[c].name, name) == 0)
return (jam_flagarray[c].jamflagbit);
return (0);
}
bool jam_importfunc(struct MemMessage * mm, struct Area * area)
{
struct TextChunk *chunk;
struct Path *pathnode;
struct jam_Area *ja;
s_JamSubPacket *SubPacket_PS;
s_JamMsgHeader Header_S;
uchar buf[100], domain[20], newflags[100], flag[10];
ulong c, f, jbcpos, linebegin, linelen;
uchar *msgtext;
ulong msgsize, msgpos;
int res;
bool hasorigin;
struct Node4D n4d;
/* Get an area to write to */
if (!(ja = jam_getarea(area)))
return (FALSE);
/* Start import */
ja->newmsg = TRUE;
JAM_ClearMsgHeader(&Header_S);
if (!(SubPacket_PS = JAM_NewSubPacket())) {
nomem = TRUE;
return (FALSE);
}
/* Allocate memory to store message text in */
msgpos = 0;
msgsize = 0;
msgtext = NULL;
for (chunk = (struct TextChunk *) mm->TextChunks.First; chunk; chunk = chunk->Next)
if (chunk->Data)
msgsize += strlen(chunk->Data);
if (msgsize != 0) {
if (!(msgtext = malloc(msgsize))) {
LogWrite(1, SYSTEMERR, "Out of memory");
JAM_DelSubPacket(SubPacket_PS);
return (FALSE);
}
}
/* Do header */
Header_S.DateProcessed = time(NULL);
Header_S.DateWritten = FidoToTime(mm->DateTime);
/* Damned time zones... dates should be in local time in JAM */
Header_S.DateProcessed -= jam_utcoffset;
Header_S.DateWritten -= jam_utcoffset;
Header_S.Cost = mm->Cost;
Header_S.MsgIdCRC = JAM_Crc32(mm->MSGID, strlen(mm->MSGID));
Header_S.ReplyCRC = JAM_Crc32(mm->REPLY, strlen(mm->REPLY));
/* Add header fields */
if (mm->From[0])
jam_addfield(SubPacket_PS, JAMSFLD_SENDERNAME, mm->From);
if (mm->To[0])
jam_addfield(SubPacket_PS, JAMSFLD_RECVRNAME, mm->To);
if (mm->Subject[0])
jam_addfield(SubPacket_PS, JAMSFLD_SUBJECT, mm->Subject);
/* Addresses in netmail */
if (mm->Area[0] == 0) {
Print4D(&mm->OrigNode, buf, 100);
jam_addfield(SubPacket_PS, JAMSFLD_OADDRESS, buf);
Print4D(&mm->DestNode, buf, 100);
jam_addfield(SubPacket_PS, JAMSFLD_DADDRESS, buf);
}
/* Header attributes */
Header_S.Attribute = mmAttr2JAM(mm->Attr);
if (mm->Attr & FLAG_FILEATTACH) {
Header_S.Attribute |= MSG_FILEATTACH;
c = 0;
while (mm->Subject[c] != 0) {
f = 0;
while (mm->Subject[c] != 0 && mm->Subject[c] != 32 && mm->Subject[c] != ',' && f < 80)
buf[f++] = mm->Subject[c++];
buf[f] = 0;
while (mm->Subject[c] == 32 || mm->Subject[c] == ',')
c++;
if (buf[0] != 0)
jam_addfield(SubPacket_PS, JAMSFLD_ENCLFILE, buf);
}
}
if (mm->Attr & FLAG_FILEREQ) {
Header_S.Attribute |= MSG_FILEREQUEST;
c = 0;
while (mm->Subject[c] != 0) {
f = 0;
while (mm->Subject[c] != 0 && mm->Subject[c] != 32 && mm->Subject[c] != ',' && f < 80)
buf[f++] = mm->Subject[c++];
buf[f] = 0;
while (mm->Subject[c] == 32 || mm->Subject[c] == ',')
c++;
if (buf[0] != 0)
jam_addfield(SubPacket_PS, JAMSFLD_ENCLFREQ, buf);
}
}
/* Echomail/netmail attribute */
if (mm->Area[0] == 0)
Header_S.Attribute |= MSG_TYPENET;
else
Header_S.Attribute |= MSG_TYPEECHO;
/* Separate kludges from text */
hasorigin = FALSE;
if (msgsize != 0)
for (chunk = (struct TextChunk *) mm->TextChunks.First; chunk; chunk = chunk->Next)
if (chunk->Data)
for (c = 0; chunk->Data[c];) {
linebegin = msgpos;
while (chunk->Data[c] != 13 && chunk->Data[c]) {
if (chunk->Data[c] != 10)
msgtext[msgpos++] = chunk->Data[c];
c++;
}
if (chunk->Data[c] == 13 && chunk->Data[c])
msgtext[msgpos++] = chunk->Data[c++];
linelen = msgpos - linebegin;
if (linelen != 0) {
if (linelen >= 5 && strncmp(&msgtext[linebegin], "\001PID:", 5) == 0) {
mystrncpy(buf, &msgtext[linebegin + 5], MIN(100, linelen - 5));
stripleadtrail(buf);
jam_addfield(SubPacket_PS, JAMSFLD_PID, buf);
msgpos = linebegin;
} else if (linelen >= 7 && strncmp(&msgtext[linebegin], "\001MSGID:", 7) == 0) {
mystrncpy(buf, &msgtext[linebegin + 7], MIN(100, linelen - 7));
stripleadtrail(buf);
jam_addfield(SubPacket_PS, JAMSFLD_MSGID, buf);
msgpos = linebegin;
} else if (linelen >= 7 && strncmp(&msgtext[linebegin], "\001REPLY:", 7) == 0) {
mystrncpy(buf, &msgtext[linebegin + 7], MIN(100, linelen - 7));
stripleadtrail(buf);
jam_addfield(SubPacket_PS, JAMSFLD_REPLYID, buf);
msgpos = linebegin;
} else if (linelen > 5 && strncmp(&msgtext[linebegin], "\001Via ", 5) == 0) {
mystrncpy(buf, &msgtext[linebegin + 5], MIN(100, linelen - 5));
stripleadtrail(buf);
jam_addfield(SubPacket_PS, JAMSFLD_TRACE, buf);
msgpos = linebegin;
} else if (linelen >= 7 && strncmp(&msgtext[linebegin], "\001FLAGS:", 7) == 0) {
mystrncpy(buf, &msgtext[linebegin + 7], MIN(100, linelen - 7));
stripleadtrail(buf);
jbcpos = 0;
newflags[0] = 0;
while (jbstrcpy(flag, buf, 10, &jbcpos)) {
ulong flagbit;
if ((flagbit = jam_findflag(flag))) {
Header_S.Attribute |= flagbit;
} else {
strcat(newflags, flag);
strcat(newflags, " ");
}
}
stripleadtrail(newflags);
if (newflags[0] != 0)
jam_addfield(SubPacket_PS, JAMSFLD_FLAGS, newflags);
msgpos = linebegin;
} else if (linelen >= 5 && strncmp(&msgtext[linebegin], "\001INTL", 5) == 0) {
/* Remove this kludge */
msgpos = linebegin;
} else if (linelen >= 5 && strncmp(&msgtext[linebegin], "\001TOPT", 5) == 0) {
/* Remove this kludge */
msgpos = linebegin;
} else if (linelen >= 5 && strncmp(&msgtext[linebegin], "\001FMPT", 5) == 0) {
/* Remove this kludge */
msgpos = linebegin;
} else if (msgtext[linebegin] == 1) {
mystrncpy(buf, &msgtext[linebegin + 1], MIN(100, linelen - 1));
stripleadtrail(buf);
jam_addfield(SubPacket_PS, JAMSFLD_FTSKLUDGE, buf);
msgpos = linebegin;
} else {
if (!hasorigin && linelen > 11 && strncmp(&msgtext[linebegin], " * Origin: ", 11) == 0) {
mystrncpy(buf, &msgtext[linebegin + 11], MIN(100, linelen - 11));
stripleadtrail(buf);
if (ExtractAddress(buf, &n4d, domain)) {
hasorigin = TRUE;
if (n4d.Zone == 0)
n4d.Zone = mm->PktOrig.Zone;
Print4D(&n4d, buf, 100);
jam_addfield(SubPacket_PS, JAMSFLD_OADDRESS, buf);
}
}
}
}
}
/* Seen-by */
if ((area->Flags & AREA_IMPORTSEENBY) && mm->Area[0]) {
uchar *buf;
ulong c, d;
if ((buf = mmMakeSeenByBuf(&mm->SeenBy))) {
c = 0;
while (buf[c] != 0) {
d = c;
while (buf[d] != 0 && buf[d] != 13)
d++;
if (buf[d] == 13) {
buf[d++] = 0;
jam_addfield(SubPacket_PS, JAMSFLD_SEENBY2D, &buf[c + 9]);
}
c = d;
}
}
free(buf);
}
/* Path */
for (pathnode = (struct Path *) mm->Path.First; pathnode; pathnode = pathnode->Next)
for (c = 0; c < pathnode->Paths; c++)
jam_addfield(SubPacket_PS, JAMSFLD_PATH2D, pathnode->Path[c]);
if (jam_nomem) {
LogWrite(1, SYSTEMERR, "Out of memory");
JAM_DelSubPacket(SubPacket_PS);
if (msgsize)
free(msgtext);
return (FALSE);
}
/* Write message */
if (JAM_LockMB(ja->Base_PS, 10)) {
LogWrite(1, SYSTEMERR, "Timeout when trying to lock JAM messagebase \"%s\"", area->Path);
JAM_DelSubPacket(SubPacket_PS);
if (msgsize)
free(msgtext);
return (FALSE);
}
res = JAM_AddMessage(ja->Base_PS, &Header_S, SubPacket_PS, msgpos == 0 ? NULL : msgtext, msgpos);
JAM_UnlockMB(ja->Base_PS);
JAM_DelSubPacket(SubPacket_PS);
if (msgsize)
free(msgtext);
if (res) {
LogWrite(1, SYSTEMERR, "Failed to write message to JAM messagebase \"%s\"", area->Path);
return (FALSE);
}
return (TRUE);
}
void jam_makekludge(struct MemMessage *mm, uchar * pre, uchar * data, ulong len)
{
uchar *buf;
if (!(buf = malloc(strlen(pre) + len + 10))) /* A few bytes extra */
return;
strcpy(buf, pre);
if (len && data)
mystrncpy(&buf[strlen(buf)], data, len + 1);
strcat(buf, "\015");
mmAddLine(mm, buf, MM_ADD);
free(buf);
}
/*struct ViaLine {*/
/* struct ViaLine *Next;*/
/* uchar *buf;*/
/*};*/
bool jam_ExportJAMNum(struct Area *area, ulong num, bool(*acceptfunc) (struct MemMessage *mm), bool(*handlefunc) (struct MemMessage * mm))
{
struct MemMessage *mm;
struct jam_Area *ja;
uchar *msgtext;
/* struct jbList ViaList;*/
/* struct ViaLine *tmpvia;*/
uchar buf[200], domain[20];
int res, c;
s_JamSubPacket *SubPacket_PS;
s_JamMsgHeader Header_S;
s_JamSubfield *Field_PS;
struct Node4D n4d;
bool hasaddr;
uchar flagsbuf[200], filesubject[200];
/* ushort oldattr;*/
bool gotarea = FALSE, gotfrom = FALSE;
LogWrite(6, SYSTEMINFO, "In jam_ExportJAMNum(\"%s\", %d, ...)", area->Tagname, num);
/* Open the area */
if (!(ja = jam_getarea(area)))
return (FALSE);
memset(&Header_S, 0, sizeof(s_JamMsgHeader));
res = JAM_ReadMsgHeader(ja->Base_PS, num - ja->BaseNum, &Header_S, &SubPacket_PS);
if (res) {
if (res == JAM_NO_MESSAGE) {
/* Message no longer exists */
LogWrite(6, SYSTEMINFO, "In jam_ExportJAMNum(): No message");
return (TRUE);
} else {
LogWrite(1, TOSSINGERR, "Failed to read message #%lu in JAM messagebase \"%s\"", num, area->Path);
return (TRUE);
}
}
/* Check if deleted or locked */
if (Header_S.Attribute & MSG_DELETED || Header_S.Attribute & MSG_LOCKED) {
/* Message deleted or locked */
LogWrite(6, SYSTEMINFO, "In jam_ExportJAMNum(): Deleted or locked");
JAM_DelSubPacket(SubPacket_PS);
return (TRUE);
}
/* Allocate message structure */
if (!(mm = mmAlloc())) {
JAM_DelSubPacket(SubPacket_PS);
return (FALSE);
}
if (area->AreaType == AREATYPE_NETMAIL)
mm->Area[0]=0;
else
strcpy(mm->Area, area->Tagname);
mm->msgnum = num;
/* Subfields */
flagsbuf[0] = 0;
filesubject[0] = 0;
hasaddr = FALSE;
/* jbNewList(ViaList);*/
for (Field_PS = JAM_GetSubfield(SubPacket_PS); Field_PS; Field_PS = JAM_GetSubfield(NULL)) {
switch (Field_PS->LoID) {
case JAMSFLD_OADDRESS:
mystrncpy(buf, Field_PS->Buffer, Field_PS->DatLen + 1);
if (Parse5D(buf, &n4d, domain)) {
mm->OrigNode.Zone = n4d.Zone;
mm->OrigNode.Net = n4d.Net;
mm->OrigNode.Node = n4d.Node;
mm->OrigNode.Point = n4d.Point;
}
break;
case JAMSFLD_DADDRESS:
mystrncpy(buf, Field_PS->Buffer, Field_PS->DatLen + 1);
if (hasaddr) {
LogWrite(1, TOSSINGERR, "Warning: Multiple DADDRESS not supported by CrashEcho");
} else {
hasaddr = TRUE;
if (Parse5D(buf, &n4d, domain)) {
mm->DestNode.Zone = n4d.Zone;
mm->DestNode.Net = n4d.Net;
mm->DestNode.Node = n4d.Node;
mm->DestNode.Point = n4d.Point;
}
}
break;
case JAMSFLD_SENDERNAME:
mystrncpy(buf, Field_PS->Buffer, Field_PS->DatLen + 1);
mystrncpy(mm->From, buf, 36);
break;
case JAMSFLD_RECVRNAME:
mystrncpy(buf, Field_PS->Buffer, Field_PS->DatLen + 1);
mystrncpy(mm->To, buf, 36);
break;
case JAMSFLD_MSGID:
jam_makekludge(mm, "\001MSGID: ", Field_PS->Buffer, Field_PS->DatLen);
break;
case JAMSFLD_REPLYID:
jam_makekludge(mm, "\001REPLY: ", Field_PS->Buffer, Field_PS->DatLen);
break;
case JAMSFLD_SUBJECT:
mystrncpy(buf, Field_PS->Buffer, Field_PS->DatLen + 1);
mystrncpy(mm->Subject, buf, 72);
break;
case JAMSFLD_PID:
jam_makekludge(mm, "\001PID: ", Field_PS->Buffer, Field_PS->DatLen);
break;
case JAMSFLD_TRACE:
/* FIXME Add ^aVia's at the end of message */
jam_makekludge(mm, "\001Via ", Field_PS->Buffer, Field_PS->DatLen);
/* FIXME acceptfunc will be called before @Via appended */
/* if ((tmpvia=calloc(1, sizeof(struct ViaList))) != NULL) {*/
/* uchar *tmpbuf;*/
/* Alloc Datlen + 5 (@Via) + 1 (CR) + 1 (NUL) bytes */
/* if ((tmpbuf=calloc(1, Field_PS->DatLen+5+1+1))) {*/
/* strcpy(tmpbuf, "\001Via ");*/
/* memcpy(tmpbuf+5, Field_PS->Buffer, Field_PS->DatLen);*/
/* tmpbuf already zeroed after calloc */
/* strcat(tmpbuf, "\015");*/
/* tmpvia->buf = tmpbuf;*/
/* jbAddNode(ViaList, tmpvia);*/
/* }*/
/* }*/
break;
case JAMSFLD_ENCLFILE:
if (filesubject[0])
LogWrite(1, TOSSINGERR, "Warning: Multiple ENCLOSEDFILE not supported by CrashEcho");
else
mystrncpy(filesubject, Field_PS->Buffer, Field_PS->DatLen + 1);
break;
case JAMSFLD_ENCLFREQ:
LogWrite(1, TOSSINGERR, "Warning: ENCLOSEDFREQ not supported by CrashEcho");
break;
case JAMSFLD_ENCLFWALIAS:
LogWrite(1, TOSSINGERR, "Warning: ENCLOSEDFILEWALIAS not supported by CrashEcho");
break;
case JAMSFLD_ENCLFILEWC:
LogWrite(1, TOSSINGERR, "Warning: ENCLOSEDFILEWCARD with wildcards not supported by CrashEcho");
break;
case JAMSFLD_ENCLINDFILE:
LogWrite(1, TOSSINGERR, "Warning: ENCLOSEDINDIRECTFILE not supported by CrashEcho");
break;
case JAMSFLD_FTSKLUDGE:
/* if (nowdoing == DOING_TOSSBAD) {*/ /* } (to make vim hapy :-) */
if (area->AreaType == AREATYPE_BAD) {
ulong len;
len = Field_PS->DatLen;
if (!gotfrom && len > 5 && !strncmp(Field_PS->Buffer, "FROM:", 5)) {
struct Node4D node;
uchar buf2[100];
mystrncpy(buf2, &Field_PS->Buffer[5], (len - 5 > 99 ? 99 : len - 5) + 1);
stripleadtrail(buf2);
if (Parse4D(buf2, &node))
Copy4D(&mm->PktOrig, &node);
/* Skip this kludge */
gotfrom = TRUE;
break;
} else if (!gotarea && len > 5 && !strncmp(Field_PS->Buffer, "AREA:", 5)) {
mystrncpy(mm->Area, &Field_PS->Buffer[5], (len - 5 > 79 ? 79 : len - 5) + 1);
/* Strip spaces from area name... */
stripleadtrail(mm->Area);
gotarea = TRUE;
/* ... and skip this kludge */
break;
} else if (len >= 7 && !strncmp(Field_PS->Buffer, "REASON:", 7))
/* Just skip this kludge */
break;
}
jam_makekludge(mm, "\001", Field_PS->Buffer, Field_PS->DatLen);
break;
case JAMSFLD_SEENBY2D:
jam_makekludge(mm, "SEEN-BY: ", Field_PS->Buffer, Field_PS->DatLen);
break;
case JAMSFLD_PATH2D:
jam_makekludge(mm, "\001PATH: ", Field_PS->Buffer, Field_PS->DatLen);
break;
case JAMSFLD_FLAGS:
strcpy(flagsbuf, "\001FLAGS: ");
mystrncpy(&flagsbuf[8], Field_PS->Buffer, Field_PS->DatLen + 1);
/* Don't add until attributes from header has been added */
break;
}
}
if (filesubject[0]) {
mm->Attr |= FLAG_FILEATTACH;
mystrncpy(mm->Subject, filesubject, 72);
}
/* Message header */
MakeFidoDate(Header_S.DateWritten + jam_utcoffset, mm->DateTime);
mm->Cost = Header_S.Cost;
for (c = 0; jam_flagarray[c].name; c++)
if (Header_S.Attribute & jam_flagarray[c].jamflagbit) {
if (jam_flagarray[c].fidoflagbit) {
mm->Attr |= jam_flagarray[c].fidoflagbit;
} else if (jam_flagarray[c].name[0] && strlen(flagsbuf) < 90) {
if (flagsbuf[0] == 0)
strcpy(flagsbuf, "\001FLAGS: ");
else
strcat(flagsbuf, " ");
strcat(flagsbuf, jam_flagarray[c].name);
}
}
if (flagsbuf[0]) {
strcat(flagsbuf, "\015");
mmAddLine(mm, buf, MM_KLUDGE);
}
/* oldattr = mm->Attr;*/
/* Add own kludges */
if (area->AreaType == AREATYPE_NETMAIL) {
if (mm->OrigNode.Zone != mm->DestNode.Zone || (config.cfg_Flags & CFG_FORCEINTL)) {
snprintf(buf, 200, "\001INTL %u:%u/%u %u:%u/%u\015", mm->DestNode.Zone,
mm->DestNode.Net, mm->DestNode.Node, mm->OrigNode.Zone,
mm->OrigNode.Net, mm->OrigNode.Node);
mmAddLine(mm, buf, MM_HEAD);
}
if (mm->OrigNode.Point) {
snprintf(buf, 200, "\001FMPT %u\015", mm->OrigNode.Point);
mmAddLine(mm, buf, MM_HEAD);
}
if (mm->DestNode.Point) {
snprintf(buf, 200, "\001TOPT %u\015", mm->DestNode.Point);
mmAddLine(mm, buf, MM_HEAD);
}
}
JAM_DelSubPacket(SubPacket_PS);
if ((*acceptfunc) (mm)) {
LogWrite(6, SYSTEMINFO, "In jam_ExportJAMNum(): Message accepted");
/* Read message text */
msgtext = NULL;
if (Header_S.TxtLen) {
if (!(msgtext = malloc(Header_S.TxtLen))) {
nomem = TRUE;
mmFree(mm);
return (FALSE);
}
res = JAM_ReadMsgText(ja->Base_PS, Header_S.TxtOffset, Header_S.TxtLen, msgtext);
if (res) {
LogWrite(1, TOSSINGERR, "Failed to read message #%lu in JAM messagebase \"%s\"", num, area->Path);
free(msgtext);
mmFree(mm);
return (FALSE);
}
}
if (msgtext) {
mmAddBuf(&mm->TextChunks, msgtext, Header_S.TxtLen, MM_ADD);
free(msgtext);
}
if (!(*handlefunc) (mm)) {
mmFree(mm);
return (FALSE);
}
if (mm->Changed) {
LogWrite(6, SYSTEMINFO, "In jam_ExportJAMNum(): Updating %d", num);
/* Update attributes */
Header_S.Attribute = mmAttr2JAM(mm->Attr);
if (mm->Deleted)
Header_S.Attribute |= MSG_DELETED;
if (mm->Deleted && (config.cfg_jam_Flags & CFG_JAM_HARDDELETE)) {
if (JAM_LockMB(ja->Base_PS, 10)) {
LogWrite(1, SYSTEMERR, "Timeout when trying to lock JAM messagebase \"%s\"", area->Path);
mmFree(mm);
return (FALSE);
}
JAM_DeleteMessage(ja->Base_PS, num - ja->BaseNum);
JAM_UnlockMB(ja->Base_PS);
} else {
Header_S.DateProcessed = time(NULL);
Header_S.DateProcessed -= jam_utcoffset;
if (JAM_LockMB(ja->Base_PS, 10)) {
LogWrite(1, SYSTEMERR, "Timeout when trying to lock JAM messagebase \"%s\"", area->Path);
mmFree(mm);
return (FALSE);
}
JAM_ChangeMsgHeader(ja->Base_PS, num - ja->BaseNum, &Header_S);
JAM_UnlockMB(ja->Base_PS);
}
}
}
mmFree(mm);
return (TRUE);
}
/*bool jam_exportfunc(struct Area * area, bool(*handlefunc) (struct MemMessage * mm))*/
bool jam_scanfunc (struct Area * area, bool usehw, bool ignorehw, ulong max, struct jbList *msglist, bool(*acceptfunc) (struct MemMessage * mm), bool(*handlefunc) (struct MemMessage * mm))
{
ulong start, end;
struct jam_Area *ja;
/* Open the area */
if (!(ja = jam_getarea(area))) {
if (nomem)
return (FALSE);
/* Area did not exist and could not be created. Go on anyway. */
return (TRUE);
}
if (usehw && config.cfg_jam_Flags & CFG_JAM_HIGHWATER)
jam_gethighwater(ja);
/* ignorehw doesn't make any sense in JAM base */
if (ja->HighWater)
start = ja->HighWater + 1;
else
start = ja->BaseNum;
if (start < ja->BaseNum)
start = ja->BaseNum;
if (max != 0 && ja->OldNum > max)
start = ja->BaseNum + ja->OldNum - max;
end = ja->BaseNum + ja->OldNum;
if (msglist) {
struct MsgEntry *tmpmsg;
for (tmpmsg = (struct MsgEntry *) msglist->First; tmpmsg; tmpmsg = tmpmsg->Next) {
if (tmpmsg->num < ja->BaseNum)
/* Skip it... */
continue;
if (!jam_ExportJAMNum(area, tmpmsg->num, acceptfunc, handlefunc))
return (FALSE);
if (ctrlc)
return (FALSE);
}
} else {
while (start < end) {
if (!jam_ExportJAMNum(area, start, acceptfunc, handlefunc))
return (FALSE);
if (ctrlc)
return (FALSE);
start++;
}
}
if (usehw)
ja->HighWater = end - 1;
return (TRUE);
}
/*{*/
/* ulong start;*/
/* struct jam_Area *ja;*/
/* Open the area */
/* if (!(ja = jam_getarea(area)))*/
/* return (FALSE);*/
/* start = ja->BaseNum;*/
/* if (max != 0 && ja->OldNum > max)*/
/* start = ja->BaseNum + ja->OldNum - max;*/
/* while (start < ja->BaseNum + ja->OldNum) {*/
/* if (!jam_ExportJAMNum(area, start, handlefunc))*/
/* return (FALSE);*/
/* if (ctrlc)*/
/* return (FALSE);*/
/* start++;*/
/* }*/
/* return (TRUE);*/
/*}*/
#endif
syntax highlighted by Code2HTML, v. 0.9.1