home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1999 February / PCO_0299.ISO / filesbbs / dos / indigo01.exe / AREAS.CPP next >
Encoding:
C/C++ Source or Header  |  1997-08-21  |  13.9 KB  |  358 lines

  1. // This program is free software; you can redistribute it and/or modify it
  2. // under the terms of the GNU General Public License as published by the Free
  3. // Software Foundation; either version 2 of the License, or (at your option)
  4. // any later version.
  5.  
  6. // You should have received a copy of the GNU General Public License along
  7. // with this program; if not, write to the Free Software Foundation, Inc., 675
  8. // Mass Ave, Cambridge, MA 02139, USA.
  9.  
  10. // areas.cpp
  11. // Routines for handling Blue Wave packets.
  12.  
  13. #include <string.h>
  14. #include <stdio.h>
  15. #include <ctype.h>
  16. #include "areas.h"
  17. #include "fido.h"
  18. #include "shorttag.h"
  19. #include "debug.h"
  20. #ifdef __EMX__
  21. #include <unistd.h>
  22. #endif
  23.  
  24. // Class: BlueWaveArea
  25. // Description: Contains information about one area in a Blue Wave packet.
  26.  
  27. // constructor
  28. // Initialize data.
  29. BlueWaveArea::BlueWaveArea(unsigned isNetmail, char *areaNumber, char
  30.                            *areaTag, char *areaName, unsigned defZone)
  31. {
  32.     doDEBUG(printf("BlueWaveArea::BlueWaveArea(%u, \"%s\", \"%s\", \"%s\", %u)\n",
  33.             isNetmail, areaNumber, areaTag, areaName, defZone));
  34.  
  35.     // Zero out the data structures.
  36.     memset(&areainfo, 0, sizeof(INF_AREA_INFO));
  37.     memset(&mixrec,   0, sizeof(MIX_REC)      );
  38.  
  39.     // Set the default zone number.
  40.     defaultZone = defZone;
  41.  
  42.     // Copy information needed for the .inf file record.
  43.     strncpy((char *) &areainfo.areanum[0], areaNumber, sizeof(areainfo.areanum));
  44.     areainfo.areanum[sizeof(areainfo.areanum) - 1] = 0; // null terminated
  45.     strncpy((char *) &areainfo.title[0],   areaName,   sizeof(areainfo.title)  );
  46.     areainfo.title[sizeof(areainfo.title) - 1] = 0; // null terminated
  47.  
  48.     if (strlen(areaTag) >= sizeof(areainfo.echotag)) {
  49.         // The echotag is too long to fit in a .inf record, so we need to
  50.         // truncate it.
  51.         strcpy((char *) &areainfo.echotag[0], makeShortTag(areaTag));
  52.         doDEBUG(printf("!! long area name truncated to \"%s\"\n",
  53.                 areainfo.echotag));
  54.     }
  55.     else {
  56.         // The echotag is short enough.
  57.         strncpy((char *) &areainfo.echotag[0], areaTag, sizeof(areainfo.echotag));
  58.     }
  59.  
  60.     // Remember the real areatag.
  61.     myTag = strdup(areaTag);
  62.  
  63.     // Set up some area flags.
  64.     areainfo.network_type = INF_NET_FIDONET;
  65.     areainfo.area_flags = INF_SCANNING | INF_ANY_NAME | INF_ECHO |
  66.                           INF_POST;
  67.     areainfo.area_flags |= isNetmail ? INF_NETMAIL | INF_NO_PUBLIC :
  68.                            INF_NO_PRIVATE;
  69.     iAmNetmail = isNetmail;
  70.  
  71.     // Copy the information we need for the .mix file.
  72.     strncpy((char *) &mixrec.areanum[0], areaNumber, sizeof(mixrec.areanum));
  73.  
  74.     // Create temporary files for the .fti and .dat files.
  75.     char tempFileNameBase[8];
  76.     strcpy(tempFileNameBase, areaNumber);
  77.  
  78.     strcpy(tempFtiFile, tempFileNameBase);
  79.     strcat(tempFtiFile, ".ft$");
  80.  
  81.     strcpy(tempDatFile, tempFileNameBase);
  82.     strcat(tempDatFile, ".da$");
  83.  
  84.     // Remove the temporary files if they already existed.
  85.     remove(tempDatFile);
  86.     remove(tempFtiFile);
  87. }
  88.  
  89. // destructor
  90. BlueWaveArea::~BlueWaveArea()
  91. {
  92.     doDEBUG(printf("BlueWaveArea[%s]::~BlueWaveArea()\n", areainfo.areanum));
  93.  
  94.     // deallocate anything we have allocated
  95.     if (myTag) delete myTag;
  96. }
  97.  
  98. // method: addMessage
  99. // Adds a message from the PKT file to our area.
  100. void BlueWaveArea::addMessage(char *mFrom, char *mTo, char *mSubject, char
  101.                               *mDate, FidoAddress fromAddress,
  102.                               FILE *input, unsigned isPersonal)
  103. {
  104.     doDEBUG(printf("BlueWaveArea[%s]::addMessage(\"%s\", \"%s\", \"%s\", "
  105.             "\"%s\", %u:%u/%u.%u, (FILE *) %p, %u)\n",
  106.             areainfo.areanum,
  107.             mFrom, mTo, mSubject, mDate, fromAddress.zone, fromAddress.net,
  108.             fromAddress.node, fromAddress.point,
  109.             (void *) input, isPersonal));
  110.  
  111.     // Each message needs a .fti record.
  112.     FTI_REC ftirec;
  113.     memset(&ftirec, 0, sizeof(FTI_REC));
  114.  
  115.     // Increase the counters in the .mix file.
  116.     mixrec.totmsgs ++;
  117.     if (isPersonal)
  118.         mixrec.numpers ++;
  119.  
  120.     // Make sure the sender's and recipient's name does not only consist
  121.     // of uppercase letters (buggy QWK doors)
  122.  
  123.     // -*-Todo: This is done twice. It should be a function. I'm just too
  124.     // lazy to write one.-*-
  125.     
  126.     // Sender's name.
  127.     if (strlen(mFrom)) {
  128.         unsigned i = 0;
  129.         while (i < strlen(mFrom) && (isupper(mFrom[i]) || !isalpha(mFrom[i])))
  130.             i ++;
  131.         if (i == strlen(mFrom)) { // It was all uppercase, convert.
  132.             unsigned beginword = 1;
  133.             i = 0;
  134.             while (i < strlen(mFrom)) {
  135.                 if (!beginword)
  136.                     mFrom[i] = tolower(mFrom[i]);
  137.                 beginword = ' ' == mFrom[i] ? 1 : 0;
  138.                 i ++;
  139.             }
  140.         }
  141.     }
  142.  
  143.     // Recipient's name.
  144.     if (strlen(mTo)) {
  145.         unsigned i = 0;
  146.         while (i < strlen(mTo) && (isupper(mTo[i]) || !isalpha(mTo[i])))
  147.             i ++;
  148.         if (i == strlen(mTo)) { // It was all uppercase, convert.
  149.             unsigned beginword = 1;
  150.             i = 0;
  151.             while (i < strlen(mTo)) {
  152.                 if (!beginword)
  153.                     mTo[i] = tolower(mTo[i]);
  154.                 beginword = ' ' == mTo[i] ? 1 : 0;
  155.                 i ++;
  156.             }
  157.         }
  158.     }
  159.  
  160.     doDEBUG(printf("[%s] %s: %s\n", areainfo.echotag, mFrom, mSubject));
  161.  
  162.     // Put in .fti record data.
  163.     strncpy((char *) &ftirec.from[0],    mFrom,    sizeof(ftirec.from)   );
  164.     strncpy((char *) &ftirec.to[0],      mTo,      sizeof(ftirec.to)     );
  165.     strncpy((char *) &ftirec.subject[0], mSubject, sizeof(ftirec.subject));
  166.     strncpy((char *) &ftirec.date[0],    mDate,    sizeof(ftirec.date)   );
  167.  
  168.     // Open the .dat and .fti [temporary] files for writing.
  169.     FILE *datFile, *ftiFile;
  170.     if (NULL != (datFile = fopen(tempDatFile, "ab"))) {
  171.         if (NULL != (ftiFile = fopen(tempFtiFile, "ab"))) {
  172.             // Move to the end of the .fti and .dat files.
  173.             // This is not strictly necessary, but I do it to be on the
  174.             // safe side.
  175.             fseek(ftiFile, 0, SEEK_END);
  176.             fseek(datFile, 0, SEEK_END);
  177.  
  178.             // Fill the rest of the .fti record fields.
  179.             ftirec.msgnum = mixrec.totmsgs;
  180.             ftirec.msgptr = ftell(datFile); // Offset in the .dat file.
  181.             if (fromAddress.net != 0) {
  182.                 ftirec.orig_zone  = fromAddress.zone ? fromAddress.zone
  183.                                     : defaultZone;
  184.                 ftirec.orig_net   = fromAddress.net;
  185.                 ftirec.orig_node  = fromAddress.node;
  186.             }
  187.             ftirec.flags = 0;   // -*-Todo: Check this one-*-
  188.  
  189.             // Copy the message, end at null character in input stream.
  190.             // Start with a space (the Blue Wave format demands this).
  191.             fputc(' ', datFile);
  192.             ftirec.msglength = 1;
  193.  
  194.             // In netmail we need to read some kludges to find the real
  195.             // address of the sender. Since checking for kludges is slow,
  196.             // this check is not done for echomail.
  197.  
  198.             // -*-Todo: This should be cleaned up, and splitted, one that
  199.             // looks for the first kludges, and uses them, and goes on to
  200.             // the body when there are no more kludges. This will be
  201.             // necessary when the CHRS kludge support is implemented.-*-
  202.             
  203.             if (iAmNetmail) { // I'm netmail, so do kludge checking
  204.                 char kludgebuffer[80];
  205.                 int isNewLine = 1, isKludgeLine = 0;
  206.                 unsigned i = 0;
  207.                 int ch = fgetc(input);
  208.                 // Do until null character, or end of file.
  209.                 while (0 != ch && EOF != ch) {
  210.                     fputc(ch, datFile);
  211.                     ftirec.msglength ++;
  212.                     if (isKludgeLine && i < 80) { // Insert in kludge buffer.
  213.                         kludgebuffer[i ++] = ch;
  214.                         if (13 == ch) { // End of kludge line.
  215.                             kludgebuffer[i - 1] = 0;
  216.                             doDEBUG(printf("kludgebuffer = \"%s\"\n",
  217.                                            kludgebuffer));
  218.                             // INTL and MSGID kludges helps us to find the
  219.                             // complete address. The Blue Wave packet
  220.                             // format does not have a field for the point
  221.                             // address in the .fti file, so it is not
  222.                             // recovered. The reader will take care of it
  223.                             // if it finds a FMPT kludge, which should be
  224.                             // included in the PKT file anyway.
  225.  
  226.                             if (!strncmp(kludgebuffer, "INTL ", 5)) {
  227.                                 // INTL kludge.
  228.                                 char *ch_p = strrchr(kludgebuffer, ' ');
  229.                                 sscanf(ch_p + 1, "%u:%u/%u",
  230.                                        &ftirec.orig_zone,
  231.                                        &ftirec.orig_net,
  232.                                        &ftirec.orig_node);
  233.                                 doDEBUG(printf("=> %u:%u/%u\n",
  234.                                                ftirec.orig_zone,
  235.                                                ftirec.orig_net,
  236.                                                ftirec.orig_node));
  237.                             }
  238.                             else if (!strncmp(kludgebuffer, "MSGID: ", 7)) {
  239.                                 // MSGID kludge.
  240.                                 unsigned z, n, f;
  241.                                 if (3 == sscanf(&kludgebuffer[7], "%u:%u/%u",
  242.                                                 &z, &n, &f)) {
  243.                                     ftirec.orig_zone = z;
  244.                                     ftirec.orig_net = n;
  245.                                     ftirec.orig_node = f;
  246.                                     doDEBUG(printf("=> %u:%u/%u\n",
  247.                                                    ftirec.orig_zone,
  248.                                                    ftirec.orig_net,
  249.                                                    ftirec.orig_node));
  250.                                 }
  251.                             }
  252.                             i = 0;
  253.                             isKludgeLine = 0;
  254.                         }
  255.                     }
  256.                     
  257.                     // Check if the new line is a kludge line.
  258.                     if (isNewLine)
  259.                         isKludgeLine = 1 == ch;
  260.  
  261.                     // Does a new line start?
  262.                     isNewLine = 13 == ch;
  263.  
  264.                     // Get next character.
  265.                     ch = fgetc(input);
  266.                 }
  267.             }
  268.             else { // I'm echomail, so skip kludge checking.
  269.                 int ch = fgetc(input);
  270.                 // Copy everything.
  271.                 while (0 != ch && EOF != ch) {
  272.                     fputc(ch, datFile);
  273.                     ftirec.msglength ++;
  274.                     ch = fgetc(input);
  275.                 }
  276.             }
  277.  
  278.             // Write the .fti record to our temporary .fti file.
  279.             fwrite(&ftirec, sizeof(ftirec), 1, ftiFile);
  280.             fclose(ftiFile);
  281.         }
  282.         fclose(datFile);
  283.     }
  284. }
  285.  
  286. // method: addToFiles
  287. // Adds the data we have accumulated to the real Blue Wave files.
  288. void BlueWaveArea::addToFiles(FILE *infFile, FILE *mixFile, FILE *ftiFile,
  289.                               FILE *datFile)
  290. {
  291.     doDEBUG(printf("BlueWaveArea[%s]::addToFiles((FILE *) %p, (FILE *) %p, "
  292.             "(FILE *) %p, (FILE *) %p)\n",
  293.             areainfo.areanum,
  294.             infFile, mixFile, ftiFile, datFile));
  295.  
  296.     // Write a record to the .inf file.
  297.     fwrite(&areainfo, sizeof(areainfo), 1, infFile);
  298.  
  299.     // Write a record to the .mix file
  300.     mixrec.msghptr = ftell(ftiFile);    // Start position in .fti file.
  301.     fwrite(&mixrec, sizeof(mixrec), 1, mixFile);
  302.  
  303.     // Copy .fti and .dat files, if they exist.
  304.     FILE *thisFti, *thisDat;
  305.     if (NULL != (thisFti = fopen(tempFtiFile, "rb"))) {
  306.         if (NULL != (thisDat = fopen(tempDatFile, "rb"))) {
  307.             printf("Adding messages in %s.\n", areainfo.title);
  308.  
  309.             UINT32 totalDatSize = 0;
  310.  
  311.             // Write records to the .fti file.
  312.  
  313.             // Offset in the "real" .dat file.
  314.             SINT32 datFileOffset = ftell(datFile);
  315.             for(UINT16 i = 0; i < mixrec.totmsgs; i ++) {
  316.                 FTI_REC ftirec;
  317.                 fread(&ftirec, sizeof(ftirec), 1, thisFti);
  318.                 // Increase our intermediate offset to cope with the
  319.                 // real .dat file.
  320.                 ftirec.msgptr += datFileOffset;
  321.                 fwrite(&ftirec, sizeof(ftirec), 1, ftiFile);
  322.                 totalDatSize += ftirec.msglength;
  323.             }
  324.  
  325.             // Copy the .dat file in blocks of 1 Kbyte each.
  326.             char buffer[1024];
  327.             while (totalDatSize >= sizeof(buffer)) {
  328.                 fread( &buffer, sizeof(buffer), 1, thisDat);
  329.                 fwrite(&buffer, sizeof(buffer), 1, datFile);
  330.                 totalDatSize -= sizeof(buffer);
  331.             }
  332.             if (totalDatSize) {
  333.                 fread( &buffer, totalDatSize, 1, thisDat);
  334.                 fwrite(&buffer, totalDatSize, 1, datFile);
  335.             }
  336.  
  337.             // Close our temporary files
  338.             fclose(thisDat);
  339.             fclose(thisFti);
  340.  
  341.             // and delete them.
  342.             remove(tempDatFile);
  343.             remove(tempFtiFile);
  344.         }
  345.         fclose(thisFti);
  346.     }
  347. }
  348.  
  349. // method: isThisYou
  350. // Checks if we are the area that are requested.
  351. int BlueWaveArea::isThisYou(const char *echotag) {
  352.     doDEBUG(printf("BlueWaveArea[%s]::isThisYou(\"%s\") [I am \"%s\"]\n",
  353.             areainfo.areanum, echotag, myTag));
  354.  
  355.     // Is this my echotag?
  356.     return 0 == stricmp(echotag, myTag);
  357. }
  358.