// --------------------------------------------------------------------
//       p a r s e t p l . c p p
//                                                                     
//        Fido messages tracker                            
//        Work with template files
// --------------------------------------------------------------------
//        Copyright (c) 1998,99 by Fyodor Ustinov                         
//                              FIDONet 2:5020/79                      
//                                                                     
//        All rights reserved.                                         
// --------------------------------------------------------------------
#ifndef __GNUC__
#include <io.h>
#include <direct.h>
#else
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <errno.h>
#endif                                                                                                          
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "constant.hpp"
#include "help.hpp"
#include "utils.hpp"
#include "vars.hpp"
#include "scandir.hpp"
#include "badmsg.hpp"
#include "aka.hpp"
#include "age.hpp"
#include "parsetpl.hpp"
#include "ufmtypes.h"

// --------------------------------------------------------------------
//                         Local function prototypes
// --------------------------------------------------------------------

int SetLogFile(void);
int SetLogLevel(void);
int SetNodelist(void);
int CommentLine(void);
int SetIndexFile(void);
int SetNodelistPath(void);
int SetMyAddr(void);
int SetSysopName(void);
int SetUseOwnZone(void);
int SetForceINTL(void);
int SetLoopStr(void);
int SetNoLogIgnore(void);

// --------------------------------------------------------------------
//                                Local variables
// --------------------------------------------------------------------

static int AddSysop(Template *Tpl);
static int AddMaxAge(Template *Tpl);
static int AddMyAddr(Template *Tpl);
static int AddMsgDate(Template *Tpl);
static int AddMsgAge(Template *Tpl);
static int AddFromName(Template *Tpl);
static int AddToName(Template *Tpl);
static int AddSubject(Template *Tpl);
static int AddFromAddr(Template *Tpl);
static int AddFromZone(Template *Tpl);
static int AddFromNet(Template *Tpl);
static int AddFromNode(Template *Tpl);
static int AddFromPoint(Template *Tpl);
static int AddToAddr(Template *Tpl);
static int AddToZone(Template *Tpl);
static int AddToNet(Template *Tpl);
static int AddToNode(Template *Tpl);
static int AddToPoint(Template *Tpl);
static int AddMsgFlags(Template *Tpl);
static int AddMsgHeader(Template *Tpl);
static int AddDate(Template *Tpl);
static int AddMsgBody(Template *Tpl);
static int AddMsgKludges(Template *Tpl);
static int AddMsgVias(Template *Tpl);
static int AddNodelists(Template *Tpl);
static int AddMsgOrigin(Template *Tpl);
static int AddMsgTearline(Template *Tpl);
static int AddMsgNOrigin(Template *Tpl);
static int AddMsgNTearline(Template *Tpl);
static int AddOrigin(Template *Tpl);
static int AddTearline(Template *Tpl);
static int AddMsgLoops(Template *Tpl);
static int AddMsgAttachSize(Template *Tpl);
static int AddMaxAttachSize(Template *Tpl);
static int AddAreaName(Template *Tpl);
static int AddSize(Template *Tpl);
static int AddLines(Template *Tpl);
static int AddRoutedVia(Template *Tpl);
static int AddMsgId(Template *Tpl);
static int AddMsgReply(Template *Tpl);
static int AddNewMsgId(Template *Tpl);
static int AddFVersion(Template *Tpl);
   
typedef struct {
   char *Token;
   int  (*Func)(Template *Tpl);
} TplTok;

