home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 2 BBS / 02-BBS.zip / lora299s.zip / MAILWIN.CPP < prev    next >
C/C++ Source or Header  |  1998-05-12  |  49KB  |  1,389 lines

  1.  
  2. // LoraBBS Version 2.99 Free Edition
  3. // Copyright (C) 1987-98 Marco Maccaferri
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation; either version 2 of the License, or
  8. // (at your option) any later version.
  9. //
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software
  17. // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  
  19. #include "_ldefs.h"
  20. #include "msgbase.h"
  21. #include "lorawin.h"
  22.  
  23. PSZ Exts[] = { "su0", "mo0", "tu0", "we0", "th0", "fr0", "sa0", NULL };
  24.  
  25. // ----------------------------------------------------------------------------
  26. // Mail processor output filter
  27. // ----------------------------------------------------------------------------
  28.  
  29. #if defined(__OS2__) || defined(__NT__)
  30. TPMList::TPMList (HWND hwnd)
  31. {
  32.    time_t t;
  33.    struct tm *ltm;
  34.  
  35.    fp = NULL;
  36.    hwndList = hwnd;
  37.  
  38.    if (Cfg->MakeProcessLog == TRUE) {
  39.       if ((fp = fopen ("process.log", "at")) != NULL) {
  40.          t = time (NULL);
  41.          ltm = localtime (&t);
  42.          fprintf (fp, "\nProcessing date/time: %s", asctime (ltm));
  43.          fprintf (fp, "-------------------------------------------------------------------------------\n");
  44.       }
  45.    }
  46.  
  47.    DoWrite = FALSE;
  48. }
  49. #elif defined(__LINUX__) || defined(__DOS__)
  50. TPMList::TPMList (void)
  51. {
  52.    time_t t;
  53.    struct tm *ltm;
  54.  
  55.    fp = NULL;
  56.    window = wopen (13, 1, 20, 78, 5, LGREY|_BLACK, LCYAN|_BLACK);
  57.    First = TRUE;
  58.  
  59.    if (Cfg->MakeProcessLog == TRUE) {
  60.       if ((fp = fopen ("process.log", "at")) != NULL) {
  61.          t = time (NULL);
  62.          ltm = localtime (&t);
  63.          fprintf (fp, "\nProcessing date/time: %s", asctime (ltm));
  64.          fprintf (fp, "-------------------------------------------------------------------------------\n");
  65.       }
  66.    }
  67.  
  68.    DoWrite = FALSE;
  69. }
  70. #endif
  71.  
  72. TPMList::~TPMList (void)
  73. {
  74. #if defined(__DOS__) || defined(__LINUX__)
  75.    if (window != 0) {
  76.       wactiv (window);
  77.       wclose ();
  78.    }
  79. #endif
  80.    if (fp != NULL && Cfg->MakeProcessLog == TRUE) {
  81.       if (DoWrite == TRUE) {
  82.          fprintf (fp, "%s\n", Line);
  83.          DoWrite = FALSE;
  84.       }
  85.       fprintf (fp, "-------------------------------------------------------------------------------\n");
  86.       fclose (fp);
  87.    }
  88. }
  89.  
  90. VOID TPMList::Add (PSZ Text)
  91. {
  92. #if defined(__OS2__)
  93.    WinSendMsg (hwndList, WM_USER, MPFROMSHORT (WMU_ADDOUTBOUNDLINE), MPFROMP (Text));
  94. #elif defined(__NT__)
  95.    SendMessage (hwndList, WM_USER, (WPARAM)WMU_ADDOUTBOUNDLINE, (LPARAM)Text);
  96. #elif defined(__LINUX__) || defined(__DOS__)
  97.    if (window != 0) {
  98.       wactiv (window);
  99.       if (First == TRUE) {
  100.          wprintf ("%.78s", Text);
  101.          First = FALSE;
  102.       }
  103.       else
  104.          wprintf ("\n%.78s", Text);
  105.       videoupdate ();
  106.    }
  107. #endif
  108.    if (fp != NULL && Cfg->MakeProcessLog == TRUE) {
  109.       if (DoWrite == TRUE) {
  110.          fprintf (fp, "%s\n", Line);
  111.          DoWrite = FALSE;
  112.       }
  113.       strcpy (Line, Text);
  114.       DoWrite = TRUE;
  115.    }
  116. }
  117.  
  118. VOID TPMList::Update (PSZ Text)
  119. {
  120. #if defined(__OS2__)
  121.    WinSendMsg (hwndList, WM_USER, MPFROMSHORT (WMU_REPLACEOUTBOUNDLINE), MPFROMP (Text));
  122. #elif defined(__NT__)
  123.    SendMessage (hwndList, WM_USER, (WPARAM)WMU_REPLACEOUTBOUNDLINE, (LPARAM)Text);
  124. #elif defined(__DOS__) || defined(__LINUX__)
  125.    if (window != 0) {
  126.       wactiv (window);
  127.       wprintf ("\r%.78s", Text);
  128.       videoupdate ();
  129.    }
  130. #endif
  131.    if (fp != NULL && Cfg->MakeProcessLog == TRUE) {
  132.       strcpy (Line, Text);
  133.       DoWrite = TRUE;
  134.    }
  135. }
  136.  
  137. VOID TPMList::Clear (VOID)
  138. {
  139. #if defined(__OS2__)
  140.    WinSendMsg (hwndList, WM_USER, MPFROMSHORT (WMU_CLEAROUTBOUND), 0L);
  141. #elif defined(__NT__)
  142.    SendMessage (hwndList, WM_USER, (WPARAM)WMU_CLEAROUTBOUND, 0L);
  143. #elif defined(__DOS__) || defined(__LINUX__)
  144.    if (window != 0) {
  145.       wactiv (window);
  146.       wclear ();
  147.       videoupdate ();
  148.       First = TRUE;
  149.    }
  150. #endif
  151. }
  152.  
  153. // ----------------------------------------------------------------------------
  154. // Mail kludges
  155. // ----------------------------------------------------------------------------
  156.  
  157. TKludges::TKludges (void)
  158. {
  159.    Data.Clear ();
  160.    Sort = TRUE;
  161. }
  162.  
  163. TKludges::~TKludges (void)
  164. {
  165.    Data.Clear ();
  166. }
  167.  
  168. USHORT TKludges::Add (VOID)
  169. {
  170.    USHORT Insert = FALSE;
  171.    CHAR Temp[64];
  172.    KLUDGES Buffer, *Current;
  173.  
  174.    sprintf (Temp, "%u:%u/%u.%u", Zone, Net, Node, Point);
  175.  
  176.    if (Check (Temp) == FALSE) {
  177.       memset (&Buffer, 0, sizeof (KLUDGES));
  178.  
  179.       Buffer.Zone = Zone;
  180.       Buffer.Net = Net;
  181.       Buffer.Node = Node;
  182.       Buffer.Point = Point;
  183.  
  184.       if (Sort == TRUE) {
  185.          if ((Current = (KLUDGES *)Data.First ()) != NULL) {
  186.             if (Current->Net > Net)
  187.                Insert = TRUE;
  188.             else if (Current->Net == Net && Current->Node > Node)
  189.                Insert = TRUE;
  190.             else if (Current->Net == Net && Current->Node == Node && Current->Point > Point)
  191.                Insert = TRUE;
  192.  
  193.             if (Insert == TRUE) {
  194.                Data.Insert (&Buffer, sizeof (KLUDGES));
  195.                Data.Insert (Current, sizeof (KLUDGES));
  196.                Data.First ();
  197.                Data.Remove ();
  198.                Data.First ();
  199.             }
  200.             else {
  201.                while ((Current = (KLUDGES *)Data.Next ()) != NULL) {
  202.                   if (Current->Net > Net)
  203.                      Insert = TRUE;
  204.                   else if (Current->Net == Net && Current->Node > Node)
  205.                      Insert = TRUE;
  206.                   else if (Current->Net == Net && Current->Node == Node && Current->Point > Point)
  207.                      Insert = TRUE;
  208.  
  209.                   if (Insert == TRUE) {
  210.                      Data.Previous ();
  211.                      Data.Insert (&Buffer, sizeof (KLUDGES));
  212.                      break;
  213.                   }
  214.                }
  215.                if (Insert == FALSE) {
  216.                   Data.Add (&Buffer, sizeof (KLUDGES));
  217.                   Insert = TRUE;
  218.                }
  219.             }
  220.          }
  221.          else {
  222.             if (Insert == FALSE) {
  223.                Data.Add (&Buffer, sizeof (KLUDGES));
  224.                Insert = TRUE;
  225.             }
  226.          }
  227.       }
  228.       else
  229.          Data.Add (&Buffer, sizeof (KLUDGES));
  230.    }
  231.  
  232.    return (Insert);
  233. }
  234.  
  235. USHORT TKludges::AddString (PSZ pszString)
  236. {
  237.    USHORT RetVal = FALSE;
  238.    CHAR Temp[128], *p;
  239.    class TAddress Address;
  240.  
  241.    strcpy (Temp, pszString);
  242.    if ((p = strtok (Temp, " ")) != NULL)
  243.       do {
  244.          if (Check (p) == FALSE) {
  245.             Address.Parse (p);
  246.             Zone = Address.Zone;
  247.             if (Address.Net != 0)
  248.                Net = Address.Net;
  249.             if (Address.Node != 0)
  250.                Node = Address.Node;
  251.             Point = Address.Point;
  252.             RetVal = Add ();
  253.          }
  254.       } while ((p = strtok (NULL, " ")) != NULL);
  255.  
  256.    return (RetVal);
  257. }
  258.  
  259. USHORT TKludges::Check (PSZ pszAddress)
  260. {
  261.    USHORT RetVal = FALSE;
  262.    KLUDGES *El;
  263.    class TAddress Addr;
  264.  
  265.    Addr.Parse (pszAddress);
  266.  
  267.    if ((El = (KLUDGES *)Data.First ()) != NULL)
  268.       do {
  269.          if (El->Net == Addr.Net && El->Node == Addr.Node && El->Point == Addr.Point) {
  270.             Zone = El->Zone;
  271.             Net = El->Net;
  272.             Node = El->Node;
  273.             Point = El->Point;
  274.             sprintf (Address, "%u/%u", Net, Node);
  275.             RetVal = TRUE;
  276.             break;
  277.          }
  278.       } while ((El = (KLUDGES *)Data.Next ()) != NULL);
  279.  
  280.    return (RetVal);
  281. }
  282.  
  283. VOID TKludges::Clear (VOID)
  284. {
  285.    Data.Clear ();
  286.    New ();
  287. }
  288.  
  289. VOID TKludges::Delete (VOID)
  290. {
  291.    if (Data.Value () != NULL)
  292.       Data.Remove ();
  293. }
  294.  
  295. USHORT TKludges::First (VOID)
  296. {
  297.    USHORT RetVal = FALSE;
  298.    KLUDGES *El;
  299.  
  300.    if ((El = (KLUDGES *)Data.First ()) != NULL) {
  301.       Zone = El->Zone;
  302.       Net = El->Net;
  303.       Node = El->Node;
  304.       Point = El->Point;
  305.       if (Point != 0)
  306.          sprintf (Address, "%u/%u.%u", Net, Node, Point);
  307.       else
  308.          sprintf (Address, "%u/%u", Net, Node);
  309.       strcpy (ShortAddress, Address);
  310.       RetVal = TRUE;
  311.    }
  312.  
  313.    return (RetVal);
  314. }
  315.  
  316. VOID TKludges::New (VOID)
  317. {
  318.    Zone = 0;
  319.    Net = 0;
  320.    Node = 0;
  321.    Point = 0;
  322. }
  323.  
  324. USHORT TKludges::Next (VOID)
  325. {
  326.    USHORT RetVal = FALSE;
  327.    KLUDGES *El;
  328.  
  329.    if ((El = (KLUDGES *)Data.Next ()) != NULL) {
  330.       if (Net != El->Net) {
  331.          if (El->Point != 0)
  332.             sprintf (ShortAddress, "%u/%u.%u", El->Net, El->Node, El->Point);
  333.          else
  334.             sprintf (ShortAddress, "%u/%u", El->Net, El->Node);
  335.       }
  336.       else {
  337.          if (Node == El->Node && El->Point != 0)
  338.             sprintf (ShortAddress, ".%u", El->Point);
  339.          else {
  340.             if (El->Point != 0)
  341.                sprintf (ShortAddress, "%u.%u", El->Point);
  342.             else
  343.                sprintf (ShortAddress, "%u", El->Node);
  344.          }
  345.       }
  346.  
  347.       Zone = El->Zone;
  348.       Net = El->Net;
  349.       Node = El->Node;
  350.       Point = El->Point;
  351.       if (Point != 0)
  352.          sprintf (Address, "%u/%u.%u", Net, Node, Point);
  353.       else
  354.          sprintf (Address, "%u/%u", Net, Node);
  355.       RetVal = TRUE;
  356.    }
  357.  
  358.    return (RetVal);
  359. }
  360.  
  361. // ----------------------------------------------------------------------------
  362. // Mail processor
  363. // ----------------------------------------------------------------------------
  364.  
  365. TMailProcessor::TMailProcessor (void)
  366. {
  367.    Output = NULL;
  368.    Status = NULL;
  369.    Packets = 0;
  370.    Bad = Duplicate = NetMail = MsgTossed = 0L;
  371. }
  372.  
  373. TMailProcessor::~TMailProcessor (void)
  374. {
  375. }
  376.  
  377. VOID TMailProcessor::MakeArcMailName (PSZ pszAddress, CHAR Flag)
  378. {
  379.    USHORT i, Found;
  380.    CHAR *p;
  381.    ULONG Crc32;
  382.    class TAddress Addr;
  383.    class TOutbound *Out;
  384.    struct stat statbuf;
  385.    struct dosdate_t d_date;
  386.  
  387.    _dos_getdate (&d_date);
  388.  
  389.    Addr.Parse (pszAddress);
  390.    Crc32 = StringCrc32 (Cfg->MailAddress.String, 0xFFFFFFFFL);
  391.    Crc32 = StringCrc32 (Addr.String, Crc32);
  392.  
  393.    if (Addr.Zone == 0 || Cfg->MailAddress.Zone == Addr.Zone) {
  394.       if (Addr.Point != 0)
  395.          sprintf (ArcMailName, "%s\\%04x%04x.pnt\\%08lx.%s", Outbound, Addr.Net, Addr.Node, Crc32, Exts[d_date.dayofweek]);
  396.       else
  397.          sprintf (ArcMailName, "%s\\%08lx.%s", Outbound, Crc32, Exts[d_date.dayofweek]);
  398.    }
  399.    else {
  400.       if (Addr.Point != 0)
  401.          sprintf (ArcMailName, "%s.%03x\\%04x%04x.pnt\\%08lx.%s", Outbound, Addr.Zone, Addr.Net, Addr.Node, Crc32, Exts[d_date.dayofweek]);
  402.       else
  403.          sprintf (ArcMailName, "%s.%03x\\%08lx.%s", Outbound, Addr.Zone, Crc32, Exts[d_date.dayofweek]);
  404.    }
  405.  
  406.    AdjustPath (ArcMailName);
  407.  
  408.    Found = FALSE;
  409.    if ((p = strchr (ArcMailName, '\0')) != NULL) {
  410.       p--;
  411.       for (i = '0'; i <= '9' && Found == FALSE; i++) {
  412.          *p = (CHAR)i;
  413.          if (stat (ArcMailName, &statbuf) == 0) {
  414.             Found = TRUE;
  415.             if (statbuf.st_size == 0L) {
  416.                unlink (ArcMailName);
  417.                if (++i > '9')
  418.                   i = '0';
  419.                *p = (CHAR)i;
  420.             }
  421.          }
  422.       }
  423.       if (Found == FALSE)
  424.          *p = '0';
  425.    }
  426.  
  427.    if ((Out = new TOutbound (Cfg->Outbound)) != NULL) {
  428.       if (Cfg->MailAddress.First () == TRUE)
  429.          Out->DefaultZone = Cfg->MailAddress.Zone;
  430.       Found = FALSE;
  431.       Out->Add (Addr.Zone, Addr.Net, Addr.Node, Addr.Point, Addr.Domain);
  432.       if (Out->First () == TRUE)
  433.          do {
  434.             if (!stricmp (Out->Complete, ArcMailName)) {
  435.                Found = TRUE;
  436.                break;
  437.             }
  438.          } while (Out->Next () == TRUE);
  439.  
  440.       if (Found == FALSE) {
  441.          Out->New ();
  442.          Out->Zone = Addr.Zone;
  443.          Out->Net = Addr.Net;
  444.          Out->Node = Addr.Node;
  445.          Out->Point = Addr.Point;
  446.          strcpy (Out->Domain, Addr.Domain);
  447.          strcpy (Out->Name, &ArcMailName[strlen (ArcMailName) - 12]);
  448.          strcpy (Out->Complete, ArcMailName);
  449.          Out->Status = Flag;
  450.          Out->ArcMail = TRUE;
  451.          Out->TruncateAfter = TRUE;
  452.          Out->Add ();
  453.          Out->Update ();
  454.       }
  455.  
  456.       delete Out;
  457.    }
  458. }
  459.  
  460. VOID TMailProcessor::News (VOID)
  461. {
  462.    CHAR *Base;
  463.    ULONG Number, Tossed, SentArea, Msgn;
  464.    class USENET *Usenet;
  465.    class TUser *User;
  466.    class TEchotoss *EchoToss;
  467.  
  468.    if (Output != NULL)
  469.       Output->Clear ();
  470.    if (Log != NULL)
  471.       Log->Write ("+Processing NEWSgroups");
  472.  
  473.    MsgTossed = MsgSent = 0L;
  474.  
  475.    if ((Data = new TMsgData (Cfg->SystemPath)) != NULL) {
  476.       if (Data->First () == TRUE)
  477.          do {
  478.             if (Data->Storage != ST_USENET && Data->Storage != ST_PASSTHROUGH && Data->NewsGroup[0] != '\0' && Data->UpdateNews == TRUE) {
  479.                if (Data->Storage == ST_JAM) {
  480.                   Msg = new JAM (Data->Path);
  481.                   Base = "JAM";
  482.                }
  483.                else if (Data->Storage == ST_SQUISH) {
  484.                   Msg = new SQUISH (Data->Path);
  485.                   Base = "Squish<tm>";
  486.                }
  487.                else if (Data->Storage == ST_FIDO) {
  488.                   Msg = new FIDOSDM (Data->Path);
  489.                   Base = "Fido *.MSG";
  490.                }
  491.                else if (Data->Storage == ST_ADEPT) {
  492.                   Msg = new ADEPT (Data->Path);
  493.                   Base = "AdeptXBBS";
  494.                }
  495.                else if (Data->Storage == ST_HUDSON) {
  496.                   Msg = new HUDSON (Data->Path, (UCHAR)Data->Board);
  497.                   Base = "Hudson";
  498.                }
  499.  
  500.                if (Msg != NULL) {
  501.                   if (Status != NULL) {
  502.                      Status->Clear ();
  503.                      Status->SetLine (0, "Processing %s ", Data->NewsGroup);
  504.                   }
  505.  
  506.                   if ((Usenet = new USENET (Cfg->NewsServer, Data->NewsGroup)) != NULL) {
  507.                      strcpy (Usenet->HostName, Cfg->HostName);
  508.                      strcpy (Usenet->Organization, Cfg->SystemName);
  509.                      sprintf (Usenet->ProgramID, "%s Version %s", NAME, VERSION);
  510.  
  511.                      if (Status != NULL)
  512.                         Status->SetLine (0, "Sending messages to %s", Data->NewsGroup);
  513.  
  514.                      Msg->Lock (0L);
  515.                      Number = 0L;
  516.                      if (Data->NewsHWM < Msg->Highest ())
  517.                         Number = Data->NewsHWM;
  518.                      SentArea = 0L;
  519.  
  520.                      if (Msg->Next (Number) == TRUE)
  521.                         do {
  522.                            if (Msg->Read (Number, MAX_LINE_LENGTH) == TRUE) {
  523.                               Msgn = Msg->UidToMsgn (Number);
  524.                               if (Status != NULL && (Msgn % 10) == 0L)
  525.                                  Status->SetLine (1, "   %lu / %lu", Msgn, Msg->Number ());
  526.  
  527.                               if (Msg->Sent == FALSE) {
  528.                                  if (Status != NULL && (Msgn % 10) != 0L)
  529.                                     Status->SetLine (1, "   %lu / %lu", Msgn, Msg->Number ());
  530.                                  strcpy (Usenet->User, "anonymous");
  531.                                  if (Msg->Local == TRUE) {
  532.                                     if ((User = new TUser (Cfg->UserFile)) != NULL) {
  533.                                        if (User->GetData (Msg->From) == TRUE)
  534.                                           strcpy (Usenet->User, User->MailBox);
  535.                                        delete User;
  536.                                     }
  537.                                  }
  538.                                  if (Usenet->Add (Msg) == TRUE) {
  539.                                     Msg->Delete (Number);
  540.                                     SentArea++;
  541.                                     MsgSent++;
  542.                                  }
  543.                                  else if (Log != NULL) {
  544.                                     Log->Write (":Sending msg# %lu in %s", Number, Data->NewsGroup);
  545.                                     Log->Write ("!Server error: %s", Usenet->Error);
  546.                                  }
  547.                               }
  548.                            }
  549.                         } while (Msg->Next (Number) == TRUE);
  550.  
  551.                      Msg->UnLock ();
  552.  
  553.                      // Aggiorna subito l'high water mark per le aree newsgroup
  554.                      Data->NewsHWM = Number;
  555.                      Data->Update ();
  556.  
  557.                      Tossed = 0L;
  558.                      Number = Data->Highest;
  559.                      // Se e' stato impostato un limite di messaggi si assicura di ricevere gli ultimi n messaggi
  560.                      if (Cfg->RetriveMaxMessages != 0 && (Usenet->Highest () - Number) > Cfg->RetriveMaxMessages)
  561.                         Number = Usenet->Highest () - Cfg->RetriveMaxMessages;
  562.  
  563.                      if (Status != NULL) {
  564.                         Status->Clear ();
  565.                         Status->SetLine (0, "Receiving message from %s (%lu msgs)", Data->NewsGroup, Usenet->Number ());
  566.                      }
  567.  
  568.                      while (Usenet->Next (Number) == TRUE) {
  569.                         if (Status != NULL)
  570.                            Status->SetLine (1, "   %lu / %lu", Usenet->UidToMsgn (Number), Usenet->UidToMsgn (Usenet->Highest ()));
  571.                         if (Output != NULL) {
  572.                            sprintf (Display, "%6lu %-32.32s", Usenet->UidToMsgn (Number), Data->NewsGroup);
  573.                            Output->Add (Display);
  574.                         }
  575.                         if (Usenet->Read (Number, MAX_LINE_LENGTH) == TRUE) {
  576.                            Usenet->Sent = TRUE;
  577.                            Msg->Add (Usenet);
  578.                            if (Output != NULL) {
  579.                               sprintf (Display, "%6lu %-32.32s %-12.12s %6lu", Usenet->UidToMsgn (Number), Data->NewsGroup, Base, Msg->UidToMsgn (Msg->Highest ()));
  580.                               Output->Update (Display);
  581.                            }
  582.                            Tossed++;
  583.                            MsgTossed++;
  584.                            //////////////////////////////////////////////////////////////////////////////////////////////////
  585.                            // Verifica il raggiungimento del limite di messaggi da ricevere in una volta sola              //
  586.                            //////////////////////////////////////////////////////////////////////////////////////////////////
  587.                            if (Cfg->RetriveMaxMessages != 0 && Tossed >= Cfg->RetriveMaxMessages)
  588.                               break;
  589.                         }
  590.                      }
  591.  
  592.                      Data->Highest = Number;
  593.  
  594.                      if (Log != NULL && (Tossed != 0L || SentArea != 0L)) {
  595.                         Log->Write (":   %-20.20s (Toss=%04d,Sent=%04lu)", Data->NewsGroup, Tossed, SentArea);
  596.                         if ((EchoToss = new TEchotoss (Cfg->SystemPath)) != NULL) {
  597.                            EchoToss->Load ();
  598.                            if (Data->EchoTag[0] != '\0')
  599.                               EchoToss->Add (Data->EchoTag);
  600.                            EchoToss->Save ();
  601.                            delete EchoToss;
  602.                         }
  603.                      }
  604.  
  605.                      delete Usenet;
  606.  
  607.                      Data->ActiveMsgs = Msg->Number ();
  608.                      Data->Update ();
  609.                   }
  610.                   delete Msg;
  611.                   Msg = NULL;
  612.                }
  613.             }
  614.          } while (Data->Next () == TRUE);
  615.  
  616.       delete Data;
  617.    }
  618. }
  619.  
  620. VOID TMailProcessor::Mail (VOID)
  621. {
  622.    CHAR Host[128], Name[32], *p, ToUs;
  623.    ULONG Number, Msgn;
  624.    class TUser *User;
  625.    class INETMAIL *Mail;
  626.    class TAddress Addr;
  627.    class TMsgBase *EMail;
  628.  
  629.    if (Status != NULL)
  630.       Status->Clear ();
  631.    if (Log != NULL)
  632.       Log->Write ("+Processing Internet Mail");
  633.  
  634.    MsgSent = MsgTossed = 0L;
  635.  
  636. #if !defined(__POINT__)
  637.    if (stricmp (Cfg->MailPath, Cfg->NetMailPath)) {
  638.       Msg = NULL;
  639.       if (Cfg->MailStorage == ST_JAM)
  640.          Msg = new JAM (Cfg->MailPath);
  641.       else if (Cfg->MailStorage == ST_SQUISH)
  642.          Msg = new SQUISH (Cfg->MailPath);
  643.       else if (Cfg->MailStorage == ST_FIDO)
  644.          Msg = new FIDOSDM (Cfg->MailPath);
  645.       else if (Cfg->MailStorage == ST_ADEPT)
  646.          Msg = new ADEPT (Cfg->MailPath);
  647.       else if (Cfg->MailStorage == ST_HUDSON)
  648.          Msg = new HUDSON (Cfg->HudsonPath, (UCHAR)Cfg->MailBoard);
  649.  
  650.       if ((Mail = new INETMAIL) != NULL) {
  651.          strcpy (Mail->SMTPHostName, Cfg->MailServer);
  652.          if (Status != NULL) {
  653.             sprintf (Temp, "Sending e-mail to %s", Mail->SMTPHostName);
  654.             Status->SetLine (0, Temp);
  655.          }
  656.          Number = Msg->Lowest ();
  657.          do {
  658.             if (Msg->ReadHeader (Number) == TRUE) {
  659.                Msgn = Msg->UidToMsgn (Number);
  660.                if (Status != NULL && (Msgn % 10) == 0L)
  661.                   Status->SetLine (1, "   %lu / %lu", Msgn, Msg->Number ());
  662.                if (Msg->Sent == FALSE && strchr (Msg->To, '@') != NULL) {
  663.                   Msg->Read (Number);
  664.                   if (Status != NULL && (Msgn % 10) != 0L)
  665.                      Status->SetLine (1, "   %lu / %lu", Msgn, Msg->Number ());
  666.  
  667.                   // Verifica se la prima riga del testo del messaggio contiene il kludge
  668.                   // To: per specificare l'indirizzo internet di destinazione.
  669.                   if ((p = (CHAR *)Msg->Text.First ()) != NULL) {
  670.                      strcpy (Host, p);
  671.                      if (!strncmp (strlwr (Host), "to:", 3)) {
  672.                         p += 3;
  673.                         while (*p == ' ')
  674.                            p++;
  675.                         strcpy (Msg->To, p);
  676.                         // La riga con il kludge viene tolta.
  677.                         Msg->Text.Remove ();
  678.                         // Verifica se la riga sucessiva e' vuota, nel qual caso toglie anche quella.
  679.                         if ((p = (CHAR *)Msg->Text.First ()) != NULL) {
  680.                            if (*p == '\0')
  681.                               Msg->Text.Remove ();
  682.                         }
  683.                      }
  684.                   }
  685.  
  686.                   // Scrive qualche informazione sul log.
  687.                   if (Log != NULL) {
  688.                      Log->Write (":  Msg#: %lu", Msg->UidToMsgn (Number));
  689.                      Log->Write (":    Fm: %s", Msg->From);
  690.                      Log->Write (":    To: %s", Msg->To);
  691.                      Log->Write (":    Sb: %s", Msg->Subject);
  692.                   }
  693.  
  694.                   if (Msg->Local == TRUE) {
  695.                      // Nel caso di messaggi locali viene impostato di default un indirizzo
  696.                      // di ritorno di convenienza per il nostro host.
  697.                      sprintf (Msg->FromAddress, "anonymous@%s", Cfg->HostName);
  698.                      if ((User = new TUser (Cfg->UserFile)) != NULL) {
  699.                         if (User->GetData (Msg->From, FALSE) == TRUE) {
  700.                            // Se l'utente ha un indirizzo e-mail proprio, viene usato quello come
  701.                            // indirizzo di ritorno, altrimenti viene usata la sua mailbox presso
  702.                            // il nostro host.
  703.                            if (User->UseInetAddress == TRUE && User->InetAddress[0] != '\0')
  704.                               strcpy (Msg->FromAddress, User->InetAddress);
  705.                            else
  706.                               sprintf (Msg->FromAddress, "%s@%s", User->MailBox, Cfg->HostName);
  707.                         }
  708.                         delete User;
  709.                      }
  710.                   }
  711.                   else {
  712.                      // Nel caso in cui il messaggio provenga da un'altro nodo imposta come
  713.                      // indirizzo di ritorno di default quello standard per il gateway FidoNet.
  714.                      Addr.Parse (Msg->FromAddress);
  715.                      if (Addr.Point != 0)
  716.                         sprintf (Msg->FromAddress, "%s@p%u.f%u.n%u.z%u.fidonet.org", Msg->From, Addr.Point, Addr.Node, Addr.Net, Addr.Zone);
  717.                      else
  718.                         sprintf (Msg->FromAddress, "%s@f%u.n%u.z%u.fidonet.org", Msg->From, Addr.Node, Addr.Net, Addr.Zone);
  719.                      while ((p = strchr (Msg->FromAddress, ' ')) != NULL)
  720.                         *p = '.';
  721.                      if ((Nodes = new TNodes (Cfg->NodelistPath)) != NULL) {
  722.                         if (Nodes->Read (Msg->FromAddress, FALSE) == FALSE) {
  723.                            // Nel caso in cui il nodo (o point) abbia un suo indirizzo e-mail viene
  724.                            // usato quello come indirizzo di ritorno.
  725.                            if (Nodes->UseInetAddress == TRUE && Nodes->InetAddress[0] != '\0')
  726.                               strcpy (Msg->FromAddress, Nodes->InetAddress);
  727.                         }
  728.                         delete Nodes;
  729.                      }
  730.                   }
  731.  
  732.                   // Invia il mail attraverso la classe INETMAIL.
  733.                   if (Mail->Add (Msg) == TRUE) {
  734.                      Msg->ReadHeader (Number);
  735.                      Msg->Sent = TRUE;
  736.                      Msg->WriteHeader (Number);
  737.                      MsgSent++;
  738.                   }
  739.                }
  740.             }
  741.          } while (Msg->Next (Number) == TRUE);
  742.          delete Mail;
  743.       }
  744.  
  745.       if (Msg != NULL) {
  746.          delete Msg;
  747.          Msg = NULL;
  748.       }
  749.  
  750.       if (Status != NULL)
  751.          Status->Clear ();
  752.    }
  753. #endif
  754.  
  755.    Msg = NULL;
  756.    if (Cfg->NetMailStorage == ST_JAM)
  757.       Msg = new JAM (Cfg->NetMailPath);
  758.    else if (Cfg->NetMailStorage == ST_SQUISH)
  759.       Msg = new SQUISH (Cfg->NetMailPath);
  760.    else if (Cfg->NetMailStorage == ST_FIDO)
  761.       Msg = new FIDOSDM (Cfg->NetMailPath);
  762.    else if (Cfg->NetMailStorage == ST_ADEPT)
  763.       Msg = new ADEPT (Cfg->NetMailPath);
  764.    else if (Cfg->NetMailStorage == ST_HUDSON)
  765.       Msg = new HUDSON (Cfg->HudsonPath, (UCHAR)Cfg->NetMailBoard);
  766.  
  767.    if ((Mail = new INETMAIL) != NULL) {
  768.       strcpy (Mail->SMTPHostName, Cfg->MailServer);
  769.       if (Status != NULL) {
  770.          sprintf (Temp, "Sending NetMail to %s", Mail->SMTPHostName);
  771.          Status->SetLine (0, Temp);
  772.       }
  773.       Number = Msg->Lowest ();
  774.       do {
  775.          if (Msg->ReadHeader (Number) == TRUE) {
  776.             Addr.Clear ();
  777.             Addr.Parse (Msg->ToAddress);
  778.             if (Cfg->MailAddress.First () == TRUE && Addr.Zone == 0)
  779.                Addr.Zone = Cfg->MailAddress.Zone;
  780.  
  781.             Msgn = Msg->UidToMsgn (Number);
  782.             if (Status != NULL && (Msgn % 10) == 0L)
  783.                Status->SetLine (1, "   %lu / %lu", Msgn, Msg->Number ());
  784.  
  785.             ToUs = FALSE;
  786.             if (Msg->Sent == FALSE && Cfg->MailAddress.First () == TRUE)
  787.                do {
  788.                   if (Cfg->MailAddress.Zone == Addr.Zone || Addr.Zone == 0) {
  789.                      if (Cfg->MailAddress.Net == Addr.Net && Cfg->MailAddress.Node == Addr.Node) {
  790.                         if (Cfg->MailAddress.Point == Addr.Point)
  791.                            ToUs = TRUE;
  792.                      }
  793.                   }
  794.                } while (Cfg->MailAddress.Next () == TRUE);
  795.  
  796.             if (ToUs == TRUE && Msg->Sent == FALSE && strchr (Msg->To, '@') != NULL) {
  797.                Msg->Read (Number);
  798.                if (Status != NULL && (Msgn % 10) != 0L)
  799.                   Status->SetLine (1, "   %lu / %lu", Msgn, Msg->Number ());
  800.                if (Log != NULL) {
  801.                   Log->Write (":  Msg#: %lu", Msg->UidToMsgn (Number));
  802.                   Log->Write (":    Fm: %s", Msg->From);
  803.                   Log->Write (":    To: %s", Msg->To);
  804.                   Log->Write (":    Sb: %s", Msg->Subject);
  805.                }
  806.                if (Msg->Local == TRUE) {
  807.                   sprintf (Msg->FromAddress, "anonymous@%s", Cfg->HostName);
  808.                   if ((User = new TUser (Cfg->UserFile)) != NULL) {
  809.                      if (User->GetData (Msg->From, FALSE) == TRUE) {
  810.                         if (User->UseInetAddress == TRUE && User->InetAddress[0] != '\0')
  811.                            strcpy (Msg->FromAddress, User->InetAddress);
  812.                         else
  813.                            sprintf (Msg->FromAddress, "%s@%s", User->MailBox, Cfg->HostName);
  814.                      }
  815.                      delete User;
  816.                   }
  817.                }
  818.                else {
  819.                   if ((Nodes = new TNodes (Cfg->NodelistPath)) != NULL) {
  820.                      if (Nodes->Read (Msg->FromAddress, FALSE) == TRUE) {
  821.                         if (Nodes->UseInetAddress == TRUE && Nodes->InetAddress[0] != '\0')
  822.                            strcpy (Msg->From, Nodes->InetAddress);
  823.                         else {
  824.                            Addr.Parse (Msg->FromAddress);
  825.                            if (Addr.Point != 0)
  826.                               sprintf (Msg->FromAddress, "%s@p%u.f%u.n%u.z%u.fidonet.org", Msg->From, Addr.Point, Addr.Node, Addr.Net, Addr.Zone);
  827.                            else
  828.                               sprintf (Msg->FromAddress, "%s@f%u.n%u.z%u.fidonet.org", Msg->From, Addr.Node, Addr.Net, Addr.Zone);
  829.                         }
  830.                      }
  831.                      else {
  832.                         Addr.Parse (Msg->FromAddress);
  833.                         if (Addr.Point != 0)
  834.                            sprintf (Msg->FromAddress, "%s@p%u.f%u.n%u.z%u.fidonet.org", Msg->From, Addr.Point, Addr.Node, Addr.Net, Addr.Zone);
  835.                         else
  836.                            sprintf (Msg->FromAddress, "%s@f%u.n%u.z%u.fidonet.org", Msg->From, Addr.Node, Addr.Net, Addr.Zone);
  837.                      }
  838.                      delete Nodes;
  839.                   }
  840.                }
  841.                if (Mail->Add (Msg) == TRUE) {
  842.                   Msg->ReadHeader (Number);
  843.                   Msg->Sent = TRUE;
  844.                   Msg->WriteHeader (Number);
  845.                   MsgSent++;
  846.                }
  847.             }
  848.          }
  849.       } while (Msg->Next (Number) == TRUE);
  850.       delete Mail;
  851.    }
  852.  
  853.    if (Msg != NULL) {
  854.       delete Msg;
  855.       Msg = NULL;
  856.    }
  857.  
  858.    if (Status != NULL)
  859.       Status->Clear ();
  860.  
  861.    Msg = NULL;
  862. #if defined(__POINT__)
  863.    if (Cfg->NetMailStorage == ST_JAM)
  864.       Msg = new JAM (Cfg->NetMailPath);
  865.    else if (Cfg->NetMailStorage == ST_SQUISH)
  866.       Msg = new SQUISH (Cfg->NetMailPath);
  867.    else if (Cfg->NetMailStorage == ST_FIDO)
  868.       Msg = new FIDOSDM (Cfg->NetMailPath);
  869.    else if (Cfg->NetMailStorage == ST_ADEPT)
  870.       Msg = new ADEPT (Cfg->NetMailPath);
  871.    else if (Cfg->NetMailStorage == ST_HUDSON)
  872.       Msg = new HUDSON (Cfg->HudsonPath, Cfg->NetMailBoard);
  873. #else
  874.    if (Cfg->MailStorage == ST_JAM)
  875.       Msg = new JAM (Cfg->MailPath);
  876.    else if (Cfg->MailStorage == ST_SQUISH)
  877.       Msg = new SQUISH (Cfg->MailPath);
  878.    else if (Cfg->MailStorage == ST_FIDO)
  879.       Msg = new FIDOSDM (Cfg->MailPath);
  880.    else if (Cfg->MailStorage == ST_ADEPT)
  881.       Msg = new ADEPT (Cfg->MailPath);
  882.    else if (Cfg->MailStorage == ST_HUDSON)
  883.       Msg = new HUDSON (Cfg->HudsonPath, (UCHAR)Cfg->MailBoard);
  884. #endif
  885.  
  886.    Cfg->MailAddress.First ();
  887.    if ((User = new TUser (Cfg->UserFile)) != NULL) {
  888.       if (User->First () == TRUE)
  889.          do {
  890.             if (User->ImportPOP3Mail == TRUE && User->InetAddress[0] != '\0') {
  891.                if (Status != NULL) {
  892.                   sprintf (Temp, "Receiving e-mail for %s (%s)", User->Name, User->InetAddress);
  893.                   Status->SetLine (0, Temp);
  894.                }
  895.                if ((p = strchr (User->InetAddress, '@')) != NULL) {
  896.                   *p = '\0';
  897.                   strcpy (Name, User->InetAddress);
  898.                   strcpy (Host, &p[1]);
  899.                   *p = '@';
  900.                }
  901.                if ((Mail = new INETMAIL (Host, Name, User->Pop3Pwd)) != NULL) {
  902.                   if (Mail->Number () > 0L) {
  903.                      if (Log != NULL)
  904.                         Log->Write ("+Receiving e-mail for %s (%s)", User->Name, User->InetAddress);
  905.                      Number = Mail->Lowest ();
  906.                      do {
  907.                         if (Status != NULL) {
  908.                            sprintf (Temp, "%6lu / %-6lu", Number, Mail->Number ());
  909.                            Status->SetLine (1, Temp);
  910.                         }
  911.                         if (Mail->Read (Number, MAX_LINE_LENGTH) == TRUE) {
  912.                            if (Log != NULL) {
  913.                               Log->Write (":  Msg#: %lu", Number);
  914.                               Log->Write (":    Fm: %s", Mail->From);
  915.                               Log->Write (":    Sb: %s", Mail->Subject);
  916.                            }
  917.                            strcpy (Mail->To, User->Name);
  918.                            strcpy (Mail->ToAddress, Cfg->MailAddress.String);
  919.                            strcpy (Mail->FromAddress, Cfg->MailAddress.String);
  920.                            Mail->Sent = TRUE;
  921.                            if (Msg != NULL)
  922.                               Msg->Add (Mail);
  923.  
  924.                            Mail->Delete (Number);
  925.                            MsgTossed++;
  926.                         }
  927.                      } while (Mail->Next (Number) == TRUE);
  928.                   }
  929.                   delete Mail;
  930.                }
  931.             }
  932.          } while (User->Next () == TRUE);
  933.       delete User;
  934.    }
  935.  
  936.    if (Status != NULL)
  937.       Status->Clear ();
  938.  
  939.    if (Msg != NULL) {
  940.       delete Msg;
  941.       Msg = NULL;
  942.    }
  943.  
  944. #if !defined(__POINT__)
  945.    if (Cfg->NetMailStorage == ST_JAM)
  946.       Msg = new JAM (Cfg->NetMailPath);
  947.    else if (Cfg->NetMailStorage == ST_SQUISH)
  948.       Msg = new SQUISH (Cfg->NetMailPath);
  949.    else if (Cfg->NetMailStorage == ST_FIDO)
  950.       Msg = new FIDOSDM (Cfg->NetMailPath);
  951.    else if (Cfg->NetMailStorage == ST_ADEPT)
  952.       Msg = new ADEPT (Cfg->NetMailPath);
  953.    else if (Cfg->NetMailStorage == ST_HUDSON)
  954.       Msg = new HUDSON (Cfg->HudsonPath, (UCHAR)Cfg->NetMailBoard);
  955.  
  956.    if ((Nodes = new TNodes (Cfg->NodelistPath)) != NULL) {
  957.       if (Nodes->First () == TRUE)
  958.          do {
  959.             if (Nodes->ImportPOP3Mail == TRUE && Nodes->InetAddress[0] != '\0') {
  960.                if (Status != NULL) {
  961.                   sprintf (Temp, "Receiving e-mail for %s (%s)", Nodes->Address, Nodes->InetAddress);
  962.                   Status->SetLine (0, Temp);
  963.                }
  964.                if ((p = strchr (Nodes->InetAddress, '@')) != NULL) {
  965.                   *p = '\0';
  966.                   strcpy (Name, Nodes->InetAddress);
  967.                   strcpy (Host, &p[1]);
  968.                   *p = '@';
  969.                }
  970.                if ((Mail = new INETMAIL (Host, Name, Nodes->Pop3Pwd)) != NULL) {
  971.                   if (Mail->Number () > 0L) {
  972.                      if (Log != NULL)
  973.                         Log->Write ("+Receiving e-mail for %s (%s)", Nodes->Address, Nodes->InetAddress);
  974.                      Number = Mail->Lowest ();
  975.                      do {
  976.                         if (Status != NULL) {
  977.                            sprintf (Temp, "%6lu / %-6lu", Number, Mail->Number ());
  978.                            Status->SetLine (1, Temp);
  979.                         }
  980.                         if (Mail->Read (Number, MAX_LINE_LENGTH) == TRUE) {
  981.                            if (Log != NULL) {
  982.                               Log->Write (":  Msg#: %lu", Number);
  983.                               Log->Write (":    Fm: %s", Mail->From);
  984.                               Log->Write (":    Sb: %s", Mail->Subject);
  985.                            }
  986.                            strcpy (Mail->To, Nodes->SysopName);
  987.                            strcpy (Mail->ToAddress, Nodes->Address);
  988.                            if (Cfg->MailAddress.First () == TRUE) {
  989.                               strcpy (Mail->FromAddress, Cfg->MailAddress.String);
  990.                               do {
  991.                                  if (Cfg->MailAddress.Zone == Nodes->Zone) {
  992.                                     strcpy (Mail->FromAddress, Cfg->MailAddress.String);
  993.                                     break;
  994.                                  }
  995.                               } while (Cfg->MailAddress.Next () == TRUE);
  996.                            }
  997.                            Mail->Sent = FALSE;
  998.                            Mail->Private = TRUE;
  999.                            if (Msg != NULL)
  1000.                               Msg->Add (Mail);
  1001.  
  1002.                            // Il messaggio viene aggiunto all'email solo se i path
  1003.                            // delle aree email e netmail sono diversi.
  1004.                            if (stricmp (Cfg->MailPath, Cfg->NetMailPath)) {
  1005.                               // Se il Sysop del BBS/Point e' anche nostro utente, inserise il
  1006.                               // mail nella base message email locale.
  1007.                               if ((User = new TUser (Cfg->UserFile)) != NULL) {
  1008.                                  if (User->GetData (Msg->To, FALSE) == TRUE) {
  1009.                                     EMail = NULL;
  1010.                                     if (Cfg->MailStorage == ST_JAM)
  1011.                                        EMail = new JAM (Cfg->MailPath);
  1012.                                     else if (Cfg->MailStorage == ST_SQUISH)
  1013.                                        EMail = new SQUISH (Cfg->MailPath);
  1014.                                     else if (Cfg->MailStorage == ST_FIDO)
  1015.                                        EMail = new FIDOSDM (Cfg->MailPath);
  1016.                                     else if (Cfg->MailStorage == ST_ADEPT)
  1017.                                        EMail = new ADEPT (Cfg->MailPath);
  1018.                                     else if (Cfg->MailStorage == ST_HUDSON)
  1019.                                        EMail = new HUDSON (Cfg->HudsonPath, (UCHAR)Cfg->MailBoard);
  1020.  
  1021.                                     if (EMail != NULL) {
  1022.                                        EMail->Add (Mail);
  1023.                                        delete EMail;
  1024.                                     }
  1025.                                  }
  1026.                                  delete User;
  1027.                               }
  1028.                            }
  1029.  
  1030.                            Mail->Delete (Number);
  1031.                            MsgTossed++;
  1032.                         }
  1033.                      } while (Mail->Next (Number) == TRUE);
  1034.                   }
  1035.  
  1036.                   Mail->Close ();
  1037.                   delete Mail;
  1038.                }
  1039.             }
  1040.          } while (Nodes->Next () == TRUE);
  1041.       delete Nodes;
  1042.    }
  1043.  
  1044.    if (Msg != NULL) {
  1045.       delete Msg;
  1046.       Msg = NULL;
  1047.    }
  1048.  
  1049.    if (Status != NULL)
  1050.       Status->Clear ();
  1051. #endif
  1052. }
  1053.  
  1054. // ----------------------------------------------------------------------------
  1055. // Nodelist compiler
  1056. // ----------------------------------------------------------------------------
  1057.  
  1058. #define isLeap(x) ((x)%1000)?((((x)%100)?(((x)%4)?0:1):(((x)%400)?0:1))):(((x)%4000)?1:0)
  1059.  
  1060. USHORT UpdateNodelist (PSZ name, PSZ diff, class TStatus *Status)
  1061. {
  1062.    FILE *fps, *fpd, *fpn;
  1063.    DIR *dir;
  1064.    SHORT i, max, next, m, delay = 0;
  1065.    CHAR Temp[256], Path[64], String[32], *p;
  1066.    ULONG Perc, OldPerc = 101;
  1067.    time_t t;
  1068.    struct dirent *ent;
  1069.    struct tm *ltm;
  1070.  
  1071.    t = time (NULL);
  1072.    ltm = localtime (&t);
  1073.  
  1074.    strcpy (Path, Cfg->NodelistPath);
  1075.    p = strchr (Path, '\0');
  1076.    while (p > Path && *p != '\\' && *p != '/')
  1077.       p--;
  1078.    *p = '\0';
  1079.  
  1080.    max = -1;
  1081.    if ((dir = opendir (AdjustPath (Path))) != NULL) {
  1082.       while ((ent = readdir (dir)) != NULL) {
  1083.          if ((p = strchr (ent->d_name, '.')) != NULL) {
  1084.             *p++ = '\0';
  1085.             if (!stricmp (ent->d_name, name)) {
  1086.                i = (SHORT)atoi (p);
  1087.                if (i > max)
  1088.                   max = i;
  1089.             }
  1090.          }
  1091.       }
  1092.       closedir (dir);
  1093.    }
  1094.  
  1095.    if (max != -1) {
  1096.       next = (SHORT)(max + 7);
  1097.       if ((isLeap (ltm->tm_year - 1)) && next > 366)
  1098.          next -= 366;
  1099.       else if (!(isLeap (ltm->tm_year - 1)) && next > 365)
  1100.          next -= 365;
  1101.  
  1102.       if (diff != NULL && *diff != '\0') {
  1103.          sprintf (Temp, "%s\\%s.%03d", Path, diff, next);
  1104.          if ((fps = fopen (AdjustPath (Temp), "rt")) != NULL) {
  1105.             sprintf (Temp, "%s\\%s.%03d", Path, name, max);
  1106.             fpn = fopen (AdjustPath (Temp), "rt");
  1107.  
  1108.             sprintf (Temp, "%s\\%s.%03d", Path, name, next);
  1109.             fpd = fopen (AdjustPath (Temp), "wt");
  1110.  
  1111. #if !defined(__POINT__)
  1112.             if (Log != NULL)
  1113.                Log->Write (":  Updating %s.%03d with %s.%03d", name, max, diff, next);
  1114. #endif
  1115.             if (Status != NULL) {
  1116.                sprintf (Temp, "Updating %s.%03d with %s.%03d", name, max, diff, next);
  1117.                Status->SetLine (0, Temp);
  1118.                Status->SetLine (1, "");
  1119.             }
  1120.  
  1121.             if (fpn != NULL && fpd != NULL) {
  1122.                fgets (Temp, sizeof (Temp) - 1, fps);
  1123.  
  1124.                while (fgets (Temp, sizeof (Temp) - 1, fps) != NULL) {
  1125.                   while (Temp[strlen (Temp) -1] == 0x0D || Temp[strlen (Temp) -1] == 0x0A || Temp[strlen (Temp) -1] == ' ')
  1126.                      Temp[strlen (Temp) -1] = '\0';
  1127.  
  1128.                   if (Status != NULL) {
  1129.                      Perc = (ftell (fps) * 100L) / filelength (fileno (fps));
  1130.                      if (Perc != OldPerc) {
  1131.                         sprintf (String, "     %02lu%%", Perc);
  1132.                         Status->SetLine (1, String);
  1133.                         OldPerc = Perc;
  1134.                      }
  1135.                   }
  1136.  
  1137.                   if (Temp[0] == 'A' && isdigit (Temp[1])) {
  1138.                      m = (SHORT)atoi (&Temp[1]);
  1139.                      for (i = 0; i < m; i++) {
  1140.                         fgets (Temp, sizeof (Temp) - 1, fps);
  1141.                         fputs (Temp, fpd);
  1142.                      }
  1143.                   }
  1144.                   else if (Temp[0] == 'C' && isdigit (Temp[1])) {
  1145.                      m = (SHORT)atoi (&Temp[1]);
  1146.                      for (i = 0; i < m; i++) {
  1147.                         fgets (Temp, sizeof (Temp) - 1, fpn);
  1148.                         fputs (Temp, fpd);
  1149.                      }
  1150.                   }
  1151.                   else if (Temp[0] == 'D' && isdigit (Temp[1])) {
  1152.                      m = (SHORT)atoi (&Temp[1]);
  1153.                      for (i = 0; i < m; i++)
  1154.                         fgets (Temp, sizeof (Temp) - 1, fpn);
  1155.                   }
  1156.  
  1157. #if defined(__OS2__)
  1158.                   if ((delay++ % 16) == 0)
  1159.                      DosSleep (1L);
  1160. #elif defined(__NT__)
  1161.                   if ((delay++ % 16) == 0)
  1162.                      Sleep (1L);
  1163. #endif
  1164.                }
  1165.  
  1166.                if (fpn != NULL)
  1167.                   fclose (fpn);
  1168.                if (fpd != NULL)
  1169.                   fclose (fpd);
  1170.  
  1171.                fclose (fps);
  1172.  
  1173.                sprintf (Temp, "%s\\%s.%03d", Path, name, max);
  1174.                unlink (AdjustPath (Temp));
  1175.                sprintf (Temp, "%s\\%s.%03d", Path, diff, next);
  1176.                unlink (AdjustPath (Temp));
  1177.                max = next;
  1178.             }
  1179.          }
  1180.       }
  1181.    }
  1182.  
  1183.    return (max);
  1184. }
  1185.  
  1186. VOID CompileNodelist (USHORT force)
  1187. {
  1188.    FILE *fps;
  1189.    int fd;
  1190.    USHORT nzone, nnet, nnode;
  1191.    SHORT i, m, Build = force;
  1192.    CHAR Temp[256], *p;
  1193.    ULONG hdrpos, entrypos, records, totalnodes;
  1194.    IDXHEADER idx;
  1195.    NODEIDX nidx;
  1196.    struct stat statbuf, statidx;
  1197.    class TNodes *Nodes;
  1198.    class TAddress Addr;
  1199.    class TStatus *Status;
  1200.  
  1201.    nzone = 2;
  1202.    nnet = 0;
  1203.    if (Cfg->MailAddress.First () == TRUE) {
  1204.       nzone = Cfg->MailAddress.Zone;
  1205.       nnet = Cfg->MailAddress.Net;
  1206.    }
  1207.    records = 0L;
  1208.    totalnodes = 0L;
  1209.  
  1210. #if !defined(__POINT__)
  1211. #if defined(__OS2__) || defined(__NT__)
  1212.    if ((Status = new TPMStatus (hwndMainClient)) != NULL)
  1213.       Status->Clear ();
  1214. #else
  1215.    if ((Status = new TPMStatus) != NULL)
  1216.       Status->Clear ();
  1217. #endif
  1218. #endif
  1219.    if ((Nodes = new TNodes (Cfg->NodelistPath)) != NULL)
  1220.       Nodes->LoadNodelist ();
  1221.  
  1222.    if (Build == FALSE) {
  1223.       sprintf (Temp, "%snodes.idx", Cfg->NodelistPath);
  1224.       if (stat (Temp, &statidx) != 0)
  1225.          Build = TRUE;
  1226.  
  1227.       if (Nodes->FirstNodelist () == TRUE) {
  1228.          do {
  1229.             if (Nodes->Nodelist[1] == ':' || Nodes->Nodelist[0] == '\\')
  1230.                strcpy (Temp, Nodes->Nodelist);
  1231.             else
  1232.                sprintf (Temp, "%s%s", Cfg->NodelistPath, Nodes->Nodelist);
  1233.             if (stat (Temp, &statbuf) == 0) {
  1234.                if (statbuf.st_mtime > statidx.st_mtime)
  1235.                   Build = TRUE;
  1236.             }
  1237.          } while (Nodes->NextNodelist () == TRUE);
  1238.       }
  1239.  
  1240.       sprintf (Temp, "%snodes.idx", Cfg->NodelistPath);
  1241.       if ((fd = open (Temp, O_RDONLY|O_BINARY)) != -1) {
  1242.          while (read (fd, &idx, sizeof (IDXHEADER)) == sizeof (IDXHEADER)) {
  1243.             if (idx.Name[1] == ':' || idx.Name[0] == '\\')
  1244.                strcpy (Temp, idx.Name);
  1245.             else
  1246.                sprintf (Temp, "%s%s", Cfg->NodelistPath, idx.Name);
  1247.             if (stat (Temp, &statbuf) == 0) {
  1248.                if (statbuf.st_mtime > statidx.st_mtime) {
  1249.                   Build = TRUE;
  1250.                   break;
  1251.                }
  1252.             }
  1253.             else {
  1254.                Build = TRUE;
  1255.                break;
  1256.             }
  1257.  
  1258.             lseek (fd, idx.Entry * sizeof (NODEIDX), SEEK_CUR);
  1259.          }
  1260.          close (fd);
  1261.       }
  1262.    }
  1263.  
  1264.    if (Build == TRUE) {
  1265. #if !defined(__POINT__)
  1266.       if (Log != NULL)
  1267.          Log->Write (":Rebuild nodelist index");
  1268. #endif
  1269.  
  1270.       sprintf (Temp, "%snodes.idx", Cfg->NodelistPath);
  1271.       if ((fd = open (Temp, O_RDWR|O_BINARY|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE)) != -1) {
  1272.          if (Nodes->FirstNodelist () == TRUE)
  1273.             do {
  1274.                nzone = 2;
  1275.                if (Cfg->MailAddress.First () == TRUE)
  1276.                   nzone = Cfg->MailAddress.Zone;
  1277.                if (Nodes->DefaultZone != 0)
  1278.                   nzone = Nodes->DefaultZone;
  1279.  
  1280.                if (strchr (Nodes->Nodelist, '.') == NULL) {
  1281.                   if ((i = UpdateNodelist (Nodes->Nodelist, Nodes->Nodediff, Status)) != -1) {
  1282.                      for (;;) {
  1283.                         m = UpdateNodelist (Nodes->Nodelist, Nodes->Nodediff, Status);
  1284.                         if (m == i)
  1285.                            break;
  1286.                         i = m;
  1287.                      }
  1288.                      sprintf (Temp, ".%03d", i);
  1289.                      strcat (Nodes->Nodelist, Temp);
  1290.                   }
  1291.                }
  1292.  
  1293. #if !defined(__POINT__)
  1294.                if (Log != NULL)
  1295.                   Log->Write ("+Compiling %s", Nodes->Nodelist);
  1296. #endif
  1297.                if (Status != NULL) {
  1298.                   sprintf (Temp, "Compiling %s", Nodes->Nodelist);
  1299.                   Status->SetLine (0, Temp);
  1300.                }
  1301.  
  1302.                if (Nodes->Nodelist[1] == ':' || Nodes->Nodelist[0] == '\\')
  1303.                   strcpy (Temp, Nodes->Nodelist);
  1304.                else
  1305.                   sprintf (Temp, "%s%s", Cfg->NodelistPath, Nodes->Nodelist);
  1306.                if ((fps = fopen (Temp, "rt")) != NULL) {
  1307.                   memset (&idx, 0, sizeof (IDXHEADER));
  1308.                   strcpy (idx.Name, Nodes->Nodelist);
  1309.                   hdrpos = tell (fd);
  1310.                   write (fd, &idx, sizeof (IDXHEADER));
  1311.  
  1312.                   entrypos = ftell (fps);
  1313.                   while (fgets (Temp, sizeof (Temp) - 1, fps) != NULL) {
  1314.                      if (Temp[0] == ';') {
  1315.                         entrypos = ftell (fps);
  1316.                         continue;
  1317.                      }
  1318.  
  1319.                      if (strnicmp (Temp, "Down,", 5))
  1320.                         totalnodes++;
  1321.  
  1322.                      p = strtok (Temp, ",");
  1323.                      if (stricmp (p, "Boss") && stricmp (p, "Zone") && stricmp (p, "Region") && stricmp (p, "Host")) {
  1324.                         entrypos = ftell (fps);
  1325.                         continue;
  1326.                      }
  1327.  
  1328.                      nnode = 0;
  1329.                      if (!stricmp (p, "Boss")) {
  1330.                         p = strtok (NULL, ",");
  1331.                         Addr.Parse (p);
  1332.                         nzone = Addr.Zone;
  1333.                         nnet = Addr.Net;
  1334.                         nnode = Addr.Node;
  1335.                      }
  1336.                      else if (!stricmp (p, "Zone")) {
  1337.                         p = strtok (NULL, ",");
  1338.                         nzone = nnet = (USHORT)atoi (p);
  1339.                      }
  1340.                      else {
  1341.                         p = strtok (NULL, ",");
  1342.                         nnet = (USHORT)atoi (p);
  1343.                      }
  1344.  
  1345.                      if ((totalnodes % 16) == 0L && Status != NULL) {
  1346.                         sprintf (Temp, "%5u:%-5u Total: %lu", nzone, nnet, totalnodes);
  1347.                         Status->SetLine (1, Temp);
  1348. #if defined(__OS2__)
  1349.                         DosSleep (1L);
  1350. #elif defined(__NT__)
  1351.                         Sleep (1L);
  1352. #endif
  1353.                      }
  1354.  
  1355.                      nidx.Zone = nzone;
  1356.                      nidx.Net = nnet;
  1357.                      nidx.Node = nnode;
  1358.                      nidx.Position = entrypos;
  1359.                      write (fd, &nidx, sizeof (NODEIDX));
  1360.                      idx.Entry++;
  1361.                      records++;
  1362.                      entrypos = ftell (fps);
  1363.                   }
  1364.  
  1365.                   fclose (fps);
  1366.  
  1367.                   lseek (fd, hdrpos, SEEK_SET);
  1368.                   write (fd, &idx, sizeof (IDXHEADER));
  1369.                   lseek (fd, 0L, SEEK_END);
  1370.                }
  1371.             } while (Nodes->NextNodelist () == TRUE);
  1372.          close (fd);
  1373.       }
  1374.  
  1375. #if !defined(__POINT__)
  1376.       if (Log != NULL)
  1377.          Log->Write ("+%lu total nodes, %lu record(s) written", totalnodes, records);
  1378. #endif
  1379.    }
  1380.  
  1381.    if (Nodes != NULL)
  1382.       delete Nodes;
  1383.    if (Status != NULL) {
  1384.       Status->Clear ();
  1385.       delete Status;
  1386.    }
  1387. }
  1388.  
  1389.