home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / hamradio / 7plus202.zip / 7PL2SRC.LZH / DECODE.C < prev    next >
C/C++ Source or Header  |  1992-06-11  |  16KB  |  569 lines

  1. #include "7plus.h"
  2. #include "globals.h"
  3.  
  4. /*
  5. *** First decode. If there already are CORs for that file, try correcting
  6. *** afterwards.
  7. ***
  8.  */
  9. int control_decode (char *name)
  10. {
  11.   int i, cor_exists;
  12.   char newname[MAXPATH];
  13.  
  14.   i = cor_exists = 0;
  15.   *_ext = EOS;
  16.  
  17.   fnsplit (name, _drive, _dir, _file, _ext);
  18.   sprintf (newname, "%s%s%s.cor", _drive, _dir, _file);
  19.  
  20.   if (!test_exist (newname))
  21.     cor_exists = 1;
  22.  
  23.   i = decode_file (name, cor_exists);
  24.   if ((i == 11 || i == 19) && cor_exists)
  25.     return (correct_meta (newname, 1));
  26.  
  27.   return (i);
  28. }
  29.  
  30. /*
  31. *** decode a file. create error report, if errors detected.
  32. ***
  33. ***
  34.  */
  35.  
  36. int decode_file (char *name, int flag)
  37. {
  38.   struct   m_index index;
  39.   FILE     *in, *out;
  40.   int      part, _part, parts, _parts, _parts0;
  41.   int      c_line, c_line2, f_lines, blocklines;
  42.   int      defect, rest, length, hcorrupted, ignored;
  43.   uint     csequence, crc;
  44.   long     binbytes, _binbytes, lines, rebuilt;
  45.   ulong    ftimestamp, line;
  46.   char     rline[81], *p, dummi[20], dummi2[81];
  47.   char     inpath[MAXFPATH], indexfile[MAXPATH], metafile[MAXPATH];
  48.   char     filename[13], srcname[MAXPATH], orgname[MAXFNAME];
  49.   char     orgname2[66], destname[13];
  50.   register i, j;
  51.  
  52.   *orgname = EOS;
  53.   in = out = NULLFP;
  54.   hcorrupted = ignored = 0;
  55.   ftimestamp = 0UL;
  56.  
  57.   /* Isolate input-path and filename */
  58.   fnsplit (name, _drive, _dir, _file, _ext);
  59.   sprintf (inpath, "%s%s", _drive, _dir);
  60.   build_DOS_name (_file);
  61.   build_DOS_name (_ext);
  62.   _file[8] = _ext[3] = EOS;
  63.  
  64.   /* Make up names for the meta- and indexfile */
  65.   sprintf (metafile,  "%s.7mf", _file);
  66.   sprintf (indexfile, "%s.7if", _file);
  67.  
  68.   if (!test_exist (metafile))
  69.   {
  70.     printf ("\007Metafile '%s' already exists.\n", metafile);
  71.     return (19);
  72.   }
  73.  
  74.   /* Initialize index-info */
  75.   *index.filename  = *index.full_name  = EOS;
  76.   index.length     = index.timestamp   = 0UL;
  77.   index.splitsize  = 0;
  78.   for (i=0;i<8160;i++)
  79.     index.lines_ok[i] = 0;
  80.  
  81.   /* Find out, if it's a splitted file */
  82.   parts = 2;
  83.   sprintf (srcname, "%s%s.p01", inpath, _file);
  84.   if (test_exist (srcname))
  85.   {
  86.     parts = 1;
  87.     sprintf (srcname, "%s%s.7pl", inpath, _file);
  88.     if (test_exist (srcname))
  89.     {
  90.       sprintf (srcname, "%s.7pl/p01", _file);
  91.       printf (cant, srcname);
  92.       return (2);
  93.     }
  94.   }
  95.  
  96.   /* Open input file */
  97.   in = fopen (srcname, OPEN_READ_BINARY);
  98.  
  99.   /* Set I/O-buffering */
  100.   setvbuf (in, NULL, _IOFBF, buflen);
  101.  
  102.   printf ("\n-----------\nDecoding...\n-----------\n\n");
  103.  
  104.   defect = _parts0 = rest = length = 0;
  105.   lines = rebuilt = 0L;
  106.  
  107.   /* Loop for number of parts. */
  108.   for (part = 1; part < parts +1; part++)
  109.   {
  110.     if (part == 256)
  111.     {
  112.       printf ("\007\nMore than 255 parts not allowed. Break.\n");
  113.       kill_dest (in, out, metafile);
  114.       return (8);
  115.     }
  116.  
  117.     /* If more than 1 part, generate filename for messages and handling. */
  118.     if (parts == 1)
  119.       sprintf (filename, "%s.7pl", _file);
  120.     else
  121.       sprintf (filename, "%s.p%02x", _file, part);
  122.  
  123.     /* If we're already at part > 1, generate filename for next part. */
  124.     if (part != 1)
  125.     {
  126.       sprintf (srcname, "%s%s", inpath, filename);
  127.       if (!(in = fopen (srcname, OPEN_READ_BINARY)))
  128.       {
  129.         printf ("\007\n'%s': Not found. Break.\n", srcname);
  130.         printf ("\nYou must have all parts to be able to decode!\n");
  131.         printf ("              ===\n");
  132.         printf ("Get the missing files and try again.\n");
  133.  
  134.         kill_dest (in, out, metafile);
  135.         return (2);
  136.       }
  137.       setvbuf (in, NULL, _IOFBF, buflen);
  138.     }
  139.  
  140.     /* Read, until starting line is found. */
  141.     while ((p = my_fgets (rline, 80, in)) != NULL)
  142.     {
  143.       if (!strncmp (rline, " go_7+. ", 7))
  144.         break;
  145.     }
  146.     /* p == NULL? then no starting line found. File no good. */
  147.     if (!p)
  148.     {
  149.       printf ("\007'%s': 7PLUS-startline ", filename);
  150.       printf ("not found. Break.\n");
  151.       kill_dest (in, out, metafile);
  152.       return (3);
  153.     }
  154.  
  155.     if (!mcrc (rline, 0))
  156.       rebuild (rline, 1);
  157.  
  158.     /* Check if file went trough 7bit channel */
  159.     if (!strstr (rline, "\xb0\xb1"))
  160.     {
  161.       printf ("\007\n'%s':\nBit 8 has been stripped! Can't decode.\n", filename);
  162.       printf ("Please check all settings of your terminal and tnc regarding 8 bit transfer.\n");
  163.       printf ("You will have to re-read '%s' from the mailbox\n", filename);
  164.       printf ("after having corrected the settings.\n");
  165.       kill_dest (in, out, metafile);
  166.       return (9);
  167.     }
  168.  
  169.     /* Get info from 7PLUS header */
  170.     if(sscanf (rline+8, "%d %s %d %s %ld %s %s %s %s %s",
  171.             &_part, dummi, &_parts, destname,
  172.             &binbytes, dummi, dummi2, dummi, dummi, dummi) != 10)
  173.       hcorrupted = 1;
  174.     blocklines = get_hex (dummi2);
  175.     strlwr (destname);                  /* Convert to lower case */
  176.  
  177.     /* Set number of lines in this file */
  178.     f_lines = blocklines;
  179.     if (_part == _parts)
  180.       f_lines = (int) (((binbytes + 61) / 62) % blocklines);
  181.     if (!f_lines)
  182.       f_lines = blocklines;
  183.     f_lines--;
  184.  
  185.     if (strlen (dummi) == 5)
  186.       if (!mcrc(rline, 0))
  187.         hcorrupted = 1;
  188.  
  189.     if (!hcorrupted)
  190.     {
  191.       if (_part == 1)
  192.       {
  193.         _parts0  = _parts;
  194.         strcpy (index.filename, destname);
  195.         index.length  = binbytes;
  196.         index.splitsize = blocklines;
  197.       }
  198.  
  199.       if (_parts0 != _parts        || stricmp(index.filename, destname) ||
  200.           index.length != binbytes || index.splitsize != blocklines)
  201.         hcorrupted = 1;
  202.     }
  203.     if (hcorrupted)
  204.     {
  205.       printf ("'%s': Header is corrupted. Can't continue.\n", filename);
  206.       kill_dest (in, out, metafile);
  207.       return(5);
  208.     }
  209.     /* If first part, process filename, calculate how many valid binary bytes
  210.        are contained in last code line of last part, initialize index-info. */
  211.     if (_part == 1)
  212.     {
  213.  
  214.       *orgname2 = EOS;
  215.  
  216.       if (dummi[3] == '*')
  217.       {
  218.         my_fgets (rline, 80, in);
  219.         if (!mcrc (rline, 0))
  220.         {
  221.           printf ("\nExtended Filename corrupted. Using filename from header.\n");
  222.           strcpy (orgname2, index.filename);
  223.         }
  224.         else
  225.           sscanf (rline, "/%60[^/]", orgname2);
  226.       }
  227.  
  228.       strcpy (orgname,  index.filename);
  229.       if (extended == '*' && *orgname2)
  230.         strncpy (orgname, orgname2, (size_t)(MAXFNAME-1));
  231.       strcpy (index.full_name, orgname);
  232.  
  233.       rest = (int) (binbytes % 62);
  234.       if (!rest)
  235.         rest = 62;
  236.       parts = _parts; /* Set number of parts to decode. */
  237.     }
  238.  
  239.     /* Current file does not contain expected part */
  240.     if (_part != part)
  241.     {
  242.       printf ("\007'%s': File does not contain part %03d. Break.\n", filename, part);
  243.       kill_dest (in, out, metafile);
  244.       return (4);
  245.     }
  246.  
  247.     /* If first part, open metafile for writing. */
  248.     if (part == 1)
  249.     {
  250.       out = fopen (metafile, OPEN_WRITE_BINARY);
  251.       setvbuf (out, NULL, _IOFBF, buflen); /* As always, bufferize */
  252.       printf ("File         Pt# of# Errors Rebuilt   Status\n");
  253.       progress (filename, part, parts, 0, 0, "decoding...");
  254.     }
  255.  
  256.     c_line2 = -1;
  257.  
  258.     /* Now decode this part */
  259.     do
  260.     {
  261.       /* Get a line from code file */
  262.       p = my_fgets (rline, 80, in);
  263.  
  264.       /* If line starts with a space, check if it's the last line */
  265.       if (p && *rline == ' ')
  266.         if (!strncmp (rline, " stop_7+.", 8))
  267.         {
  268.           /* Get timespamp */
  269.           if (!ftimestamp && strchr (rline, '['))
  270.           {
  271.             if (!mcrc (rline, 0))
  272.             {
  273.               progress (filename, part, parts, lines, rebuilt, "### rebuilding a line ###");
  274.               rebuild (rline, 2);
  275.               progress (filename, part, parts, lines, rebuilt, "decoding...");
  276.             }
  277.             if (mcrc (rline, 0))
  278.             {
  279.               char dummy[30];
  280.  
  281.               if (sscanf (rline, " stop_7+. %s [%X]",
  282.                                                      dummy, &ftimestamp) != 2)
  283.                 ftimestamp = 0UL;
  284.             }
  285.             index.timestamp = ftimestamp;
  286.           }
  287.           p = NULL; /* Last line, set end indicator */
  288.         }
  289.       if (p)
  290.       {
  291.         /* Calculate CRC */
  292.         csequence = 0;
  293.         for (i=0; i<64; i++)
  294.           csequence = crctab[csequence>>8] ^ (((csequence&255)<<8) |
  295.                                                                   (byte)p[i]);
  296.         csequence &= 0x3fff; /* strip calculated CRC to 14 bits */
  297.  
  298.         /* Get crc from code line */
  299.         crc_n_lnum (&crc, &c_line, p);
  300.  
  301.         if (csequence != crc)
  302.         {
  303.           progress (filename, part, parts, lines, rebuilt, "### rebuilding a line ###");
  304.           if (!rebuild (p, 0))
  305.           {
  306.             ignored++; /* Incorrect CRC. Ignore line. */
  307.             continue;
  308.           }
  309.           rebuilt++;
  310.           progress (filename, part, parts, lines, rebuilt, "decoding...");
  311.           crc_n_lnum (&crc, &c_line, p);
  312.         }
  313.  
  314.         /* Number of valid binary bytes in this line. If it's the last line
  315.            of the last part, set it to the number precalculated earlier */
  316.         length = 62;
  317.         if (c_line == f_lines && part == parts)
  318.           length = rest;
  319.       }
  320.  
  321.       /* If file ends prematurely, set current line number to number of
  322.          lines in this part, so that the missing lines can be protocolled. */
  323.       if (!p && f_lines != c_line)
  324.         c_line = f_lines+1;
  325.  
  326.       /* If current line number is greater than previous one -> ok */
  327.       if (c_line > c_line2)
  328.       {
  329.         /* Difference is greater than 1, then line(s) must be missing. */
  330.         if (c_line2 != c_line-1)
  331.         {
  332.           defect = 1;
  333.  
  334.           /* Loop for number of missing or corrupted lines */
  335.           for (i = c_line2+1; i < c_line; i++)
  336.           {
  337.             progress (filename, part, parts, lines, rebuilt, "decoding...");
  338.             lines++; /* Number of missing or corrupted lines. */
  339.  
  340.             length = 62;
  341.             if (i == f_lines && part == parts)
  342.               length = rest;
  343.  
  344.             line = (long)(part-1)*index.splitsize +i;
  345.             index.lines_ok[(int)(line>>4)] += 1U << (uint)(line&15);
  346.  
  347.             /* Write fill-bytes into metafile */
  348.             for (j=length;j;j--)
  349.               my_putc ( 0, out);
  350.  
  351.             if (length < 62 || i == f_lines)
  352.               length = 0;
  353.           }
  354.         }
  355.         decode_n_write (out, rline, length);
  356.  
  357.         c_line2 = c_line; /* Memorize current line number */
  358.       }
  359.     }
  360.     while (p); /* Loop until current code file ends */
  361.  
  362.     progress (filename, part, parts, lines, rebuilt, "decoding...");
  363.  
  364.     fclose (in);
  365.   }
  366.   progress (filename, part-1, parts, lines, rebuilt, "done...");
  367.  
  368.   index.lines_left = lines;
  369.  
  370.   /* Get size of metafile */
  371.   _binbytes = ftell (out);
  372.  
  373.   if (out)
  374.     fclose (out);
  375.  
  376.   if (defect) /* write index-file and error report */
  377.     w_index_err (&index, 0);
  378.   else
  379.   {
  380.     if (_binbytes == binbytes)
  381.     {
  382.       test_file (NULLFP, orgname, 1, MAXFNAME-1);
  383.       replace (orgname, metafile, ftimestamp);
  384.  
  385.       printf ("\n");
  386.  
  387.       if (autokill)
  388.         kill_em (_file, inpath, (parts==1)?"7pl":"p", "cor", "c", "err", "e");
  389.  
  390.       printf ("\nDecoding successful! '%s', %ld bytes.\n",
  391.                                                            orgname, binbytes);
  392.       return (0);
  393.     }
  394.   }
  395.  
  396.   printf ("\n");
  397.   if (!flag)
  398.   {
  399.     printf ("\nDecoding of '%s' not successful.\n", orgname);
  400.     if (index.lines_left > (index.length/620L))
  401.     {
  402.       printf ("\nWARNING:\n========\n");
  403.       printf ("More than 10%% of all lines are corrupted! Are you sure, your communications\n");
  404.       printf ("programm is set correctly to handle 7PLUS files (character conversion ect..)?\n");
  405.       printf ("Maybe you didn't get parts of the files because of link failures?\n");
  406.       printf ("Of course, the cause may lie with the originating source...\n\n");
  407.     }
  408.   }
  409.   if (_binbytes != binbytes)
  410.   {
  411.     printf ("\nDecoded file has wrong length! Disk full?\n");
  412.     printf ("This error should never have occured.....I hoped...\n");
  413.     return (1);
  414.   }
  415.   else
  416.     if (autokill)
  417.       kill_em (_file, inpath, (parts==1)?"7pl":"p", NULL, NULL, NULL, NULL);
  418.  
  419.   return (11);
  420. }
  421.  
  422.  
  423. /*
  424. ***
  425. *** split up longs into 2 * 31 binary bytes and write to file.
  426. ***
  427.  */
  428. void decode_n_write (FILE *out, char *p, int length)
  429. {
  430.   static ulong after[16], *af;
  431.   static int   i, j, k;
  432.  
  433.   /* Re-arrange data-characters to 2*8 longs containing 31 bits each.*/
  434.   for (i=k=0; i<64; i++)
  435.   {
  436.     if ((i&3) == 3)
  437.     {
  438.       after[k] = 0L;
  439.       for (j=i;j>(i-4);j--)
  440.         after[k] = after[k] * 216L + decode[(byte)p[j]];
  441.       k++;
  442.     }
  443.   }
  444.  
  445.   af = after;
  446.   for (i=0; i<2; i++, af+=8)
  447.   {
  448.     /* Re-arrange to 2*8 longs containing 32 bits.
  449.        7th and 15th long only contain 24 valid bits. */
  450.     af[0] = (af[0] << 1) | (af[1] >> 30);
  451.     af[1] = (af[1] << 2) | (af[2] >> 29);
  452.     af[2] = (af[2] << 3) | (af[3] >> 28);
  453.     af[3] = (af[3] << 4) | (af[4] >> 27);
  454.     af[4] = (af[4] << 5) | (af[5] >> 26);
  455.     af[5] = (af[5] << 6) | (af[6] >> 25);
  456.     af[6] = (af[6] << 7) | (af[7] >> 24);
  457.     af[7] = (af[7] << 8);
  458.     for(j=0; j<8; j++)
  459.     {
  460.       for (k=24;k;k-=8)
  461.       {
  462.         if (!length)
  463.           break;
  464.         length--;
  465.         my_putc ((int) (af[j] >> k), out);
  466.       }
  467.       if (j == 7 || !length)
  468.         break;
  469.       length--;
  470.       my_putc ((int) af[j], out);
  471.     }
  472.   }
  473. }
  474.  
  475. /*
  476. *** Write indexfile and error report
  477. ***
  478. ***
  479.  */
  480. void w_index_err (struct m_index *index, int flag)
  481. {
  482.   FILE *ifile;
  483.   char filename[13];
  484.  
  485.   if (!flag)
  486.   {
  487.     fnsplit (index->filename, NULL, NULL, filename, NULL);
  488.  
  489.     #ifndef _CHSIZE_OK
  490.      strcat (filename, ".7ix");
  491.      ifile = fopen (filename, OPEN_WRITE_BINARY);
  492.     #else
  493.      strcat (filename, ".7mf");
  494.      ifile = fopen (filename, OPEN_RANDOM_BINARY);
  495.     #endif
  496.     write_index (ifile, index, 0);
  497.     fclose (ifile);
  498.   }
  499.   fnsplit (index->filename, NULL, NULL, filename, NULL);
  500.   strcat (filename, ".err");
  501.   ifile = fopen (filename, OPEN_WRITE_TEXT);
  502.   strupr (filename);
  503.   fprintf (ifile, " go_text. %s%s", filename, delimit);
  504.   strcpy (filename, index->filename);
  505.   strupr (filename);
  506.   fprintf (ifile, "7PLUS error report: %s %03X", filename, index->splitsize);
  507.   if (strcmp (index->full_name, index->filename))
  508.     fprintf (ifile, " /%s/", index->full_name);
  509.   fprintf (ifile, " %ld%s", index->length, delimit);
  510.   write_index (ifile, index, 1);
  511.   fprintf (ifile, "[%lX]%s00%s", index->timestamp, delimit, delimit);
  512.   fprintf (ifile, "________%s stop_text.%s", delimit, delimit);
  513.   if (endstr)
  514.     fprintf (ifile, "%s%s", endstr, delimit);
  515.   fclose (ifile);
  516.  
  517.   fnsplit (index->filename, NULL, NULL, filename, NULL);
  518.   strcat (filename, ".err");
  519.   crc_file (filename, "7P", "00\n", 0);
  520. }
  521.  
  522. /*
  523. *** If an error report has been accidentally erased, it can be recreated
  524. *** using the information in the indexfile, respectively metafile.
  525. *** (depends on _CHSIZE_OK)
  526.  */
  527. int make_new_err (char *name)
  528. {
  529.   struct m_index index;
  530.   FILE   *rfile;
  531.  
  532.   printf ("-----------------------\nRecreating error report\n-----------------------\n\n");
  533.  
  534.   /* Open meta file */
  535.   if (!(rfile = fopen (name, OPEN_READ_BINARY)))
  536.   {
  537.     printf (cant, name);
  538.     return (2);
  539.   }
  540.  
  541.   /* read index info into struct index */
  542.   if (read_index (rfile, &index))
  543.   {
  544.     printf ("\007Invalid index info.\n");
  545.     return (7);
  546.   }
  547.  
  548.   fclose (rfile);
  549.  
  550.   w_index_err (&index, 1);
  551.  
  552.   printf ("Error report has been recreated from '%s'.\n", name);
  553.  
  554.   return (0);
  555. }
  556.  
  557. /*
  558. *** Progress indication
  559. ***
  560. ***
  561.  */
  562. void progress (char *filename, int part, int of_parts, long errors,
  563.                                                     long rebuilt, char *status)
  564. {
  565.   printf ("%-12s %3d %3d %6ld  %6ld   %-30s\r",
  566.     filename, part, of_parts, errors, rebuilt, status);
  567.   fflush (stdout);
  568. }
  569.