static TplTok TemplTokens[] = {
   {"Nodelists",&AddNodelists},
   {"ToName",&AddToName},
   {"FromName",&AddFromName},
   {"Subject",&AddSubject},
   {"MsgHeader",&AddMsgHeader},
   {"MsgKludges",&AddMsgKludges},
   {"MsgVias",&AddMsgVias},
   {"MsgAttr",&AddMsgFlags},
   {"Sysop",&AddSysop},
   {"FromAddr",&AddFromAddr},
   {"FromZone",&AddFromZone},
   {"FromNet",&AddFromNet},
   {"FromNode",&AddFromNode},
   {"FromPoint",&AddFromPoint},
   {"ToAddr",&AddToAddr},
   {"ToZone",&AddToZone},
   {"ToNet",&AddToNet},
   {"ToNode",&AddToNode},
   {"ToPoint",&AddToPoint},
   {"MyAddr",&AddMyAddr},
   {"MsgBody",&AddMsgBody},
   {"MsgDate",&AddMsgDate},
   {"Date",&AddDate},
   {"MsgAge",&AddMsgAge},
   {"MaxAge",&AddMaxAge},
   {"MsgOrigin",&AddMsgOrigin},
   {"MsgTearline",&AddMsgTearline},
   {"MsgNOrigin",&AddMsgNOrigin},
   {"MsgNTearline",&AddMsgNTearline},
   {"MsgAttachSize",&AddMsgAttachSize},
   {"MaxAttachSize",&AddMaxAttachSize},
   {"Origin",&AddOrigin},
   {"Tearline",&AddTearline},
   {"MsgLoops",&AddMsgLoops},
   {"MsgAreaName",&AddAreaName},
   {"MsgSize",&AddSize},
   {"MsgLines",&AddLines},
   {"MsgRoutedVia",&AddRoutedVia},
   {"MsgID",&AddMsgId},
   {"MsgReply",&AddMsgReply},
   {"Version",&AddFVersion},
//   {"NewMsgId",&AddNewMsgId},
   {0,0}
};
// --------------------------------------------------------------------

static int AddNodelists(Template *Tpl) {
char Buff[4096];
   CHP = 77001;
   Ndl.Names(Buff);
   CHP = 77002;
   Tpl->Body += Buff;
   CHP = 77003;
   return TRUE;
}

static int AddOrigin(Template *Tpl) {
   CHP = 77004;
   Tpl->Body += " * Origin: ";
   CHP = 77005;
   if (Origin != NULL) {
      Tpl->Body += Origin;
   }
   CHP = 77006;
   Tpl->Body +=" (";
   Tpl->Body += Tpl->To->_FromAddr;
   Tpl->Body += ')';
   CHP = 77007;
   return TRUE;
}

static int AddTearline(Template *Tpl) {
   CHP = 77008;
   Tpl->Body += "--- ";
   CHP = 77009;
   if (Tearline == NULL) {
      CHP = 77010;
      Tpl->Body += "FTrack "FVersion;
      CHP = 77011;
   } else {
      CHP = 77012;
      Tpl->Body += Tearline;
      CHP = 77013;
   }
   CHP = 77014;
   return TRUE;
}

static int AddMsgOrigin(Template *Tpl) {
IndBiList<Kludge>::ElemPtr Klu;
   CHP = 77015;
   Klu = Tpl->From->_Klu.GetFirst();
   CHP = 77016;
   while (Klu != NULL) {
      if (Klu->Name() != NULL) {
         if (stricmp(Klu->Name()," * Origin:") == 0) {
            Tpl->Body += " + Origin: ";
            Tpl->Body += Klu->Body();
            return TRUE;
         }
      }
      Klu++;
   }

   CHP = 77026;
   return TRUE;
}

static int AddMsgTearline(Template *Tpl) {
IndBiList<Kludge>::ElemPtr Klu;

   CHP = 77037;
   Klu = Tpl->From->_Klu.GetFirst();
   while (Klu != NULL) {
      if (Klu->Name() != NULL) {
         if (strcmp(Klu->Name(),"---") == 0) {
            Tpl->Body += "-+-";
            if (Klu->Body() != NULL) {
               Tpl->Body += ' ';
               Tpl->Body += Klu->Body();
            }
            return TRUE;
         }
      }
      Klu++;
   }

   CHP = 77047;
   return TRUE;
}

static int AddMsgNOrigin(Template *Tpl) {
uint i;
   CHP = 77058;
   i = Tpl->Body.Length();
   CHP = 77059;
   AddMsgOrigin(Tpl);
   CHP = 77060;
   if (i == Tpl->Body.Length()) {
      CHP = 77061;
      Tpl->Body += " * Origin: Default FTrack origin. (";
      Tpl->Body += Tpl->From->_FromAddr;
      Tpl->Body += ')';
      CHP = 77062;
   } else {
      CHP = 77063;
      Tpl->Body[i+1] = '*';
   }
   CHP = 77064;
   return TRUE;
}

