// -------------------------------------------------------------------- // S c d _ d o . c p p // // Fido messages tracker // ScanDir.cpp portion. // -------------------------------------------------------------------- // Copyright (c) 1998-2000 by Fyodor Ustinov // FIDONet 2:5020/79 // // All rights reserved. // -------------------------------------------------------------------- #ifndef __SCD_DP_CPP__ #define __SCD_DP_CPP__ FA &MakeFromAddr(cMSG &m, FA &s) { static FA t; CHP = 2; t = s; if (s.Zone() & FA_ANYMASK) { t.Zone(m._FromAddr.Zone()); } else { t.Zone(s.Zone()); } if (s.Net() & FA_ANYMASK) { t.Net(m._FromAddr.Net()); } else { t.Net(s.Net()); } if (s.Node() & FA_ANYMASK) { t.Node(m._FromAddr.Node()); } else { t.Node(s.Node()); } if (s.Point() & FA_ANYMASK) { t.Point(m._FromAddr.Point()); } else { t.Point(s.Point()); } if (s.Zone() & FA_TOMASK) { t = m._ToAddr; } if (s.Zone() & FA_FROMMASK) { t = m._FromAddr; } if (s.Zone() & FA_OURMASK) { t = GetMyAka(m._ToAddr); } return t; } FA &MakeToAddr(cMSG &m, FA &s) { static FA t; CHP = 3; t = s; if (s.Zone() & FA_ANYMASK) { t.Zone(m._ToAddr.Zone()); } else { t.Zone(s.Zone()); } if (s.Net() & FA_ANYMASK) { t.Net(m._ToAddr.Net()); } else { t.Net(s.Net()); } if (s.Node() & FA_ANYMASK) { t.Node(m._ToAddr.Node()); } else { t.Node(s.Node()); } if (s.Point() & FA_ANYMASK) { t.Point(m._ToAddr.Point()); } else { t.Point(s.Point()); } if (s.Zone() & FA_FROMMASK) { t = m._FromAddr; } if (s.Zone() & FA_TOMASK) { t = m._ToAddr; } if (s.Zone() & FA_OURMASK) { t = GetMyAka(m._FromAddr); } return t; } void MakeToName(cMSG &m, char *s, char *t) { CHP = 4; if (s != NULL && strcmp(s,"*") == 0) { strncpy(t,m._ToName,36); return; } if (s != NULL && strcmp(s,FROMMASK_CHAR) == 0) { strncpy(t,m._FromName,36); return; } if (s != NULL && strcmp(s,TOMASK_CHAR) == 0) { strncpy(t,m._ToName,36); return; } if (s != NULL) { strncpy(t,s,36); return; } } void MakeFromName(cMSG &m, char *s, char *t) { CHP = 5; if (s != NULL && strcmp(s,"*") == 0) { strncpy(t,m._FromName,36); return; } if (s != NULL && strcmp(s,FROMMASK_CHAR) == 0) { strncpy(t,m._FromName,36); return; } if (s != NULL && strcmp(s,TOMASK_CHAR) == 0) { strncpy(t,m._ToName,36); return; } if (s != NULL) { strncpy(t,s,36); return; } } void PrepareMsg(cMSG &s, cMSG &d, NormalMask *_Mask) { FA tf; FA tt; char sf[36]; char st[36]; char *tmt; CHP = 6; MakeFromName(s,_Mask->_FromName,sf); MakeToName(s,_Mask->_ToName,st); strncpy(d._FromName,sf,36); strncpy(d._ToName,st,36); strncpy(d._Subject,s._Subject,72); tf = MakeFromAddr(s,_Mask->_FromAddr); tt = MakeToAddr(s,_Mask->_ToAddr); if (s._FromAddr != tf) { // If we change source address d.fChanged = 1; // we need change MSGID. } d._FromAddr = tf; d._ToAddr = tt; if (&s == &d) { d.fPrivate = (_Mask->fPrivate != 0) ? _Mask->fPrivate : s.fPrivate; d.fCrash = (_Mask->fCrash != 0) ? _Mask->fCrash : s.fCrash; d.fReceived = (_Mask->fReceived != 0) ? _Mask->fReceived : s.fReceived; d.fSend = (_Mask->fSend != 0) ? _Mask->fSend : s.fSend; d.fFileAttach = (_Mask->fFileAttach != 0) ? _Mask->fFileAttach : s.fFileAttach; d.fTransit = (_Mask->fTransit != 0) ? _Mask->fTransit : s.fTransit; d.fOrphan = (_Mask->fOrphan != 0) ? _Mask->fOrphan : s.fOrphan; d.fKillSend = (_Mask->fKillSend != 0) ? _Mask->fKillSend : s.fKillSend; d.fLocal = (_Mask->fLocal != 0) ? _Mask->fLocal : s.fLocal; d.fHold = (_Mask->fHold != 0) ? _Mask->fHold : s.fHold; d.fFileRequest = (_Mask->fFileRequest != 0) ? _Mask->fFileRequest : s.fFileRequest; d.fRRQ = (_Mask->fRRQ != 0) ? _Mask->fRRQ : s.fRRQ; d.fIRR = (_Mask->fIRR != 0) ? _Mask->fIRR : s.fIRR; d.fARQ = (_Mask->fARQ != 0) ? _Mask->fARQ : s.fARQ; d.fFURQ = (_Mask->fFURQ != 0) ? _Mask->fFURQ : s.fFURQ; d.fDIR = (_Mask->fDIR != 0) ? _Mask->fDIR : s.fDIR; d.fIMM = (_Mask->fIMM != 0) ? _Mask->fIMM : s.fIMM; d.fCFM = (_Mask->fCFM != 0) ? _Mask->fCFM : s.fCFM; d.fTFS = (_Mask->fTFS != 0) ? _Mask->fTFS : s.fTFS; d.fKFS = (_Mask->fKFS != 0) ? _Mask->fKFS : s.fKFS; d.fScanned = (_Mask->fScanned != 0) ? _Mask->fScanned : s.fScanned; d.fLok = (_Mask->fLok != 0) ? _Mask->fLok : s.fLok; d.fAS = (_Mask->fAS != 0) ? _Mask->fAS : s.fAS; } else { d.fPrivate = (_Mask->fPrivate != 0) ? _Mask->fPrivate : 0; d.fCrash = (_Mask->fCrash != 0) ? _Mask->fCrash : 0; d.fReceived = (_Mask->fReceived != 0) ? _Mask->fReceived : 0; d.fSend = (_Mask->fSend != 0) ? _Mask->fSend : 0; d.fFileAttach = (_Mask->fFileAttach != 0) ? _Mask->fFileAttach : 0; d.fTransit = (_Mask->fTransit != 0) ? _Mask->fTransit : 0; d.fOrphan = (_Mask->fOrphan != 0) ? _Mask->fOrphan : 0; d.fKillSend = (_Mask->fKillSend != 0) ? _Mask->fKillSend : 0; d.fLocal = (_Mask->fLocal != 0) ? _Mask->fLocal : 0; d.fHold = (_Mask->fHold != 0) ? _Mask->fHold : 0; d.fFileRequest = (_Mask->fFileRequest != 0) ? _Mask->fFileRequest : 0; d.fRRQ = (_Mask->fRRQ != 0) ? _Mask->fRRQ : 0; d.fIRR = (_Mask->fIRR != 0) ? _Mask->fIRR : 0; d.fARQ = (_Mask->fARQ != 0) ? _Mask->fARQ : 0; d.fFURQ = (_Mask->fFURQ != 0) ? _Mask->fFURQ : 0; d.fDIR = (_Mask->fDIR != 0) ? _Mask->fDIR : 0; d.fIMM = (_Mask->fIMM != 0) ? _Mask->fIMM : 0; d.fCFM = (_Mask->fCFM != 0) ? _Mask->fCFM : 0; d.fTFS = (_Mask->fTFS != 0) ? _Mask->fTFS : 0; d.fKFS = (_Mask->fKFS != 0) ? _Mask->fKFS : 0; d.fScanned = (_Mask->fScanned != 0) ? _Mask->fScanned : 0; d.fLok = (_Mask->fLok != 0) ? _Mask->fLok : 0; d.fAS = (_Mask->fAS != 0) ? _Mask->fAS : 0; } if (_Mask->_Subject != NULL && strcmp(_Mask->_Subject,"*") != 0) { tmt = StrAsTpl(d,_Mask->_Subject); strncpy(d._Subject,tmt,72); free(tmt); } if (LogLevel >= 5) { Log.Level(LOGD) << "----------------------- Destin message -----------------" << EOL; d.Print(); Log.Level(LOGD) << "----------------------- Source message -----------------" << EOL; s.Print(); } } int Action::Do(MSGBASE &b, cMSG &m) { char *tmt; char *tmt2; cMSG *d; FILE *fh; PKT p; FA f; PKTrc rc; int rcc; CHP = 7; switch(_Act) { case ACT_IGNORE: CHP = 8; if (LogIgnore) { Log.Level(LOGI) << "Ignore msg " << b.MessageName() << EOL; } break; case ACT_DELETE: CHP = 9; tmt = b.MessageName(); Log.Level(LOGI) << "Delete msg " << tmt << EOL; if (!b.DeleteMsg()) { Log.Level(LOGE) << "Error deleting message " << tmt << EOL; return FALSE; } break; case ACT_FLAG: CHP = 10; Log.Level(LOGI) << "Create file " << _OutDir << EOL; fh = fcopen(_OutDir,"wb"); if (fh == NULL) { Log.Level(LOGE) << "Error creating file " << _OutDir << EOL; return FALSE; } fclose(fh); break; case ACT_DELFILE: CHP = 10; Log.Level(LOGI) << "Delete file " << _OutDir << EOL; unlink(_OutDir); break; case ACT_DELETEATTACH: CHP = 11; if (m.fFileAttach) { m.Normalise(); tmt = b.MessageName(); Log.Level(LOGI) << "Delete files attached to " << tmt << EOL; tmt2 = FileInbound; if (sd->_FileInbound != NULL) { FileInbound = sd->_FileInbound; } if (!DeleteAttach(m)) { FileInbound = tmt2; return FALSE; } FileInbound = tmt2; } break; case ACT_CHANGEPATH: CHP = 12; if (m.fFileAttach) { m.Normalise(); tmt = b.MessageName(); if (strlen(_OutDir) == 0) { Log.Level(LOGI) << "Strip path to attached files in " << tmt << EOL; } else { Log.Level(LOGI) << "Change path to attached files in " << tmt << " to " << _OutDir << EOL; } tmt2 = FileInbound; if (sd->_FileInbound != NULL) { FileInbound = sd->_FileInbound; } if (!ChangePath(m,_OutDir)) { FileInbound = tmt2; return FALSE; } FileInbound = tmt2; // m.fChanged = 1; if (SetViaAlways == TRUE) { m.AddOurVia(); } if (!b.WriteMsg(m)) { Log.Level(LOGE) << "Error writing message with new subject " << tmt << EOL; return FALSE; } } break; case ACT_MOVEATTACH: CHP = 13; if (m.fFileAttach) { m.Normalise(); tmt = b.MessageName(); Log.Level(LOGI) << "Move attached files in " << tmt << " to " << _OutDir << EOL; tmt2 = FileInbound; if (sd->_FileInbound != NULL) { FileInbound = sd->_FileInbound; } if (!MoveAttach(m,_OutDir)) { FileInbound = tmt2; return FALSE; } FileInbound = tmt2; // m.fChanged = 1; if (SetViaAlways == TRUE) { m.AddOurVia(); } if (!b.WriteMsg(m)) { Log.Level(LOGE) << "Error writing message with new subject " << tmt << EOL; return FALSE; } } break; case ACT_COPYATTACH: CHP = 13; if (m.fFileAttach) { m.Normalise(); tmt = b.MessageName(); Log.Level(LOGI) << "Copy attached files in " << tmt << " to " << _OutDir << EOL; tmt2 = FileInbound; if (sd->_FileInbound != NULL) { FileInbound = sd->_FileInbound; } if (!CopyAttach(m,_OutDir)) { FileInbound = tmt2; return FALSE; } FileInbound = tmt2; } break; case ACT_COPY: CHP = 14; m.Normalise(); if (SetViaAlways == TRUE) { m.AddOurVia(); } CHP = 1401; tmt = b.MessageName(); CHP = 1402; Log.Level(LOGI) << "Copy msg " << tmt << " to " << _Base->BaseName() << EOL; if (_Base->Open() != TRUE) { Log.Level(LOGE) << "Error opening base '" << _Base->BaseName() << "'" << EOL; return FALSE; } CHP = 1403; if (!_Base->WriteNewMsg(m)) { CHP = 1404; Log.Level(LOGE) << "Error writing message " << tmt << " to " << _Base->BaseName() << EOL; _Base->Close(); return FALSE; } CHP = 1405; _Base->Close(); CHP = 1406; break; case ACT_MOVE: CHP = 15; m.Normalise(); CHP = 1501; if (SetViaAlways == TRUE) { m.AddOurVia(); } tmt = b.MessageName(); CHP = 1502; Log.Level(LOGI) << "Move msg " << tmt << " to " << _Base->BaseName() << EOL; if (_Base->Open() != TRUE) { Log.Level(LOGE) << "Error opening base '" << _Base->BaseName() << "'" << EOL; return FALSE; } CHP = 1503; if (!_Base->WriteNewMsg(m)) { CHP = 1504; Log.Level(LOGE) << "Error writing message " << tmt << " to " << _Base->BaseName() << EOL; _Base->Close(); return FALSE; } CHP = 1505; if (!b.DeleteMsg()) { CHP = 1506; Log.Level(LOGE) << "Error deleting message " << tmt << EOL; _Base->Close(); return FALSE; } CHP = 1506; _Base->Close(); CHP = 1507; break; case ACT_WRITEFILE: CHP = 16; m.Normalise(); _Tpl->Clean(); _Tpl->SetMsg(m); Log.Level(LOGI) << "Create file " << _OutDir << EOL; if (!_Tpl->Parse()) { return FALSE; } if (!_Tpl->Save(_OutDir,1)) { return FALSE; } _Tpl->Clean(); break; case ACT_ADDFILE: CHP = 16001; m.Normalise(); _Tpl->Clean(); _Tpl->SetMsg(m); Log.Level(LOGI) << "Append to file " << _OutDir << EOL; if (!_Tpl->Parse()) { return FALSE; } if (!_Tpl->Save(_OutDir,2)) { return FALSE; } _Tpl->Clean(); break; case ACT_ADDNOTE: CHP = 16100; m.Normalise(); if (SetViaAlways == TRUE) { m.AddOurVia(); } _Tpl->Clean(); _Tpl->SetMsg(m); tmt = b.MessageName(); Log.Level(LOGI) << "Add note " << _OutDir << " to msg " << tmt << EOL; if (!_Tpl->Parse()) { return FALSE; } CHP = 16101; while ((tmt = strchr((char *) _Tpl->Body,'\n')) != NULL) *tmt = '\r'; tmt = m._Body; CHP = 16102; m._Body = (char *) malloc(((tmt != NULL) ? strlen(tmt) : 0) + strlen(_Tpl->Body) + 1); m.fEmpty = 0; CheckMem(m._Body); CHP = 16103; strcpy(m._Body,_Tpl->Body); CHP = 16104; if (tmt != NULL) { strcat(m._Body,tmt); free(tmt); } CHP = 16105; _Tpl->Clean(); // m.fChanged = 1; CHP = 16106; if (!b.WriteMsg(m)) { tmt = b.MessageName(); Log.Level(LOGE) << "Error rewriting message " << tmt << EOL; return FALSE; } CHP = 16107; break; case ACT_CALL: m.Normalise(); tmt = StrAsTpl(m,_TplName); Log.Level(LOGI) << "Execute programm " << tmt << EOL; if (_Tpl != NULL) { _Tpl->Clean(); _Tpl->SetMsg(m); if (!_Tpl->Parse()) { free(tmt); return FALSE; } if (!_Tpl->Save(_OutDir,1)) { free(tmt); return FALSE; } _Tpl->Clean(); } rcc = ExecP(tmt); unlink(_OutDir); if (rcc < 0) { Log.Level(LOGE) << "Error execution " << tmt << EOL; } else { Log.Level(LOGI) << "Done execution. Error code == " << rcc << EOL; } free(tmt); break; case ACT_ROUTE: CHP = 17; tmt2 = FileInbound; if (sd->_FileInbound != NULL) { FileInbound = sd->_FileInbound; } m.Normalise(); if (_f.Zone() & FA_TOMASK) { f = m._ToAddr; if (!(_f.Point() & FA_TOMASK)) { f.Point(0); } } else { f = _f; } Log.Level(LOGI) << "Route message from " << m._FromAddr; Log.Level(LOGI) << " to " << m._ToAddr; Log.Level(LOGI) << " via " << f << EOL; strncpy(m._RoutedVia,(char *)(Str)f,127); if (Before != NULL) { Log.Level(LOGI) << " Execute 'BeforeRoute' ScanDir." << EOL; Before->DoWithRoute(*sd->_Base,m); m._RoutedVia[0] = '\0'; } p.Set(f); tmt = (char *)(Str)f; m.AddOurVia(); rc = p.AddMsg(m,_Flav); switch (rc) { case BSY: Log.Level(LOGW) << f << " is Busy now." << EOL; p.Clean(); FileInbound = tmt2; return TRUE; case NULLPKT: Log.Level(LOGW) << "?UT file for address " << f << " is null size. Message " << b.MessageName() << " skipped." << EOL; p.Clean(); FileInbound = tmt2; return TRUE; case PKTERROR: Log.Level(LOGE) << "Error routing message "<< b.MessageName() << " to " << f << EOL; p.Clean(); FileInbound = tmt2; return FALSE; case ATTERROR: Log.Level(LOGE) << "Error routing files attached to message "<< b.MessageName() << " to " << f << EOL; p.Clean(); FileInbound = tmt2; return FALSE; case BADPKT: Log.Level(LOGE) << "?LO file for address " << f << " is invalid. Message " << b.MessageName() << " skipped." << EOL; p.Clean(); FileInbound = tmt2; return TRUE; default: break; } p.Clean(); LogTraffic(m,f); tmt = b.MessageName(); if (KillMode == KILL_ALWAYS || (KillMode == KILL_FLAG && m.fKillSend)) { if (!b.DeleteMsg()) { Log.Level(LOGE) << "Error deleting message " << tmt << EOL; FileInbound = tmt2; return FALSE; } } if (After != NULL) { Log.Level(LOGI) << " Execute 'AfterRoute' ScanDir." << EOL; strncpy(m._RoutedVia,(char *)(Str)f,127); After->DoWithRoute(*sd->_Base,m); m._RoutedVia[0] = '\0'; } FileInbound = tmt2; break; case ACT_POLL: CHP = -17; if (_f.Zone() & FA_TOMASK) { f = m._ToAddr; if (!(_f.Point() & FA_TOMASK)) { f.Point(0); } } else { f = _f; } Log.Level(LOGI) << "Poll " << f << EOL; p.Set(f); rc = p.Poll(_Flav); switch (rc) { case BSY: Log.Level(LOGW) << f << " is Busy now." << EOL; p.Clean(); return TRUE; case PKTERROR: Log.Level(LOGE) << "Error generating poll to " << f << EOL; p.Clean(); return FALSE; default: break; } p.Clean(); break; case ACT_NEWMSG: CHP = 18; d = new cMSG(); CHP = 1801; _Tpl->Clean(); _Tpl->SetMsg(m,*d); CHP = 1802; d->_Time = time(NULL); Log.Level(LOGI) << "Create new msg in " << _Base->BaseName() << EOL; if (_Base->Open() != TRUE) { Log.Level(LOGE) << "Error opening base '" << _Base->BaseName() << "'" << EOL; return FALSE; } CHP = 1803; PrepareMsg(m,*d,(NormalMask*)_Mask); CHP = 1804; m.Normalise(); CHP = 1805; d->fChanged = 1; if (!_Tpl->Parse()) { CHP = 1806; delete d; _Base->Close(); return FALSE; } CHP = 1807; CHP = 1808; if (!_Tpl->Save(*d)) { delete d; _Base->Close(); CHP = 1809; return FALSE; } CHP = 1810; if (SetViaAlways == TRUE) { d->AddOurVia(); } if (!_Base->WriteNewMsg(*d)) { Log.Level(LOGE) << "Error writing new message " << _Base->MessageName() << EOL; delete d; _Base->Close(); return FALSE; } CHP = 1811; _Tpl->Clean(); CHP = 1812; delete d; _Base->Close(); break; case ACT_REWRITE: CHP = 19; tmt = b.MessageName(); Log.Level(LOGI) << "Rewrite msg " << tmt << EOL; PrepareMsg(m,m,(NormalMask*)_Mask); m.Normalise(); if (SetViaAlways == TRUE) { m.AddOurVia(); } // m.fChanged = 1; if (!b.WriteMsg(m)) { Log.Level(LOGE) << "Error rewriting message " << tmt << EOL; return FALSE; } break; case ACT_RECODE: CHP = 1901; tmt = b.MessageName(); Log.Level(LOGI) << "Recode msg " << tmt << EOL; m.Normalise(); m.Recode(_TplName); if (!b.WriteMsg(m)) { Log.Level(LOGE) << "Error recoding message " << tmt << EOL; return FALSE; } break; case ACT_DISPLAY: CHP = 20; tmt = StrAsTpl(m,_TplName); Log.Level(LOGE) << tmt << EOL; free(tmt); break; case ACT_SCRIPT: CHP = 2001; if (DoThisWord(_TplName) != TRUE) { return FALSE; } break; case ACT_SPLIT:{ int Parts; int Lns; int CurPart; char *sBeg = NULL; char *tmt2; char *stmt = NULL; m.Normalise(); if (SetViaAlways == TRUE) { m.AddOurVia(); } tmt = b.MessageName(); Lns = m.Lines(); if (Lns > _Lines) { Log.Level(LOGI) << "Split message " << tmt << EOL; Parts = Lns / _Lines; if ((Lns % _Lines) != 0) Parts++; CurPart = 1; sBeg = m.Body(); tmt2 = sBeg; tmt = (char *)malloc(m.Bytes()+200); stmt = tmt; CheckMem(tmt); while (*tmt2 != '\0') { tmt = stmt; sprintf(tmt,"\1SPLITTED: By FTrack. Part %d of %d\r",CurPart, Parts); tmt += strlen(tmt); for(Lns = 0; Lns < _Lines && *tmt2 != '\0'; tmt2++,tmt++) { if (*tmt2 == '\r') Lns++; *tmt = *tmt2; } *tmt = '\0'; m.Body(stmt); m.fChanged = TRUE; if (!b.WriteNewMsg(m)) { Log.Level(LOGE) << " Error writing splitted message." << EOL; free(stmt); m.Body(sBeg); return FALSE; } CurPart++; } m.Body(sBeg); free(stmt); Log.Level(LOGI) << " Message splitted to " << Parts << " Parts" << EOL; if (!b.DeleteMsg()) { Log.Level(LOGE) << " Error deleting splitted message." << EOL; return FALSE; } } }; break; default: break; } CHP = 21; return TRUE; } #endif