/******************************************************** * 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: 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); }