static int AddMsgNTearline(Template *Tpl) {
uint i;
   CHP = 77065;
   i = Tpl->Body.Length();
   CHP = 77066;
   AddMsgTearline(Tpl);
   CHP = 77067;
   if (i == Tpl->Body.Length()) {
      CHP = 77068;
      Tpl->Body += "--- FTrack "FVersion;
   } else {
      CHP = 77069;
      Tpl->Body[i+1] = '-';
   }
   CHP = 77070;
   return TRUE;
}

static int AddSysop(Template *Tpl) {
   CHP = 77071;
   Tpl->Body += SysopName;
   return TRUE;
}

static int AddFVersion(Template *Tpl) {
   Tpl->Body += FVersion;
   return TRUE;
}

static int AddMaxAge(Template *Tpl) {
   CHP = 77072;
   if (Tpl->sd->_MaxAge != 0) {
      CHP = 77073;
      Tpl->Body += (unsigned)Tpl->sd->_MaxAge;
   } else if (MaxAge != 0) {
      CHP = 77074;
      Tpl->Body += (unsigned)MaxAge;
   } else {
      CHP = 77075;
      Tpl->Body += "NA";
   }
   CHP = 77077;
   return TRUE;
}

static int AddMaxAttachSize(Template *Tpl) {
   CHP = 77078;
   if (Tpl->sd->MaxAttachSize() != 0) {
     Tpl->Body += (unsigned)Tpl->sd->MaxAttachSize();
   } else {
      Tpl->Body += "NA";
   }
   CHP = 77080;
   return TRUE;
}

static int AddMsgAttachSize(Template *Tpl) {
   CHP = 77081;
   if (Tpl->From != NULL) {
      Tpl->Body += (unsigned)Tpl->From->AttachSize();
   } else {
      Tpl->Body += "Unknown";
   }
   CHP = 77083;
   return TRUE;
}

static int AddMsgFlags(Template *Tpl) {
char Buff[512];
   CHP = 77084;
   if (Tpl->From != NULL) {
      Tpl->Body += Tpl->From->FlagsToStr(Buff);
   } else {
      Tpl->Body += "Unknown";
   }
   CHP = 77086;
   return TRUE;
}

static int AddAreaName(Template *Tpl) {
   CHP = 77087;
   if (Tpl->From != NULL && Tpl->From->fEchomail) {
      Tpl->Body += Tpl->From->_AreaName;
   } else {
      Tpl->Body += "Unknown";
   }
   CHP = 77089;
   return TRUE;
}

static int AddSize(Template *Tpl) {
unsigned int sz;
   
   CHP = 77700;
   sz = 0;
   if (Tpl->From != NULL) {
      sz = Tpl->From->Bytes();
   }
   Tpl->Body += sz;
   CHP = 77702;
   return TRUE;
}

static int AddLines(Template *Tpl) {
unsigned int sz;
   
   CHP = 77710;
   sz = 0;
   if (Tpl->From != NULL) {
      sz = Tpl->From->Lines();
   }
   Tpl->Body += sz;
   CHP = 77712;
   return TRUE;
}

static int AddMyAddr(Template *Tpl) {
FA f;
   CHP = 77090;
   if (Tpl->To != NULL) {
      f = GetMyAka(Tpl->To->_ToAddr);
      Tpl->Body += f;
   } else {
      Tpl->Body += MyAddr;
   }
   CHP = 77092;
   return TRUE;
}

static int AddMsgDate(Template *Tpl) {
   CHP = 77093;
   if (Tpl->From != NULL) {
      Tpl->Body += FromTime(Tpl->From->_Time);
   } else {
      Tpl->Body += "Unknown";
   }
   CHP = 77095;
   return TRUE;
}

static int AddDate(Template *Tpl) {
char Buff[128];
time_t t;

   CHP = 77096;
   t = time(NULL);
   strftime(Buff,128,"%d %b %Y %H:%M:%S",localtime(&t));
//   sprintf(Buff,"%s",FromTime(time(NULL)));
   CHP = 77097;
   Tpl->Body += Buff;
   CHP = 77098;
   return TRUE;
}

