/******************************************************** * 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