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


syntax highlighted by Code2HTML, v. 0.9.1