static int AddMsgAge(Template *Tpl) {
   CHP = 77099;
   if (Tpl->From != NULL) {
      Tpl->Body += AgeIs(Tpl->From->_Time);
   } else {
      Tpl->Body += "Unknown";
   }
   CHP = 77101;
   return TRUE;
}

static int AddMsgLoops(Template *Tpl) {
   CHP = 77102;
   if (Tpl->From != NULL) {
      Tpl->Body += (unsigned) Tpl->From->LoopCount(Tpl->sd->LoopStr());
   } else {
      Tpl->Body += "Unknown";
   }
   CHP = 77104;
   return TRUE;
}

static int AddFromName(Template *Tpl) {
   CHP = 77105;
   if (Tpl->From != NULL) {
      Tpl->Body += Tpl->From->_FromName;
   } else {
      Tpl->Body += "Unknown";
   }
   CHP = 77107;
   return TRUE;
}

static int AddToName(Template *Tpl) {
   CHP = 77108;
   if (Tpl->From != NULL) {
      Tpl->Body += Tpl->From->_ToName;
   } else {
      Tpl->Body += "Unknown";
   }
   CHP = 77110;
   return TRUE;
}

static int AddSubject(Template *Tpl) {
   CHP = 77111;
   if (Tpl->From != NULL) {
      Tpl->Body += Tpl->From->_Subject;
   } else {
      Tpl->Body += "Unknown";
   }
   CHP = 77113;
   return TRUE;
}

static int AddFromAddr(Template *Tpl) {
   CHP = 77114;
   if (Tpl->From != NULL) {
      Tpl->Body += Tpl->From->_FromAddr;
   } else {
      Tpl->Body += "Unknown";
   }
   CHP = 77116;
   return TRUE;
}

static int AddFromZone(Template *Tpl) {
   if (Tpl->From != NULL) {
      Tpl->Body += fatoa(Tpl->From->_FromAddr.Zone());
   } else {
      Tpl->Body += -1;
   }
   return TRUE;
}

static int AddFromNet(Template *Tpl) {

   if (Tpl->From != NULL) {
      Tpl->Body += fatoa(Tpl->From->_FromAddr.Net());
   } else {
      Tpl->Body += -1;
   }
   return TRUE;
}

static int AddFromNode(Template *Tpl) {
   if (Tpl->From != NULL) {
      Tpl->Body += fatoa(Tpl->From->_FromAddr.Node());
   } else {
      Tpl->Body += -1;
   }
   return TRUE;
}

static int AddFromPoint(Template *Tpl) {
   if (Tpl->From != NULL) {
      if (Tpl->From->_FromAddr.Point() & FA_NOTDEF) {
         Tpl->Body += 0;
      } else {
         Tpl->Body += fatoa(Tpl->From->_FromAddr.Point());
      }
   } else {
      Tpl->Body += -1;
   }
   return TRUE;
}


static int AddToAddr(Template *Tpl) {
   CHP = 77117;
   if (Tpl->From != NULL) {
      Tpl->Body += Tpl->From->_ToAddr;
   } else {
      Tpl->Body += "Unknown";
   }
   CHP = 77119;
   return TRUE;
}

static int AddToZone(Template *Tpl) {
   if (Tpl->From != NULL) {
      Tpl->Body += fatoa(Tpl->From->_ToAddr.Zone());
   } else {
      Tpl->Body += -1;
   }
   return TRUE;
}

static int AddToNet(Template *Tpl) {
   if (Tpl->From != NULL) {
      Tpl->Body += fatoa(Tpl->From->_ToAddr.Net());
   } else {
      Tpl->Body += -1;
   }
   return TRUE;
}

static int AddToNode(Template *Tpl) {
   if (Tpl->From != NULL) {
      Tpl->Body += fatoa(Tpl->From->_ToAddr.Node());
   } else {
      Tpl->Body += -1;
   }
   return TRUE;
}

