/********************************************************
* File: memmessage.c
* Created at Sun Jan 28 22:10:31 MSK 2001 by raorn // raorn@binec.ru
* Memorized message handling
* $Id: memmessage.c,v 1.8 2001/12/24 01:02:55 raorn Exp $
*******************************************************/
#include "crashecho.h"
bool mmAddNodes2DList(struct jbList *list, ushort net, ushort node)
{
/* Add a node to SEEN-BY list */
struct Nodes2D *tmplist;
ushort num;
/* Check if it already exists */
for (tmplist = (struct Nodes2D *) list->First; tmplist; tmplist = tmplist->Next) {
for (num = 0; num < tmplist->Nodes; num++)
if (tmplist->Net[num] == net && tmplist->Node[num] == node)
return (TRUE);
}
tmplist = (struct Nodes2D *) list->Last;
if (tmplist && tmplist->Nodes == PKT_NUM2D)
tmplist = NULL;
if (!tmplist) {
if (!(tmplist = (struct Nodes2D *) malloc(sizeof(struct Nodes2D)))) {
nomem = TRUE;
return (FALSE);
}
jbAddNode(list, (struct jbNode *) tmplist);
tmplist->Nodes = 0;
tmplist->Next = NULL;
}
tmplist->Net[tmplist->Nodes] = net;
tmplist->Node[tmplist->Nodes] = node;
tmplist->Nodes++;
return (TRUE);
}
void mmRemNodes2DList(struct jbList *list, ushort net, ushort node)
{
/* Rem a node from SEEN-BY list */
struct Nodes2D *tmplist;
ushort num;
for (tmplist = (struct Nodes2D *) list->First; tmplist; tmplist = tmplist->Next)
for (num = 0; num < tmplist->Nodes; num++)
if (tmplist->Net[num] == net && tmplist->Node[num] == num) {
tmplist->Net[num] = 0;
tmplist->Node[num] = 0;
}
}
void mmRemNodes2DListPat(struct jbList *list, struct Node2DPat *pat)
{
struct Nodes2D *tmplist;
ushort num;
for (tmplist = (struct Nodes2D *) list->First; tmplist; tmplist = tmplist->Next)
for (num = 0; num < tmplist->Nodes; num++) {
if (Compare2DPat(pat, tmplist->Net[num], tmplist->Node[num]) == 0) {
tmplist->Net[num] = 0;
tmplist->Node[num] = 0;
}
}
}
bool mmAddPath(uchar * str, struct jbList *list)
{
/* Add a node string to PATH list */
struct Path *path;
if (str[0] == 0)
return (TRUE);
path = (struct Path *) list->Last;
if (path && path->Paths == PKT_NUMPATH)
path = NULL;
if (!path) {
if (!(path = (struct Path *) malloc(sizeof(struct Path)))) {
nomem = TRUE;
return (FALSE);
}
jbAddNode(list, (struct jbNode *) path);
path->Paths = 0;
path->Next = NULL;
}
mystrncpy(path->Path[path->Paths], str, 100);
striptrail(path->Path[path->Paths]);
path->Paths++;
return (TRUE);
}
bool mmAddBuf(struct jbList * chunklist, uchar * buf, ulong len, ulong where)
{
struct TextChunk *chunk, *lastchunk, *tmpchunk;
if (!(chunk = (struct TextChunk *) calloc(1, sizeof(struct TextChunk)))) {
nomem = TRUE;
return (FALSE);
}
if (!(chunk->Data = calloc(1, len + 1))) {
nomem = TRUE;
return (FALSE);
}
memcpy(chunk->Data, buf, (size_t) len);
switch(where) {
case MM_ADD:
jbAddNode(chunklist, (struct jbNode *) chunk);
break;
case MM_HEAD:
chunk->Next = (struct TextChunk *) chunklist->First;
chunklist->First = (struct jbNode *) chunk;
if (!chunk->Next)
chunklist->Last = (struct jbNode *) chunk;
break;
case MM_KLUDGE:
lastchunk = NULL;
/* Find first non-kudge line */
for (tmpchunk = (struct TextChunk *) chunklist->First; tmpchunk; lastchunk = tmpchunk, tmpchunk = tmpchunk->Next)
if (tmpchunk->Data && tmpchunk->Data[0] != '\001')
break;
/* Add chunk after lastchunk */
if (lastchunk) {
chunk->Next = lastchunk->Next;
lastchunk->Next = chunk;
} else {
chunk->Next = (struct TextChunk *) chunklist->First;
chunklist->First = (struct jbNode *) chunk;
}
if (!chunk->Next)
chunklist->Last = (struct jbNode *) chunk;
break;
default:
free(chunk->Data);
free(chunk);
return FALSE;
break;
}
return (TRUE);
}
struct MemMessage *mmAlloc(void)
{
struct MemMessage *mm;
if (!(mm = calloc(1, sizeof(struct MemMessage)))) {
nomem = TRUE;
return NULL;
}
jbNewList(&mm->TextChunks);
jbNewList(&mm->SeenBy);
jbNewList(&mm->Path);
return mm;
}
void mmClear(struct MemMessage *mm)
{
struct TextChunk *chunk;
struct Node4D null4d = { 0, 0, 0, 0 };
Copy4D(&mm->OrigNode, &null4d);
Copy4D(&mm->DestNode, &null4d);
Copy4D(&mm->PktOrig, &null4d);
Copy4D(&mm->PktDest, &null4d);
mm->Area[0] = 0;
mm->To[0] = 0;
mm->From[0] = 0;
mm->Subject[0] = 0;
mm->DateTime[0] = 0;
mm->MSGID[0] = 0;
mm->REPLY[0] = 0;
mm->Attr = 0;
mm->Cost = 0;
mm->Type = 0;
mm->Rescanned = FALSE;
mm->Changed = FALSE;
mm->Deleted = FALSE;
mm->no_security = FALSE;
for (chunk = (struct TextChunk *) mm->TextChunks.First; chunk; chunk = chunk->Next)
if (chunk->Data)
free(chunk->Data);
jbFreeList(&mm->TextChunks);
jbFreeList(&mm->SeenBy);
jbFreeList(&mm->Path);
}
void mmFree(struct MemMessage *mm)
{
struct TextChunk *chunk;
for (chunk = (struct TextChunk *) mm->TextChunks.First; chunk; chunk = chunk->Next)
if (chunk->Data)
free(chunk->Data);
jbFreeList(&mm->TextChunks);
jbFreeList(&mm->SeenBy);
jbFreeList(&mm->Path);
free(mm);
}
struct TempSort {
ushort Net;
ushort Node;
};
int CompareSort(const void *t1, const void *t2)
{
if (((struct TempSort *) t1)->Net > ((struct TempSort *) t2)->Net)
return (1);
if (((struct TempSort *) t1)->Net < ((struct TempSort *) t2)->Net)
return (-1);
if (((struct TempSort *) t1)->Node > ((struct TempSort *) t2)->Node)
return (1);
if (((struct TempSort *) t1)->Node < ((struct TempSort *) t2)->Node)
return (-1);
return (0);
}
bool mmSortNodes2D(struct jbList * list)
{
struct Nodes2D *tmp;
struct TempSort *sorttemp;
ulong nodes = 0;
ulong c, d;
for (tmp = (struct Nodes2D *) list->First; tmp; tmp = tmp->Next)
nodes += tmp->Nodes;
if (nodes == 0)
return (TRUE);
if (!(sorttemp = (struct TempSort *) malloc(sizeof(struct TempSort) * nodes))) {
nomem = TRUE;
return (FALSE);
}
d = 0;
for (tmp = (struct Nodes2D *) list->First; tmp; tmp = tmp->Next)
for (c = 0; c < tmp->Nodes; c++) {
sorttemp[d].Net = tmp->Net[c];
sorttemp[d].Node = tmp->Node[c];
d++;
}
qsort(sorttemp, (size_t) nodes, sizeof(struct TempSort), CompareSort);
tmp = (struct Nodes2D *) list->First;
tmp->Nodes = 0;
for (c = 0; c < nodes; c++) {
if (tmp->Nodes == PKT_NUM2D) {
tmp = tmp->Next;
tmp->Nodes = 0;
}
tmp->Net[tmp->Nodes] = sorttemp[c].Net;
tmp->Node[tmp->Nodes] = sorttemp[c].Node;
tmp->Nodes++;
}
free(sorttemp);
return (TRUE);
}
bool AddSeenby(uchar * str, struct jbList * list)
{
/* Add a node string to SEEN-BY list */
ulong c, d;
uchar buf[60];
ushort lastnet, num;
c = 0;
lastnet = 0;
while (str[c] != 13 && str[c] != 0) {
d = 0;
while (str[c] != 0 && str[c] != 13 && str[c] != 32 && d < 59)
buf[d++] = str[c++];
buf[d] = 0;
while (str[c] == 32)
c++;
if (buf[0]) {
num = 0;
d = 0;
while (buf[d] >= '0' && buf[d] <= '9') {
num *= 10;
num += buf[d] - '0';
d++;
}
if (buf[d] == '/') {
lastnet = num;
num = atoi(&buf[d + 1]);
if (!mmAddNodes2DList(list, lastnet, num))
return (FALSE);
} else if (buf[d] == 0) {
if (!mmAddNodes2DList(list, lastnet, num))
return (FALSE);
}
}
}
return (TRUE);
}
void ProcessKludge(struct MemMessage *mm, uchar * kludge)
{
struct Node4D node;
uchar buf[60];
ulong c, d;
if (strncmp(kludge, "\001RESCANNED", 10) == 0) {
mm->Rescanned = TRUE;
} else if (strncmp(kludge, "\001MSGID:", 7) == 0) {
for (d = 0, c = 8; d < 79 && kludge[c] != 13 && kludge[c] != 0; c++, d++)
mm->MSGID[d] = kludge[c];
mm->MSGID[d] = 0;
} else if (strncmp(kludge, "\001REPLY:", 7) == 0) {
for (d = 0, c = 8; d < 79 && kludge[c] != 13 && kludge[c] != 0; c++, d++)
mm->REPLY[d] = kludge[c];
mm->REPLY[d] = 0;
} else if (mm->Area[0] == 0) {
if (strncmp(kludge, "\001FMPT", 5) == 0)
mm->OrigNode.Point = atoi(&kludge[6]);
else if (strncmp(kludge, "\001TOPT", 5) == 0)
mm->DestNode.Point = atoi(&kludge[6]);
else if (strncmp(kludge, "\001INTL", 5) == 0) {
if (kludge[5] == ':')
c = 7;
else
c = 6;
for (d = 0; d < 59 && kludge[c] != 32 && kludge[c] != 0; c++, d++)
buf[d] = kludge[c];
buf[d] = 0;
if (Parse4D(buf, &node)) {
mm->DestNode.Zone = node.Zone;
mm->DestNode.Net = node.Net;
mm->DestNode.Node = node.Node;
}
if (kludge[c] == 32)
c++;
for (d = 0; d < 59 && kludge[c] != 32 && kludge[c] != 0 && kludge[c] != 13; c++, d++)
buf[d] = kludge[c];
buf[d] = 0;
if (Parse4D(buf, &node)) {
mm->OrigNode.Zone = node.Zone;
mm->OrigNode.Net = node.Net;
mm->OrigNode.Node = node.Node;
}
}
}
}
bool mmAddLine(struct MemMessage *mm, uchar * buf, ulong where)
{
if (mm->Area[0] && strncmp(buf, "SEEN-BY:", 8) == 0) {
return AddSeenby(&buf[9], &mm->SeenBy);
} else if (mm->Area[0] && strncmp(buf, "\001PATH:", 6) == 0) {
return mmAddPath(&buf[7], &mm->Path);
} else if (buf[0] == 1) {
if (strncmp(buf, "\001RESCANNED", 10) == 0) {
mm->Rescanned = TRUE;
return TRUE;
} else
ProcessKludge(mm, buf);
}
return mmAddBuf(&mm->TextChunks, buf, (ulong) strlen(buf), where);
}
uchar *mmMakeSeenByBuf(struct jbList * list)
{
uchar *text;
ulong seenbys, size;
struct Nodes2D *nodes;
ulong c;
ushort lastnet;
uchar buf[100], buf2[50], buf3[20];
/* Count seenbys */
seenbys = 0;
for (nodes = (struct Nodes2D *) list->First; nodes; nodes = nodes->Next)
seenbys += nodes->Nodes;
/*
* We allocate generously. Maximum length per seenby: <space>12345/12345:
* 12 characters 79 characters - "SEEN-BY:" = 71 characters which makes
* 71/12 seenbys/line = 5
*
* Fortunately even with this generous calculation will not result in huge
* memory areas, 500 seenbys (which is a lot) would need 8000 bytes...
*
*/
size = (seenbys / 5 + 1) * 80;
/* Allocate our memory block */
if (!(text = malloc(size)))
return (NULL);
text[0] = 0;
strcpy(buf, "SEEN-BY:");
lastnet = 0;
for (nodes = (struct Nodes2D *) list->First; nodes; nodes = nodes->Next) {
for (c = 0; c < nodes->Nodes; c++) {
if (nodes->Net[c] != 0 || nodes->Node[c] != 0) {
strcpy(buf2, " ");
if (nodes->Net[c] != lastnet) {
snprintf(buf3, 20, "%u/", nodes->Net[c]);
strcat(buf2, buf3);
}
snprintf(buf3, 20, "%u", nodes->Node[c]);
strcat(buf2, buf3);
lastnet = nodes->Net[c];
if (strlen(buf) + strlen(buf2) > 77) {
strcat(text, buf);
strcat(text, "\015");
strcpy(buf, "SEEN-BY:");
snprintf(buf2, 50, " %u/%u", nodes->Net[c], nodes->Node[c]);
lastnet = nodes->Net[c];
strcat(buf, buf2);
} else {
strcat(buf, buf2);
}
}
}
}
if (strlen(buf) > 8) {
strcat(text, buf);
strcat(text, "\015");
}
return (text);
}
syntax highlighted by Code2HTML, v. 0.9.1