// --------------------------------------------------------------------
// M s g . c p p
//
// Fido messages tracker
// Message.
// --------------------------------------------------------------------
// Copyright (c) 1998,99 by Fyodor Ustinov
// FIDONet 2:5020/79
//
// All rights reserved.
// --------------------------------------------------------------------
#ifndef UNIX
#include <io.h>
#endif
#ifndef __GNUC__
#include <direct.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include "constant.hpp"
#include "vars.hpp"
#include "log.hpp"
#include "nodelist.hpp"
#include "utils.hpp"
#include "aka.hpp"
#include "age.hpp"
#include "attach.hpp"
#include "msg.hpp"
#include <smapi/msgapi.h>
#include <smapi/progprot.h>
#include <smapi/prog.h>
#ifdef __WATCOMC__
#include <smapi/months.c>
#endif
// ---------------------------
//char months[][4] = {
// "Jan", "Feb", "Mar", "Apr", "May", "Jun",
// "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
//};
char *FromTime(time_t tmt) {
static char buf[40];
tm *t = localtime(&tmt);
sprintf(buf, "%02u %3.3s %02u %02u:%02u:%02u",
t->tm_mday, months_ab[t->tm_mon], t->tm_year % 100,
t->tm_hour, t->tm_min, t->tm_sec);
buf[19] = '\0';
return buf;
}
time_t ToTime(char *txt) {
struct tm t;
char mon[4];
int i;
// struct tm *t2;
time_t tt;
sscanf(txt, "%02u %3s %02u %02u:%02u:%02u",
&t.tm_mday, mon, &t.tm_year,
&t.tm_hour, &t.tm_min, &t.tm_sec
);
t.tm_isdst = -1;
t.tm_mon = 0;
if (t.tm_year < 70) t.tm_year += 100;
for (i = 0; i < 12; i++) {
if (strcasecmp(months_ab[i],mon) == 0) {
t.tm_mon = i;
break;
}
}
tt = mktime(&t);
return tt;
}
#if 0
static int _mdays [13] =
{
/* Jan */ 0,
/* Feb */ 31,
/* Mar */ 31+28,
/* Apr */ 31+28+31,
/* May */ 31+28+31+30,
/* Jun */ 31+28+31+30+31,
/* Jul */ 31+28+31+30+31+30,
/* Aug */ 31+28+31+30+31+30+31,
/* Sep */ 31+28+31+30+31+30+31+31,
/* Oct */ 31+28+31+30+31+30+31+31+30,
/* Nov */ 31+28+31+30+31+30+31+31+30+31,
/* Dec */ 31+28+31+30+31+30+31+31+30+31+30,
/* Jan */ 31+28+31+30+31+30+31+31+30+31+30+31
};
#define WOFC( a, b ) ( (uint)a | (((uint)b)<<8) )
time_t FMkTime(tm *pTm) {
unsigned int Days;
int Years;
/*Get number of years since 1970*/
Years = pTm->tm_year - 70;
/*Calculate number of days during these years,*/
/*including extra days for leap years */
Days = Years * 365 + ((Years + 1) / 4);
/*Add the number of days during this year*/
Days += _mdays [pTm->tm_mon] + pTm->tm_mday - 1;
if((pTm->tm_year & 3) == 0 && pTm->tm_mon > 1)
Days++;
/*Convert to seconds, and add the number of seconds this day*/
return(((time_t) Days * 86400L) + ((time_t) pTm->tm_hour * 3600L) +
((time_t) pTm->tm_min * 60L) + (time_t) pTm->tm_sec);
}
tm *FLocalTime(time_t *pt){
static struct tm m;
int t = *pt;
int LeapDay;
m.tm_sec = (int) (t % 60); t /= 60;
m.tm_min = (int) (t % 60); t /= 60;
m.tm_hour = (int) (t % 24); t /= 24;
m.tm_wday = (int) ((t + 4) % 7);
m.tm_year = (int) (t / 365 + 1);
do {
m.tm_year--;
m.tm_yday = (int) (t - m.tm_year * 365 - ((m.tm_year + 1) / 4));
} while(m.tm_yday < 0);
m.tm_year += 70;
LeapDay = ((m.tm_year & 3) == 0 && m.tm_yday >= _mdays [2]);
for(m.tm_mon = m.tm_mday = 0; m.tm_mday == 0; m.tm_mon++)
if(m.tm_yday < _mdays [m.tm_mon + 1] + LeapDay)
m.tm_mday = m.tm_yday + 1 - (_mdays [m.tm_mon] + (m.tm_mon != 1 ? LeapDay : 0));
m.tm_mon--;
m.tm_isdst = -1;
return(&m);
}
time_t ToTime(char *txt) {
tm t;
char mon[4];
int i;
time_t tt;
sscanf(txt, "%02u %3s %02u %02u:%02u:%02u",
&t.tm_mday, mon, &t.tm_year,
&t.tm_hour, &t.tm_min, &t.tm_sec
);
t.tm_isdst = 0;
t.tm_mon = 0;
if (t.tm_year < 70) t.tm_year += 100;
for (i = 0; i < 12; i++) {
if (stricmp(months[i],mon) == 0) {
t.tm_mon = i;
break;
}
}
tt = mktime(&t);
// if (daylight == 1) {
// tt -= 60*60;
// }
return tt;
}
time_t FTime(time_t *p) {
time_t a;
time_t time_of_day;
char buffer[ 80 ];
time_of_day = time( NULL );
strftime( buffer, 80, "%d %h %y %H:%M:%S",
localtime( &time_of_day ) );
a = ToTime(buffer);
if (p != NULL) *p = a;
return a;
}
// ---------------------------
#endif
int Kludge::operator == (const Kludge &k) const {
if (_Name == NULL && k._Name != NULL) return FALSE;
if (_Name != NULL && k._Name == NULL) return FALSE;
if (_Name != NULL && k._Name != NULL && stricmp(_Name,k._Name) != 0) return FALSE;
if (_Body == NULL && k._Body != NULL) return FALSE;
if (_Body != NULL && k._Body == NULL) return FALSE;
if (_Body != NULL && k._Body != NULL && stricmp(_Body,k._Body) != 0) return FALSE;
return TRUE;
}
void Kludge::Print(void) {
if (_Name != NULL) Log.Level(LOGD) << "'" << _Name << "'";
if (_Body != NULL) Log.Level(LOGD) << " --- '" << _Body << "'";;
Log.Level(LOGD) << EOL;
}
int Kludge::Save(FILE *fh) {
if (_Name != NULL && strlen(_Name) != 0) {
if (fwrite(_Name,strlen(_Name),1,fh) != 1) {
Log.Level(LOGD) << "Kludge::Save!--1>" << EOL;
return FALSE;
}
}
if (_Body != NULL && strlen(_Body) != 0) {
if (fwrite(" ",1,1,fh) != 1) {
Log.Level(LOGD) << "Kludge::Save!--2>" << EOL;
return FALSE;
}
if (fwrite(_Body,strlen(_Body),1,fh) != 1) {
Log.Level(LOGD) << "Kludge::Save!--3>" << EOL;
return FALSE;
}
}
if (fwrite("\r",1,1,fh) != 1) {
Log.Level(LOGD) << "Kludge::Save!--4>" << EOL;
return FALSE;
}
return TRUE;
}
Kludge::Kludge(char *N, char *B) {
_Name = NULL;
_Body = NULL;
Set(N,B);
}
Kludge::Kludge(char *Txt) {
char *tmt;
char *p, *p2, *s;
_Name = NULL;
_Body = NULL;
CHP = 310;
if (strlen(Txt) == 0) return;
tmt = strdup(Txt);
p = tmt + strlen(tmt) - 1;
while (p != tmt && *p == ' ') {
*p = '\0';
p--;
}
CHP = 311;
if (strlen(tmt) == 0) {
free(tmt);
return;
}
CHP = 312;
p = tmt;
s = tmt;
while (*s != ' ' && *s != '\0') s++;
if (*s == '\0') {
p2 = NULL;
} else {
*s = '\0';
s++;
while (*s == ' ') s++;
p2 = s;
}
CHP = 313;
if (p2 != NULL && strstr(p2,"* Origin:") == p2) { // Work around for ' * Origin:'
CHP = 314;
Set(" * Origin:", p2+10);
} else {
Set(p,p2);
}
free(tmt);
CHP = 315;
}
void Kludge::Set(char *N, char *B) {
char * MY_N; // _N is defined in NetBSD system headers ...
char * MY_B;
if (N != NULL ) {
MY_N = strdup(N);
} else {
MY_N = NULL;
}
if (B != NULL ) {
MY_B = strdup(B);
} else {
MY_B = NULL;
}
if (_Name != NULL) free(_Name);
if (_Body != NULL) free(_Body);
_Name = MY_N;
_Body = MY_B;
}
Kludge::~Kludge() {
// printf("Kludge destroyed\n");
Clear();
}
void Kludge::Clear(void) {
if (_Name != NULL) {
free(_Name);
_Name = NULL;
}
if (_Body != NULL) {
free(_Body);
_Body = NULL;
}
}
void Kludge::Recode(char *RecodeTable) {
char *tmt;
if (_Body != NULL) {
tmt = _Body;
while (*tmt != '\0') {
*tmt = RecodeTable[(unsigned char)*tmt];
tmt++;
}
}
if (_Name != NULL) {
tmt = _Name;
while (*tmt != '\0') {
*tmt = RecodeTable[(unsigned char)*tmt];
tmt++;
}
}
}
// ---------------------------
cMSG::cMSG() {
_Body = NULL;
Clear();
}
// ---------------------------
cMSG::~cMSG() {
if (_Body != NULL) free (_Body);
_Klu.Clear();
}
// ---------------------------
void cMSG::Clear(void) {
CHP = 315020;
if (_Body != NULL) {
CHP = 315021;
free(_Body);
}
_Body = NULL;
CHP = 315022;
memset(_Subject,0,72);
memset(_FromName,0,36);
memset(_ToName,0,36);
memset(_Reserved,0,8);
memset(_RoutedVia,0,128);
memset(_AreaName,0,128);
CHP = 315023;
_FromAddr.Clean();
CHP = 315024;
_ToAddr.Clean();
CHP = 315025;
fNoZone = 1;
fEmpty = 1;
_Cost = 0;
_TimesRead = 0;
_ReplyTo = 0;
_NextReply = 0;
fChanged = fPrivate = fCrash = fReceived = fSend =
fFileAttach = fTransit = fOrphan = fKillSend = fLocal =
fHold = fFileRequest = fRRQ = fIRR = fARQ = fFURQ = fDIR =
fIMM = fCFM = fTFS = fKFS = fEchomail = fScanned = fLok =
fAS = 0;
CHP = 315026;
_Klu.Clear();
CHP = 315028;
}
// ---------------------------
unsigned long MsgID(void) {
static unsigned int LastMSGID = 0;
return ((time(NULL) << 3) + LastMSGID++);
}
// ---------------------------
void cMSG::Normalise(void) {
char *tmt;
IndBiList<Kludge>::ElemPtr Klu;
Kludge *TKlu;
char Ad1[500],Ad2[50];
FA f;
char Buff[4096];
int fIntlE;
int fMsgidE;
int fFlagsE;
int fFromptE;
int fToptE;
CHP = 31501;
fIntlE = FALSE;
fMsgidE = FALSE;
fFlagsE = FALSE;
fFromptE = FALSE;
fToptE = FALSE;
CHP = 31502;
if ((_FromAddr.Zone() & FA_NOTDEF) && UseOwnZone) {
_FromAddr.Zone(FA_ANYMASK);
_FromAddr.Zone(GetMyAka(_FromAddr).Zone());
}
if ((_ToAddr.Zone() & FA_NOTDEF) && UseOwnZone) {
_ToAddr.Zone(FA_ANYMASK);
_ToAddr.Zone(GetMyAka(_ToAddr).Zone());
}
Klu = _Klu.GetFirst();
CHP = 31503;
while (Klu != NULL) {
CHP = 31504;
if (Klu->Name() != NULL) {
CHP = 31505;
if (stricmp(Klu->Name(),"\1INTL") == 0) {
if ((_FromAddr.Zone() & FA_NOTDEF) || (_ToAddr.Zone() & FA_NOTDEF)) {
Klu->Set(NULL,NULL);
} else {
CHP = 31506;
fIntlE = TRUE;
f = _FromAddr;
f.Point(0);
strcpy(Ad1,(char *)(Str)f);
f = _ToAddr;
f.Point(0);
strcpy(Ad2,(char *)(Str)f);
sprintf(Buff,"%s %s",Ad2,Ad1);
CHP = 31507;
Klu->Set("\1INTL",Buff);
CHP = 31508;
}
} else if (stricmp(Klu->Name(),"\1MSGID:") == 0) {
CHP = 31509;
fMsgidE = TRUE;
if (fChanged) {
if (_FromAddr.Zone() & FA_NOTDEF) {
Klu->Set(NULL,NULL);
} else {
CHP = 31510;
strcpy(Ad1,(char *)(Str)_FromAddr);
sprintf(Buff,"%s %08lx",Ad1,MsgID());
CHP = 31511;
Klu->Set("\1MSGID:",Buff);
CHP = 31512;
}
}
} else if (stricmp(Klu->Name(),"\1FMPT") == 0) {
CHP = 31513;
fFromptE = TRUE;
if (_FromAddr.Point() & 0xffff) {
CHP = 31514;
sprintf(Buff,"%u",(word) (_FromAddr.Point() & 0xffff));
CHP = 31515;
Klu->Set("\1FMPT",Buff);
CHP = 31516;
} else {
CHP = 31517;
Klu->Set(NULL,NULL);
CHP = 31518;
}
} else if (stricmp(Klu->Name(),"\1TOPT") == 0) {
CHP = 31519;
fToptE = TRUE;
if (_ToAddr.Point() & 0xffff) {
CHP = 31520;
sprintf(Buff,"%u",(word) (_ToAddr.Point() & 0xffff));
CHP = 31521;
Klu->Set("\1TOPT",Buff);
CHP = 31522;
} else {
CHP = 31523;
Klu->Set(NULL,NULL);
CHP = 31524;
}
} else if (stricmp(Klu->Name()," * Origin:") == 0) {
CHP = 31525;
strcpy(Buff,Klu->Body());
tmt = strrchr(Buff,'(');
CHP = 31526;
if (tmt != NULL) *tmt = '\0';
strcat(Buff,"(");
strcat(Buff,(char *)(Str)_FromAddr);
strcat(Buff,")");
CHP = 31527;
Klu->Set(" * Origin:",Buff);
CHP = 31528;
} else if (stricmp(Klu->Name(),"\1FLAGS") == 0) {
CHP = 31529;
fFlagsE = TRUE;
if (strlen(SomeFlagsToStr(Ad1)) != 0) {
CHP = 31530;
Klu->Set("\1FLAGS",Ad1);
CHP = 31531;
} else {
CHP = 31532;
Klu->Set(NULL,NULL);
CHP = 31533;
}
CHP = 31534;
}
CHP = 31535;
}
CHP = 31536;
Klu++;
CHP = 31537;
}
CHP = 31547;
if (ForceINTL && (!fIntlE)) {
if ((!(_FromAddr.Zone() & FA_NOTDEF)) && (!(_ToAddr.Zone() & FA_NOTDEF))) {
CHP = 31548;
f = _FromAddr;
f.Point(0);
strcpy(Ad1,(char *)(Str)f);
f = _ToAddr;
f.Point(0);
strcpy(Ad2,(char *)(Str)f);
sprintf(Buff,"\1INTL %s %s",Ad2,Ad1);
CHP = 31549;
TKlu = new Kludge(Buff);
_Klu.AddToEnd(TKlu);
CHP = 31550;
}
}
if (!fMsgidE) {
CHP = 31551;
if (!(_FromAddr.Zone() & FA_NOTDEF)) {
strcpy(Ad1,(char *)(Str)_FromAddr);
sprintf(Buff,"\1MSGID: %s %08lx",Ad1,MsgID());
CHP = 31552;
TKlu = new Kludge(Buff);
_Klu.AddToEnd(TKlu);
}
CHP = 31553;
}
if ((_FromAddr.Point() & 0xffff) && (!fFromptE)) {
CHP = 31554;
sprintf(Buff,"\1FMPT %u",(word)(_FromAddr.Point() & 0xffff));
CHP = 31555;
TKlu = new Kludge(Buff);
_Klu.AddToEnd(TKlu);
CHP = 31556;
}
if ((_ToAddr.Point() & 0xffff) && (!fToptE)) {
CHP = 31557;
sprintf(Buff,"\1TOPT %u",(word)(_ToAddr.Point() & 0xffff));
CHP = 31558;
TKlu = new Kludge(Buff);
_Klu.AddToEnd(TKlu);
CHP = 31559;
}
if (strlen(SomeFlagsToStr(Ad1)) != 0 && (!fFlagsE)) {
CHP = 31560;
sprintf(Buff,"\1FLAGS %s",Ad1);
CHP = 31561;
TKlu = new Kludge(Buff);
_Klu.AddToEnd(TKlu);
CHP = 31562;
}
CHP = 31563;
// NewVia.Clear();
}
void cMSG::AddKludge(char *&Txt) {
char *tmt, *tmt2;
char *p, *p2, *s,*s2;
FA tAddr;
Kludge *TKlu;
CHP = 300;
if (strlen(Txt) == 0) return;
p = Txt;
while (*Txt != '\0' && *Txt != '\n' && *Txt != '\r') Txt++;
CHP = 302;
tmt = (char *) malloc(Txt - p + 1);
CheckMem(tmt);
CHP = 303;
strncpy(tmt,p,Txt - p);
tmt[Txt - p] = '\0';
// Skip one eol after kludge.
if (Txt[0] != '\0') {
if ((Txt[0] == '\n' && Txt[1] == '\r')
|| (Txt[0] == '\r' && Txt[1] == '\n')) {
Txt += 2;
} else {
if (*Txt == '\n' || *Txt == '\r') Txt++;
}
}
CHP = 304;
p = tmt + strlen(tmt) - 1;
while (p != tmt && *p == ' ') {
*p = '\0';
p--;
}
CHP = 305;
if (strlen(tmt) == 0) {
free(tmt);
return;
}
CHP = 306;
tmt2 = strdup(tmt);
p = tmt;
s = tmt;
while (*s != ' ' && *s != '\0') s++;
if (*s == '\0') {
p2 = "\0";
} else {
*s = '\0';
s++;
while (*s == ' ') s++;
p2 = s;
}
Log.Level(LOGD) << "Split kludge. p == '" << p << "', p2 == '" << p2 << "'" << EOL;
CHP = 307;
if (*p == '\0' && strstr(p2,"* Origin:") == p2) { // Origin (
CHP = 30909;
s = strrchr(p2,'(');
s2 = strrchr(p2,')');
if (s2 != NULL) *s2 = '\0';
CHP = 30910;
tAddr.Clean();
if (s != NULL) {
s++;
tAddr.Parse(s);
}
CHP = 30911;
if (s2 != NULL) *s2 = ')';
CHP = 30912;
if (tAddr.Valid()) {
_FromAddr.Zone(tAddr.Zone());
_FromAddr.Net(tAddr.Net());
_FromAddr.Node(tAddr.Node());
_FromAddr.Point(tAddr.Point());
}
CHP = 30913;
} else if (stricmp(p,"\1FMPT") == 0) { // FMPT <int> Kludge.
_FromAddr.Point(atoi(p2));
} else if (stricmp(p,"\1TOPT") == 0) { // TOPT <int> Kludge
_ToAddr.Point(atoi(p2));
} else if (stricmp(p,"\1INTL") == 0) { // INTL ToAddr FromAddr
tAddr.Parse(p2);
Log.Level(LOGD) << "Parse INTL: ToAddr == '" << tAddr << "'" << EOL;
if (tAddr.Valid()) {
_ToAddr.Zone(tAddr.Zone());
_ToAddr.Net(tAddr.Net());
_ToAddr.Node(tAddr.Node());
}
tAddr.Parse(p2);
Log.Level(LOGD) << "Parse INTL: FromAddr == '" << tAddr << "'" << EOL;
if (tAddr.Valid()) {
_FromAddr.Zone(tAddr.Zone());
_FromAddr.Net(tAddr.Net());
_FromAddr.Node(tAddr.Node());
}
} else if (stricmp(p,"\1FLAGS") == 0) { // FLAGS Flg [FLG]
p = strtok(p2," ");
while (p != NULL) {
if (stricmp(p,"DIR") == 0) {
fDIR = 1;
} else if (stricmp(p,"IMM") == 0) {
fIMM = 1;
} else if (stricmp(p,"TFS") == 0) {
fTFS = 1;
} else if (stricmp(p,"KFS") == 0) {
fKFS = 1;
} else if (stricmp(p,"PVT") == 0) {
fPrivate = 1;
} else if (stricmp(p,"HLD") == 0) {
fHold = 1;
} else if (stricmp(p,"CRA") == 0) {
fCrash = 1;
} else if (stricmp(p,"K/S") == 0) {
fKillSend = 1;
} else if (stricmp(p,"SNT") == 0) {
fSend = 1;
} else if (stricmp(p,"RCV") == 0) {
fReceived = 1;
} else if (stricmp(p,"FIL") == 0) {
fFileAttach = 1;
} else if (stricmp(p,"FRQ") == 0) {
fFileRequest = 1;
} else if (stricmp(p,"RRQ") == 0) {
fRRQ = 1;
} else if (stricmp(p,"CFM") == 0) {
fCFM = 1;
} else if (stricmp(p,"LOK") == 0) {
fLok = 1;
} else if (stricmp(p,"A/S") == 0) {
fAS = 1;
}
p = strtok(NULL," ");
}
} else if (stricmp(p,"\1MSGID:") == 0) { // MSGID: <SomeId>
// from MSGID: we take only missed parameters.
tAddr.Parse(p2);
if (tAddr.Valid()) {
Log.Level(LOGD) << "MSGID is valid. FTN addr == '" << tAddr << "'" << EOL;
if (_ToAddr.Zone() & FA_NOTDEF) {
_ToAddr.Zone(tAddr.Zone());
}
if (_FromAddr.Zone() & FA_NOTDEF) {
_FromAddr.Zone(tAddr.Zone());
}
if (_FromAddr.Net() & FA_NOTDEF) {
_FromAddr.Net(tAddr.Net());
}
if (_FromAddr.Node() & FA_NOTDEF) {
_FromAddr.Node(tAddr.Node());
}
if (_FromAddr.Point() & FA_NOTDEF) {
_FromAddr.Point(tAddr.Point());
}
}
}
CHP = 308;
TKlu = new Kludge(tmt2);
_Klu.AddToEnd(TKlu);
CHP = 308001;
free(tmt);
CHP = 308002;
free(tmt2);
CHP = 309;
}
// ---------------------------
void cMSG::Recode(char *RecodeTable){
char *tmt;
IndBiList<Kludge>::ElemPtr Klu;
int i;
if (_Body != NULL) {
tmt = _Body;
while (*tmt != '\0') {
*tmt = RecodeTable[(unsigned char)*tmt];
tmt++;
}
}
for (i = 0; i < 72; i++) {
_Subject[i] = RecodeTable[(unsigned char)_Subject[i]];
}
for (i = 0; i < 36; i++) {
_FromName[i] = RecodeTable[(unsigned char)_FromName[i]];
}
for (i = 0; i < 36; i++) {
_ToName[i] = RecodeTable[(unsigned char)_ToName[i]];
}
Klu = _Klu.GetFirst();
while (Klu != NULL) {
Klu->Recode(RecodeTable);
Klu++;
}
}
unsigned int cMSG::LoopCount(char *LS) {
IndBiList<Kludge>::ElemPtr Klu;
int lc;
lc = 0;
// Log.Level(LOGD) << "------------------------------------------------------" << EOL;
// Log.Level(LOGD) << "Search loop string '" << LS << "'" << EOL;
// Log.Level(LOGD) << "------------------------------------------------------" << EOL;
Klu = _Klu.GetFirst();
while (Klu != NULL) {
if (LS != NULL && Klu->Name() != NULL && stricmp(Klu->Name(),"\1VIA") == 0
&& Klu->Body() != NULL && strstr(Klu->Body(),LS) != NULL) lc++;
Klu++;
}
return lc;
}
// ---------------------------
unsigned int cMSG::AttachSize(void) {
int i;
i = GetAttSize(*this);
if (i == -1) return 0;
return i;
}
// ---------------------------
unsigned int cMSG::Lines(void) {
unsigned int i;
char *tmt;
i = 0;
tmt = _Body;
if (tmt == NULL) return 0;
while (*tmt != '\0') {
if (*tmt == '\r') i++;
tmt++;
}
if (tmt != _Body && (*(tmt-1) != '\r')) i++;
return i;
}
unsigned int cMSG::Bytes(void) {
if (_Body == NULL) return 0;
return strlen(_Body);
}
// ---------------------------
void cMSG::SetBody(char *Txt, unsigned int Len) {
_Body = (char *) malloc(Len + 1);
memset(_Body,0,Len + 1);
memcpy(_Body,Txt,Len);
fEmpty = 0;
}
// ---------------------------
char *cMSG::FlagsToStr(char *Str) {
Str[0] = '\0';
if (fPrivate) strcat(Str,"Pvt ");
if (fCrash) strcat(Str,"Cra ");
if (fReceived) strcat(Str,"Rcv ");
if (fSend) strcat(Str,"Snt ");
if (fFileAttach) strcat(Str,"Att ");
if (fTransit) strcat(Str,"Trn ");
if (fOrphan) strcat(Str,"Orp ");
if (fKillSend) strcat(Str,"K/S ");
if (fLocal) strcat(Str,"Loc ");
if (fHold) strcat(Str,"Hld ");
if (fFileRequest) strcat(Str,"FRQ ");
if (fRRQ) strcat(Str,"RRQ ");
if (fIRR) strcat(Str,"IRR ");
if (fARQ) strcat(Str,"ARQ ");
if (fFURQ) strcat(Str,"FURQ ");
if (fDIR) strcat(Str,"Dir ");
if (fIMM) strcat(Str,"Imm ");
if (fCFM) strcat(Str,"Cfm ");
if (fTFS) strcat(Str,"TFS ");
if (fKFS) strcat(Str,"KFS ");
if (fScanned) strcat(Str,"Scn ");
if (fLok) strcat(Str,"Lok ");
if (fAS) strcat(Str,"A/S ");
if (Str[0] != '\0') Str[strlen(Str)-1] = '\0';
return Str;
}
// ---------------------------
char *cMSG::SomeFlagsToStr(char *Str) {
Str[0] = '\0';
if (fDIR) strcat(Str,"DIR ");
if (fIMM) strcat(Str,"IMM ");
if (fCFM) strcat(Str,"CFM ");
if (fTFS) strcat(Str,"TFS ");
if (fKFS) strcat(Str,"KFS ");
if (fLok) strcat(Str,"LOK ");
if (fAS) strcat(Str,"A/S ");
if (Str[0] != '\0') Str[strlen(Str)-1] = '\0';
return Str;
}
// ---------------------------
void cMSG::ParseMem(char *Buff) {
char *tmt1, *tmt2;
int NewLine;
char BuffForSearch[128];
CHP = 229;
if (Buff == NULL || *Buff == '\0') {
if (UseOwnZone && (_FromAddr.Zone() & FA_NOTDEF)) {
_FromAddr.Zone(FA_ANYMASK);
_FromAddr.Zone(GetMyAka(_FromAddr).Zone());
_ToAddr.Zone(FA_ANYMASK);
_ToAddr.Zone(GetMyAka(_ToAddr).Zone());
}
return;
}
CHP = 230;
tmt1 = Buff;
// Check echomail.
if (tmt1[0] == 'A' && tmt1[1] == 'R' && tmt1[2] == 'E' &&
tmt1[3] == 'A' && tmt1[4] == ':') {
strncpy(_AreaName,&tmt1[5],127);
_AreaName[127] = '\0';
tmt2 = strchr(_AreaName,'\n');
if (tmt2 != NULL) *tmt2 = '\0';
tmt2 = strchr(_AreaName,'\r');
if (tmt2 != NULL) *tmt2 = '\0';
AddKludge(tmt1);
fEchomail = 1;
}
// ok. Now copy message and parse kludges.
// Fucked FTN standarts...
_Body = (char *) malloc(strlen(tmt1)+1);
CheckMem(_Body);
tmt2 = _Body;
NewLine = TRUE;
while (*tmt1 != '\0') {
// 1-st. Replace all 0A0D, 0D0A, smth0Asmth to 0D
if (tmt1[0] == '\n' && tmt1[1] == '\r') {
tmt1++;
} else if (tmt1[0] == '\r' && tmt1[1] == '\n') {
tmt1[1] = '\r';
tmt1++;
} else if (*tmt1 == '\n') {
tmt1[0] = '\r';
}
if (*tmt1 == '\r') {
NewLine = TRUE;
*tmt2 = *tmt1;
tmt2++; tmt1++;
continue;
}
if (NewLine == TRUE) { // All kludges shoul be start from begin of string.
strncpy(BuffForSearch,tmt1,126);
BuffForSearch[127] = '\0';
nls_strupr(BuffForSearch);
if ((strstr(BuffForSearch,"SEEN-BY:") == BuffForSearch)
|| (strstr(BuffForSearch," * ORIGIN:") == BuffForSearch)
|| (strstr(BuffForSearch,"--- ") == BuffForSearch)
|| (strstr(BuffForSearch,"---\n") == BuffForSearch)
|| (strstr(BuffForSearch,"---\r") == BuffForSearch)) {
AddKludge(tmt1);
continue;
} else if (*tmt1 == '\1') {
AddKludge(tmt1);
continue;
}
}
NewLine = FALSE;
*tmt2 = *tmt1;
tmt2++; tmt1++;
continue;
}
*tmt2 = '\0';
if (strlen(_Body) != 0) fEmpty = 0;
// If we have not received the Zone for this letter - we shall
// receive it in the magic way.
if (UseOwnZone) {
if (_FromAddr.Zone() & FA_NOTDEF) {
_FromAddr.Zone(FA_ANYMASK);
_FromAddr.Zone(GetMyAka(_FromAddr).Zone());
}
if (_ToAddr.Zone() & FA_NOTDEF) {
_ToAddr.Zone(FA_ANYMASK);
_ToAddr.Zone(GetMyAka(_ToAddr).Zone());
}
}
CHP = 236;
}
// ---------------------------
void cMSG::AddOurVia(void) {
time_t t;
char Buff[1024];
char *tmt;
struct tm *tt;
DelLastOurVia();
Buff[0] = '\0';
t = time(NULL);
tt = localtime(&t);
if (UTC == 99) {
UTC = tzoffset();
}
if (NewVIAType == FALSE) {
sprintf(Buff,"\1Via %s FTrack %s ", (char*)(Str)GetMyAka(_ToAddr),FVersion);
strftime(Buff+strlen(Buff),80,"%d %b %Y %H:%M:%S",localtime(&t));
if (UTC != 99) {
sprintf(Buff+strlen(Buff)," UTC%+03d00",UTC);
}
} else {
sprintf(Buff,"\1Via %s @", (char *)(Str)GetMyAka(_ToAddr));
if (UTC != 99) {
t = t - UTC * (60*60);
}
strftime(Buff+strlen(Buff),80,"%Y%m%d.%H%M%S",localtime(&t));
if (UTC != 99) {
strcat(Buff,".UTC");
}
sprintf(Buff+strlen(Buff)," FTrack %s",FVersion);
}
tmt = Buff;
AddKludge(tmt);
}
void cMSG::DelLastOurVia(void) {
char Buff[1024];
IndBiList<Kludge>::ElemPtr Klu;
Klu = _Klu.GetLast();
sprintf(Buff,"%s ", (char *)(Str)GetMyAka(_ToAddr));
if (Klu != NULL) {
if (Klu->Name() != NULL && Klu->Body() != NULL) {
if (stricmp(Klu->Name(),"\1Via") == 0 &&
(strstr(Klu->Body(),Buff) == Klu->Body()) &&
(strstr(Klu->Body()," FTrack ") != NULL)) {
if (LogLevel >= 5) {
Log.Level(LOGD) << "Delete our via. Via is '" << Buff << "'" << EOL;
Log.Level(LOGD) << " Via (or Klu) in msg: " << Klu->Name() << " '--' " << Klu->Body() << EOL;
}
_Klu.Remove(Klu);
}
}
}
}
// ---------------------------
cMSG & cMSG::operator = ( const cMSG &m ){
_FromAddr = m._FromAddr;
_ToAddr = m._ToAddr;
_Body = NULL;
if (m._Body != NULL) {
_Body = strdup(m._Body);
}
strncpy(_Subject,m._Subject,72);
strncpy(_FromName,m._FromName,36);
strncpy(_ToName,m._ToName,36);
_Cost = m._Cost;
_TimesRead = _TimesRead;
_ReplyTo = m._ReplyTo;
_NextReply = m._NextReply;
memcpy(_Reserved,m._Reserved,8);
fEchomail = m.fEchomail; fNoZone = m.fNoZone; fChanged = m.fChanged;
fPrivate = m.fPrivate; fCrash = m.fCrash; fReceived = m.fReceived;
fSend = m.fSend; fFileAttach = m.fFileAttach; fTransit = m.fTransit;
fOrphan = m.fOrphan; fKillSend = m.fKillSend; fLocal = m.fLocal;
fHold = m.fHold; fFileRequest = m.fFileRequest; fRRQ = m.fRRQ;
fIRR = m.fIRR; fARQ = m.fARQ; fFURQ = m.fFURQ; fDIR = m.fDIR;
fIMM = m.fIMM; fCFM = m.fCFM; fEmpty = m.fEmpty; fTFS = m.fTFS;
fKFS = m.fKFS; fScanned = m.fScanned; fLok = m.fLok;
fAS = m.fAS;
return *this;
}
// ---------------------------
void cMSG::Print(void) {
char Buff[128];
Log.Level(LOGD) << "------------------------------------------------------" << EOL;
Log.Level(LOGD) << "Message is " << (fEmpty ? "Empty" : "not Empty") << EOL;
Log.Level(LOGD) << "Message is " << (fEchomail ? "Echomail" : "Netmail") << EOL;
if (fEchomail) {
Log.Level(LOGD) << "Area: " << _AreaName << EOL;
}
Log.Level(LOGD) << "Kludges:" << EOL;
INDBILIST_FOREACH(Kludge,_Klu,Klu) Klu->Print();
Log.Level(LOGD) << "------------------------------------------------------" << EOL;
Log.Level(LOGD) << "From : " << _FromName << " (" << _FromAddr << ")" << EOL;
Log.Level(LOGD) << "To : " << _ToName << " (" << _ToAddr << ")" << EOL;
Log.Level(LOGD) << "Attr : " << FlagsToStr(Buff) << EOL;
Log.Level(LOGD) << "Subj : " << _Subject << EOL;
Log.Level(LOGD) << "Time : " << FromTime(_Time) << EOL;
Log.Level(LOGD) << "Age : " << AgeIs(_Time) << EOL;
Log.Level(LOGD) << "Bytes: " << Bytes() << EOL;
Log.Level(LOGD) << "Lines: " << Lines() << EOL;
// Log.Level(LOGD) << "Loop: " << _LoopCount << EOL;
Log.Level(LOGD) << "------------------------------------------------------" << EOL;
}
syntax highlighted by Code2HTML, v. 0.9.1