static int AddToPoint(Template *Tpl) {
   if (Tpl->From != NULL) {
      if (Tpl->From->_ToAddr.Point() & FA_NOTDEF) {
         Tpl->Body += 0;
      } else {
         Tpl->Body += fatoa(Tpl->From->_ToAddr.Point());
      }
   } else {
      Tpl->Body += -1;
   }
   return TRUE;
}

static int AddMsgHeader(Template *Tpl) {
   CHP = 77120;
   if (Tpl->From == NULL) {
      Tpl->Body += "Unknown";
      return TRUE;
   }
   CHP = 77121;
   Tpl->Body += "From: "; AddFromName(Tpl);
   Tpl->Body += " (";     AddFromAddr(Tpl); Tpl->Body += ")\n";
   Tpl->Body += "To  : "; AddToName(Tpl);
   Tpl->Body += " (";     AddToAddr(Tpl); Tpl->Body += ")\n";
   Tpl->Body += "Subj: "; AddSubject(Tpl);Tpl->Body += "\n";
   Tpl->Body += "Date: "; AddMsgDate(Tpl);Tpl->Body += "\n";
   Tpl->Body += "Attr: "; AddMsgFlags(Tpl);
   CHP = 77129;
   return TRUE;
}

static int AddMsgBody(Template *Tpl) {
char Buff[128];
char *c;
char LastChr;

   CHP = 77130;
   if (Tpl->From == NULL) {
      Tpl->Body += "Unknown";
      return TRUE;
   }
   CHP = 77132;
   c = Tpl->From->_Body;
   if (c == NULL) {
      return TRUE;
   }
   CHP = 77134;
// Copy body of message and strip 0x0A characters. Fucked shit, 
// even who be reads standards, except for me?
   LastChr = '\0';
   while (*c != '\0') {
      if (*c == '\r') {
         if (LastChr != '\n' && *(c+1) != '\n') {
            Tpl->Body += '\r';
         }
      } else {
         Tpl->Body += *c;
      }
      LastChr = *c;
      c++;
   }
   CHP = 77136;
//   Tpl->Normalise();
   if (Tpl->Body.Length() != 0 && (Tpl->Body[Tpl->Body.Length()-1] == '\n' || Tpl->Body[Tpl->Body.Length()-1] == '\r')) {
      Tpl->Body = Tpl->Body(1,Tpl->Body.Length()-1);
   }
   return TRUE;
}

static void AddInvalidatedKlu(Template *Tpl, Kludge *Klu) {
   if (Klu->Name() != NULL && strlen(Klu->Name()) != 0) {
      if (*Klu->Name() == '\1') {
         Tpl->Body += '@';
         Tpl->Body += (Klu->Name()+1);
      } else if (stricmp(Klu->Name(),"SEEN-BY:") == 0) {
         Tpl->Body += "SEEN+BY:";
      } else if (stricmp(Klu->Name(),"---") == 0) {
         Tpl->Body += "-+-";
      } else if (stricmp(Klu->Name()," * Origin:") == 0) {
         Tpl->Body += "+ Origin:";
      } else {
         Tpl->Body += Klu->Name();
      }
   }
   Tpl->Body += ' ';
   if (Klu->Body() != NULL && strlen(Klu->Body()) != 0) {
      Tpl->Body += Klu->Body();
   }
}   

static int AddMsgKlu(Template *Tpl, IndBiList<Kludge>::ElemPtr Klu, int IsKludge) {
int FirstKlu;

   CHP = 77140;
   FirstKlu = TRUE;
   while (Klu != NULL) {
      if (Klu->Name() != NULL && strlen(Klu->Name()) != 0) { 
         if ((stricmp(Klu->Name(),"---") == 0) 
            || (stricmp(Klu->Name()," * Origin:") == 0)) {
            Klu++;
            continue;
         }
         if ((stricmp(Klu->Name(),"SEEN-BY:") == 0)
            || (stricmp(Klu->Name(),"\1VIA") == 0)
            || (stricmp(Klu->Name(),"\1Recd") == 0)
            || (stricmp(Klu->Name(),"\1Forwarded") == 0)
            || (stricmp(Klu->Name(),"\1PATH:") == 0)) {
            if (IsKludge != TRUE) {
               if (FirstKlu != TRUE) Tpl->Body += '\n';
               AddInvalidatedKlu(Tpl, Klu);
               FirstKlu = FALSE;
            } else {
               Klu++;
               continue;
            }

         } else {
            if (IsKludge == TRUE) {
               if (FirstKlu != TRUE) Tpl->Body += '\n';
               AddInvalidatedKlu(Tpl, Klu);
               FirstKlu = FALSE;
            } else {
               Klu++;
               continue;
            }
         }
      }
      Klu++;
   }
   CHP = 77160;
   return TRUE;
}

static int AddMsgKludges(Template *Tpl) {
   CHP = 77161;
   return AddMsgKlu(Tpl,Tpl->From->_Klu.GetFirst(),TRUE);
}

static int AddMsgVias(Template *Tpl) {
   CHP = 77161;
   return AddMsgKlu(Tpl,Tpl->From->_Klu.GetFirst(),FALSE);
}

static int AddRoutedVia(Template *Tpl) {
   CHP = 77163;
   if (Tpl->From != NULL) {
      Tpl->Body += Tpl->From->_RoutedVia;
   } else {
      Tpl->Body += "Unknown";
   }
   CHP = 77165;
   return TRUE;
}

static int AddSomeKludge(Template *Tpl,char *Klud) {
IndBiList<Kludge>::ElemPtr Klu;

   CHP = 77166;
   Klu = Tpl->From->_Klu.GetFirst();
   CHP = 77167;
   while (Klu != NULL) {
      if (Klu->Name() != NULL) {
         if (stricmp(Klu->Name(),Klud) == 0) {
            Tpl->Body += (Klu->Body() != NULL ? Klu->Body() : "Unknown");
            return TRUE;
         }
      }
      Klu++;
   }
   Tpl->Body += "Unknown";
   CHP = 77169;
   return TRUE;
}


char *StrAsTpl(cMSG &m, char *s) {
char *tmt;
Template *tpl;

   tpl = new Template();
   tpl->SetMsg(m);
   tpl->LastTplLine = strdup(s);
   tpl->ParseOneLine();
   tmt = strdup(tpl->Body);
   delete tpl;
   return tmt;
}



static int AddMsgId(Template *Tpl) {
   return AddSomeKludge(Tpl,"\1MSGID:");
}

static int AddMsgReply(Template *Tpl) {
   return AddSomeKludge(Tpl,"\1REPLY:");
}


static int AddNewMsgId(Template *Tpl) {
char Buff[50];
   sprintf(Buff,"%08lx",MsgID());
   Tpl->Body += Buff;
   return TRUE;
}
// --------------------------------------------------------------------

Template::Template() {
   CHP = 77170;
   TplName = NULL;
   LastTplLine = NULL;
   fh = NULL;
   MaxBodySize = 0;
   From = NULL;
   To = NULL;
   FName = NULL;
}

Template::~Template() {
   CHP = 77180;
   if (TplName != NULL) {
      free(TplName);
      TplName = NULL;
   }
   if (LastTplLine != NULL) {
      free(LastTplLine);
      LastTplLine = NULL;
   }
   if (fh != NULL) {
      fclose(fh);
      fh = NULL;
   }
   if (FName != NULL) {
      free(FName);
      FName = NULL;
   }
}

int Template::Set(char *c) {
   CHP = 77190;
   if (access(c,R_OK) != 0) {
      return FALSE;
   }
   TplName = strdup(c);
   return TRUE;
}

// --------------------------------------------------------------------

int Template::GetOneLine (void) {
   CHP = 77200;
   if (fgets(LastTplLine,MAXCFGLINE,fh) == NULL) {
      return FALSE;
   }
   CHP = 77201;
// Strip end of line
//   tmt = strrchr(LastTplLine,'\n');
//   if (tmt != NULL) *tmt = '\0';
//   tmt = strrchr(LastTplLine,'\r');
//   if (tmt != NULL) *tmt = '\0';
   return TRUE;
}

// --------------------------------------------------------------------


int Template::AddTok(char *T) {
TplTok *Tok;
   CHP = 77211;
   Tok = TemplTokens;
   while (Tok->Token != 0) {
      if (stricmp(Tok->Token,T) == 0) {
         return (Tok->Func(this));
      }
      Tok++;
   }
   CHP = 77221;
   if (Tok->Token == 0) {
      Body += '@';
      Body += T;
   }
   CHP = 77224;
   return (TRUE);
}

int Template::ParseOneLine (void) {
// get string from Template file.
// parse @f as template word
char *tmt, *tmt2;
char Tok[MAXCFGLINE];

   CHP = 77225;
   tmt = LastTplLine;
   while(*tmt != '\0') {
      if (*tmt == '@') {
         tmt++;
         if (*tmt == '@') {
            Body += *tmt++;
            continue;
         }
         tmt2 = Tok;
         while(isalpha((uchar)*tmt)) {
            *tmt2++ = *tmt++;
         }
         *tmt2 = '\0';
         if (!AddTok(Tok)) return FALSE;
      } else {
         Body += *tmt++;
      }
   }
   CHP = 77245;
   return TRUE;
}


// --------------------------------------------------------------------

void Template::Normalise(void) {
char *tmt;

   CHP = 77248;

// First - replace all \r to \n

   while ((tmt = strchr((char *) Body,'\r')) != NULL) {
      *tmt = '\n';
   }

   CHP = 77250;

}

// --------------------------------------------------------------------

int Template::Parse(void) {
   CHP = 77260;
   if (TplName == NULL) {
      Log.Level(LOGE) << "Template file not set" << EOL;
      return FALSE;
   }
   CHP = 77264;
   if (access(TplName,R_OK) != 0) {
      Log.Level(LOGE) << "Template file '" << TplName << "' is not exists." << EOL;
      return FALSE;
   }
   CHP = 77268;
   fh = fopen(TplName,"rt");
   if (fh == 0) {
      Log.Level(LOGE) << "Unable to open template file '" << TplName << "'" << EOL;
      return FALSE;
   }

   CHP = 77272;
   LastTplLine = (char *)malloc(MAXCFGLINE);
   CheckMem(LastTplLine);
   while (GetOneLine()) {
      if (!ParseOneLine()) {
         fclose (fh);
         fh = NULL;
         return FALSE;
      }
   }
   CHP = 77276;
   if (!feof(fh)) {
      Log.Level(LOGE) << "Error reading template file '" << TplName << "'" << EOL;
      fclose (fh);
      fh = NULL;
      return FALSE;
   }
   CHP = 77280;
   fclose (fh);
   fh = NULL;
   CHP = 77284;
   Normalise();
   CHP = 77288;
   return TRUE;
}
// --------------------------------------------------------------------
int Template::Save(char *Name, int Mode) {
   CHP = 77292;
   if (Mode == 1) {
      CHP = 77293;
      fh = fopen(Name,"w+t");
      if (fh == NULL) {
         Log.Level(LOGE) << "Unable to create file '" << Name << "'" << EOL;
         return FALSE;
      }
   } else {
      CHP = 77297;
      fh = fopen(Name,"a+t");
      if (fh == NULL) {
         Log.Level(LOGE) << "Unable to append to file '" << Name << "'" << EOL;
         return FALSE;
      }
   }
   CHP = 77301;
   if (fputs(Body,fh) == EOF) {
      Log.Level(LOGE) << "Unable to write to file '" << Name << "'" << EOL;
      fclose(fh);
      fh = NULL;
      return FALSE;
   }
   CHP = 77304;
   fclose(fh);
   fh = NULL;
   CHP = 77308;
   return TRUE;
}

int Template::Save(cMSG &m) {
char *tmt;
   CHP = 77312;
   m.SetBody(Body,strlen(Body));
   CHP = 77314;
   while ((tmt = strchr(m.Body(),'\n')) != NULL) *tmt = '\r';
   CHP = 77316;
   return TRUE;
}

// --------------------------------------------------------------------
void Template::Clean(void) {
   Body = "";
}
// ---------------------------- END --------------------------------------



syntax highlighted by Code2HTML, v. 0.9.1