home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 8 Other / 08-Other.zip / ydecod10.zip / ydec.c next >
C/C++ Source or Header  |  2002-04-02  |  27KB  |  1,087 lines

  1. /*
  2.  
  3. +----------------------------------------------------------------------------+
  4. !                                                                            !
  5. !   yDec 1.0  14.Nov.2001                                                    !
  6. !                                                                            !
  7. !   This sourcecode is released to the public domain - no rights reserved    !
  8. !   More info - also about the yEncoding - at:  www.yenc.org                 !
  9. !                                                                            !
  10. !   If you make a portation to another OS then please notify me (TIA)        !
  11. !          archiver@i3w.com    (Questions welcome)                           !
  12. !                                                                            !
  13. !   Juergen Helbing - infstar@infostar.de                                    !
  14. !                                                                            !
  15. !                                                                            !
  16. !   The 'offline' multipart feature has been implemented as a 'BackPack'.    !
  17. !   I'm not really happy about it - it is simply Q&D (quick and dirty).      !
  18. !                                                                            !
  19. +----------------------------------------------------------------------------+
  20.  
  21. */
  22.  
  23. /*
  24. * Ported to OS/2 by Mark Hale.
  25. */
  26.  
  27.  
  28. // Includes for OS/2 version.
  29.  
  30. #define INCL_DOS
  31. #define INCL_DOSERRORS
  32. // DosFindFirst, DosFindNext, DosFindClose
  33. #include <os2.h>
  34. #include <stdlib.h>
  35. #include <stdio.h>
  36. #include <string.h>
  37. #include <io.h>
  38.  
  39.  
  40. int errors,errparts,errfiles;
  41.  
  42. int aDsp;
  43. char attname[260];
  44. char attext[260];
  45. unsigned long ad_rescrc;
  46. unsigned long ad_reslen;
  47. int y_size;
  48. int y_line;
  49. int y_part;
  50. char datadir[260];
  51. char ad_desname[260];
  52. char ad_despath[260];
  53. int ad_cleanmode;
  54. int ad_crcmode;
  55.  
  56. #define print printf
  57. #define eprint printf
  58.  
  59.  
  60. // ad_fgetscr  is a functions which simulates 'fgets' but removes CRLF at the line end
  61.  
  62. char * ad_fgetscr(char * buffer, int maxlen, FILE * fp)
  63.     {
  64.     char * cp;
  65.     char * dp;
  66.  
  67.     cp=fgets(buffer,maxlen,fp);
  68.     if (cp==NULL) return(NULL);
  69.  
  70.     dp=strrchr(buffer,'\n');   // Eliminate CRLF
  71.     if (dp) *dp=0;
  72.     dp=strrchr(buffer,'\r');
  73.     if (dp) *dp=0;
  74.  
  75.     return(cp);
  76.  
  77.     }
  78.  
  79.  
  80.  
  81. int crc_tab[256] =
  82.  
  83. {
  84.     0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
  85.     0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
  86.     0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
  87.     0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
  88.     0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
  89.     0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
  90.     0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
  91.     0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
  92.     0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
  93.     0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
  94.     0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
  95.     0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
  96.     0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
  97.     0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
  98.     0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
  99.     0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
  100.     0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
  101.     0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
  102.     0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
  103.     0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
  104.     0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
  105.     0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
  106.     0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
  107.     0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
  108.     0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
  109.     0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
  110.     0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
  111.     0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
  112.     0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
  113.     0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
  114.     0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
  115.     0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
  116. }
  117. ;
  118.  
  119. int crc_val;
  120. long crc_anz;
  121.  
  122. void CrcInit(void)
  123.       {
  124.       crc_val = -1L ;
  125.       crc_anz=0L;
  126.       }
  127.  
  128.  
  129.  
  130. void CrcAdd(int c)
  131.     {
  132.     unsigned long ch1,ch2,cc;
  133.  
  134.  
  135.       /* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
  136.       /* for (i = 0; i < size; i++) */
  137.       /*      crccode = crc32Tab[(int) ((crccode) ^ (buf[i])) & 0xff] ^  */
  138.       /*                (((crccode) >> 8) & 0x00FFFFFFL); */
  139.       /*   return(crccode); */
  140.  
  141.  
  142.      cc= (c) & 0x000000ffL;
  143.      ch1=(crc_val ^ cc) & 0xffL;
  144.      ch1=crc_tab[ch1];
  145.      ch2=(crc_val>>8L) & 0xffffffL;  // Correct version
  146.      crc_val=ch1 ^ ch2;
  147.      crc_anz++;
  148.     }
  149.  
  150.  
  151. //  hex_to_ulong makes a conversion of an 8 character CRC to an unsigned long value
  152. //  strtol fails for CRCs which start with 89ABCDEF  !
  153.  
  154. unsigned long hex_to_ulong(char * text)
  155.     {
  156.     unsigned long res;
  157.     unsigned char c;
  158.  
  159.     if (text==NULL) return(-1);
  160.  
  161.     res=0;
  162. loop:
  163.     c=*text; text++;
  164.     if ((c>='0')&(c<='9'))
  165.         {
  166.         res=(res<<4)+((long)(c-48) & 0x0F);
  167.         goto loop;
  168.         }
  169.     if ((c>='A')&(c<='F'))
  170.         {
  171.         res=(res<<4)+((long)(c-55) & 0x0F);
  172.         goto loop;
  173.         }
  174.     if ((c>='a')&(c<='f'))
  175.         {
  176.         res=(res<<4)+((long)(c-87) & 0x0F);
  177.         goto loop;
  178.         }
  179.     return(res);
  180.     }
  181.  
  182.  
  183. long y_begin;  // Global for missing part management
  184. long y_end;
  185.  
  186. int yDecode(FILE * fOut, FILE * fIn, long y_line, long y_size,int y_part)
  187.     {
  188.     unsigned char srcbuf[4100];
  189.     unsigned char desbuf[4100];
  190.     unsigned char * srcp;
  191.     unsigned char * desp;
  192.     int deslen;
  193.     int srclen;
  194.     unsigned char c;
  195.     int id;
  196.     char * cp;
  197.     long decolen;
  198. //    long sumlen;
  199. //    int partnr;
  200.     unsigned long crc32;
  201.     char name[260];
  202.     int esize;
  203.     unsigned char * partbuf;
  204.     unsigned char * partptr;
  205.     long partsize;
  206.     long partfree;
  207.     long wlen;
  208.     long flen;
  209.  
  210.     if (aDsp) print("yDecoder started...\r\n");
  211.  
  212.     // sumlen=0; partnr=1;
  213.  
  214. part_start:
  215.     CrcInit();  // Analyse only CRC per part
  216.     decolen=0;
  217.     deslen=0; desp=desbuf;
  218.  
  219.     if (y_part)  // This is a multipart message !
  220.         {
  221.         cp=ad_fgetscr((char*) srcbuf,4097,fIn);  // fgets especially with ad_length
  222.         if (cp==NULL)
  223.             {
  224.             eprint("Unexpected eof in yEncoded file\r\n");
  225.             errors++;
  226.             return(1);
  227.             }
  228.  
  229.         if (aDsp) print("=ypart-line:  %s\r\n",srcbuf);
  230.  
  231.         if (strncmp((char*) srcbuf,"=ypart ",7))
  232.             {
  233.             eprint("Missing =ypart line in yEncoded multipart message\r\n");
  234.             errors++;
  235.             return(2);
  236.             }
  237.         cp=strstr((char*)srcbuf,"end=");
  238.         if (cp==NULL)
  239.             {
  240.             eprint("Missing end= in yEncoded multipart message\r\n");
  241.             errors++;
  242.             return(2);
  243.             }
  244.         y_end=atol(cp+4);
  245.  
  246.         cp=strstr((char*)srcbuf,"begin=");
  247.         if (cp==NULL)
  248.             {
  249.             eprint("Missing begin= in yEncoded multipart message\r\n");
  250.             errors++;
  251.             return(2);
  252.             }
  253.         y_begin=atol(cp+6);
  254.  
  255.         if (aDsp) print("part-begin: %ld\r\n",y_begin);
  256.         if (aDsp) print("part-end  : %ld\r\n",y_end);
  257.  
  258.         partbuf=malloc(y_end-y_begin+10);  // Allocate a buffer for the part
  259.         partptr=partbuf;
  260.         partsize=y_end-y_begin+1;
  261.         partfree=partsize;
  262.         }
  263.  
  264. loop:
  265.  
  266.     cp=ad_fgetscr((char*) srcbuf,4097,fIn);  // fgets especially with ad_length
  267.     if (cp==NULL)
  268.         {
  269.         eprint("Unexpected eof in yEncoded file\r\n");
  270.         errors++;
  271.         return(1);
  272.         }
  273.     if (strncmp((char*) srcbuf,"=yend ",6)==0)
  274.         {
  275.         if (aDsp) print("Endline (%d bytes): %s\r\n",decolen,srcbuf);
  276.         goto end_of_file;
  277.         }
  278.     if (strncmp((char*) srcbuf,"=ybegin ",8)==0)
  279.         {
  280.         eprint("Unexpected =ybegin in yEncoded file\r\n");
  281.         errors++;
  282.         return(1);
  283.         }
  284.     srclen=strlen((char*)srcbuf);
  285.     if (srclen<y_line)
  286.         {
  287.         if (aDsp) print("Last line.\r\n");
  288.         }
  289.     srcp=srcbuf;
  290.  
  291. loop2:
  292.     c=*srcp; srcp++;
  293.     if (c==0)
  294.         {
  295.         goto loop;  // End of line reached
  296.         }
  297.     if (c == '=')  // The escape character comes in
  298.         {
  299.         c=*srcp; srcp++;
  300.         if (c==0) return(2); // Last char cannot be escape char !
  301.         c=(unsigned char)(c-64);
  302.         }
  303.     c=(unsigned char)(c-42);  // Subtract the secret number
  304.     *desp=c; desp++; deslen++;    decolen++;
  305.  
  306.     CrcAdd(c);
  307.  
  308.     if (deslen>=4096)
  309.         {
  310.  
  311.         if (y_part)  // MultiPart --> to the partbuffer !
  312.             {
  313.             if (deslen>partfree)
  314.                 {
  315.                 eprint("Partial message corrupt: longer than (end-begin)!\r\n");
  316.                 errors++;
  317.                 return(11);
  318.                 }
  319.             memcpy(partptr,desbuf,deslen);
  320.             partptr=partptr+deslen;
  321.             partfree=partfree-deslen;
  322.             }
  323.         else    // Single part --> directly to target file
  324.             {
  325.             id=fwrite(desbuf,deslen,1,fOut);
  326.             if (id != 1)
  327.                 {
  328.                 eprint("Error in writing decoded file (code=%d)\r\n",errno);
  329.                 errors++;
  330.                 return(3);
  331.                 }
  332.             }
  333.         deslen=0; desp=desbuf;
  334.         }
  335.     goto loop2;
  336.  
  337. end_of_file:
  338.  
  339.  
  340.     if (deslen>0)  // Empty the last buffer
  341.         {
  342.         if (y_part)
  343.           {
  344.             if (deslen>partfree)
  345.                 {
  346.                 eprint("Partial message corrupt: longer than (end-begin)!\r\n");
  347.                 errors++;
  348.                 return(11);
  349.                 }
  350.             memcpy(partptr,desbuf,deslen);
  351.             //partptr=partptr+deslen;
  352.             //partfree=partfree-deslen;
  353.             }
  354.         else    // Single part --> directly to target file
  355.             {
  356.             id=fwrite(desbuf,deslen,1,fOut);
  357.             if (id != 1)
  358.                 {
  359.                 eprint("Error in writing decoded file (code=%d)\r\n",errno);
  360.                 errors++;
  361.                 return(3);
  362.                 }
  363.             }
  364.  
  365.  
  366.  
  367. //        id=fwrite(desbuf,deslen,1,fOut);
  368. //        if (id != 1)
  369. //            {
  370. //            eprint("Error in writing decoded file (code=%d)\r\n",errno);
  371. //            return(4);
  372. //            }
  373.         }
  374.  
  375.     cp=strstr((char*) srcbuf,"size=");  // Compare the decoded size to the =yend size
  376.     if (cp)
  377.         {
  378.         esize=atoi(cp+5);
  379.         if (esize != decolen)
  380.             {
  381.             sprintf(name,"%s(size=%ld)",attname,decolen);
  382.             strcpy(attname,name);
  383.             eprint("Corrupt yEnc binary - endsize mismatch (%s%s)\r\n",attname,attext);
  384.             errors++; errfiles++;
  385.             return(0);
  386.             }
  387.         }
  388.  
  389.  
  390.     // Check the srcbuf for the CRC
  391.     if (y_part==0)
  392.         {
  393.         cp=strstr((char*)srcbuf,"crc32=");
  394.         if (cp)
  395.             {
  396.             crc32=hex_to_ulong((char*)(cp+6));
  397.             ad_rescrc=crc_val ^ 0xFFFFFFFFl;
  398.             if (aDsp) print("Included CRC: $%08lx - calculated CRC: $%08lx\r\n",crc32,ad_rescrc);
  399.             }
  400.         }
  401.     else
  402.         {
  403.         cp=strstr((char*)srcbuf,"pcrc32=");
  404.         if (cp)
  405.             {
  406.             crc32=hex_to_ulong((char*)(cp+7));
  407.             ad_rescrc=crc_val ^ 0xFFFFFFFFl;
  408.             if (aDsp) print("Included CRC: $%08lx - calculated CRC: $%08lx\r\n",crc32,ad_rescrc);
  409.             }
  410.         }
  411.  
  412.     if (cp!=NULL)
  413.         {
  414.         if (crc32 != ad_rescrc)
  415.             {
  416.             sprintf(name,"%s(crc=%08lx)",attname,ad_rescrc);
  417.             strcpy(attname,name);
  418.             eprint("Corrupt yEnc binary - CRC mismatch (%s%s)\r\n",attname,attext);
  419.             errors++; errfiles++;
  420.             return(0);
  421.             }
  422.         }
  423.  
  424.     if (y_part==0)  // Single message
  425.         {
  426.         if ((y_part==0) & (decolen != y_size))
  427.             {
  428.             // eprint("Y-Decoder: Size mismatch - file corrupt.\r\n");
  429.  
  430.             sprintf(name,"%s(len=%ld)",attname,decolen);
  431.             strcpy(attname,name);
  432.             eprint("Corrupt yEnc binary - size mismatch (%s%s)\r\n",attname,attext);
  433.             errors++; errfiles++;
  434.             return(0);
  435.             }
  436.  
  437.         ad_reslen=decolen;
  438.         ad_rescrc=crc_val ^ 0xFFFFFFFFl;
  439.  
  440.         if (aDsp) print("yDecoder: Job done. %ld bytes written. CRC: $%08lx \r\n",decolen,ad_rescrc);
  441.         return(0);
  442.         }
  443.  
  444.     // Multipart message
  445.  
  446.     if ((y_part>0) & (decolen != (y_end-y_begin+1)))
  447.         {
  448.         eprint("yDecoder: Part size mismatch - file corrupt.\r\n");
  449.         errors++; errparts++;
  450.         return(6);
  451.         }
  452.  
  453.     // ----- Special handling for external decoder
  454.  
  455.     // Now write the decoded part to the target file !
  456.  
  457.     id=fseek(fOut,y_begin-1,0);
  458.     if (id)
  459.         {
  460.         eprint("Cannot write a part (fseek failed) [reason:%d]\r\n",errno);
  461.         errors++;
  462.         return(12);
  463.         }
  464.     flen=decolen;
  465.     partptr=partbuf;
  466.  
  467.     if (aDsp) print("Write part to target file (start: %ld, size: %ld)\r\n",y_begin-1,flen);
  468.  
  469.     while (flen>0)
  470.         {
  471.         wlen=flen;
  472.         if (wlen>8192) wlen=8192;
  473.         id=fwrite(partptr,wlen,1,fOut);
  474.  
  475.         if (id != 1)
  476.             {
  477.             eprint("Cannot write a part (fwrite failed) [reason:%d]\r\n",errno);
  478.             errors++;
  479.             return(12);
  480.             }
  481.         partptr=partptr+wlen;
  482.         flen=flen-wlen;
  483.         }
  484.  
  485.     free(partbuf);  // Give the part-buffer back !
  486.  
  487.     return(0);
  488.     // --------------------------------------------
  489.  
  490. /* ----- unused from newsreader decoder
  491.  
  492.     sumlen=sumlen+decolen;
  493.     if (sumlen == y_size)  // Completely decoded
  494.         {
  495.         if (aDsp) print("yDecoder: Multpart Job done. %ld bytes written\r\n",sumlen);
  496.  
  497.         ad_reslen=sumlen;
  498.         ad_rescrc=crc_val ^ 0xFFFFFFFFl;
  499.  
  500.         return(0);
  501.         }
  502.     if (sumlen>y_size)
  503.         {
  504.         eprint("yDecoder: More data than expected. File corrupt.\r\n");
  505.         errors++;
  506.         return(7);
  507.         }
  508.  
  509.     // Now scan the file for the rest !
  510.  
  511.     partnr++;  // Now scan for this part number
  512.  
  513. ploop:
  514.  
  515.     cp=ad_fgetscr((char*) srcbuf,4097,fIn);  // fgets especially with ad_length
  516.     if (cp==NULL)
  517.         {
  518.         eprint("Unexpected eof in multipart yEncoded file\r\n");
  519.         errors++;
  520.         return(1);
  521.         }
  522.     if (strncmp((char*) srcbuf,"=ybegin ",8))
  523.         {
  524.         if (aDsp) print("yEnc skipped: %s\r\n",srcbuf);
  525.         goto ploop;
  526.         }
  527.     cp=strstr((char*)srcbuf," part=");
  528.     if (cp==NULL)
  529.         {
  530.         eprint("No part in next ybegin found - in multipart yEncoded file\r\n");
  531.         errors++;
  532.         return(1);
  533.         }
  534.     if (atoi(cp+6) != partnr)
  535.         {
  536.         eprint("Unexpected part (%d) found in yEncoded message. Expected was (%d)\r\n",atoi(cp+6),partnr);
  537.         errors++;
  538.         return(1);
  539.         }
  540.     if (aDsp) print("Found part # %d\r\n",partnr);
  541.  
  542.     // Additional plausi possible for name & size
  543.  
  544.     goto part_start;
  545.  
  546. */
  547.     }
  548.  
  549.  
  550. int AddPart(char * srcname,long y_begin, long y_end)
  551.     {
  552.     FILE * fSrc;
  553.     FILE * fDes;
  554.     char desname[260];
  555.     char line[1024];
  556.     long a,e;
  557.     int copyrest;
  558.     char * cp;
  559.     int resparts;
  560.     long flen;
  561.  
  562.     if (aDsp) print("AddPart (%s) [%ld - %ld]\r\n",srcname,y_begin,y_end);
  563.  
  564.  
  565.     copyrest=0;
  566.     resparts=0;
  567.  
  568.     sprintf(desname,"%s.des",srcname);
  569.  
  570.     fSrc=fopen(srcname,"rb");
  571.     if (fSrc==NULL)
  572.         {
  573.         eprint("AddPart:  Part Info File not found (%s)\r\n",srcname);
  574.         errors++;
  575.         return(-1);
  576.         }
  577.     flen=filelength(fileno(fSrc));
  578.     if (flen==0)  // Already complete
  579.         {
  580.         return(-9);
  581.         }
  582.     fDes=fopen(desname,"wb");
  583.     if (fDes==NULL)
  584.         {
  585.         eprint("AddPart: Cannot create temporary part file (%s) [reason: %d]\r\n",desname,errno);
  586.         fclose(fSrc);
  587.         errors++;
  588.         return(-2);
  589.         }
  590. loop:
  591.     cp=fgets(line,1000,fSrc);
  592.     if (cp==NULL) goto eof1;
  593.     cp=strrchr(line,'\n');
  594.     if (cp) *cp=0;
  595.     cp=strrchr(line,'\r');
  596.     if (cp) *cp=0;
  597.  
  598.     // print("%s\r\n",line);
  599.  
  600.     if (copyrest)  // Analysis done - copy rest & done.
  601.         {
  602.         fprintf(fDes,"%s\r\n",line);
  603.         resparts++;
  604.         goto loop;
  605.         }
  606.  
  607.     a=atol(line);
  608.     if (a==0)
  609.         {
  610.         eprint("Corrupt part-info file (%s)\r\n",line);
  611.         errors++;
  612.         fclose(fSrc); fclose(fDes); return(-3);
  613.         }
  614.     cp=strchr(line,',');
  615.     if (cp==NULL)
  616.         {
  617.         eprint("Corrupt part-info file (%s)\r\n",line);
  618.         errors++;
  619.         fclose(fSrc); fclose(fDes); return(-4);
  620.         }
  621.     e=atol(cp+1);
  622.     //    print("a:%6d, e:%6d\r\n",a,e);
  623.  
  624. // ----- Case Analysis -----
  625. //    .............[yb--------ye]      (The new, incoming block)
  626. //    1...a****e                       (The old, missing block)
  627. //    2...a********-----e              (***) Newly written missing block
  628. //    3...a********--------------****e
  629. //    .............[yb--------ye]
  630. //    4............a-----e
  631. // 5............a------------e
  632. //    6............a-------------****e
  633. //    .............[yb--------ye]
  634. //    7............................a***e
  635. //    .............[yb--------ye]
  636. //    8................a----e
  637. //    9................a---------****e
  638.  
  639.  
  640.  
  641.  
  642.     if (a<y_begin)  // A previous section was missed
  643.         {
  644.         if (e<y_begin) // A previous section was missed entirely
  645.             {
  646.             // Case-1
  647.             fprintf(fDes,"%ld,%ld\r\n",a,e);  // --> Keep that entry
  648.             resparts++;
  649.             goto loop;
  650.             }
  651.         if (e<=y_end)  // Rduce the old section
  652.             {
  653.             // Case-2
  654.             fprintf(fDes,"%ld,%ld\r\n",a,y_begin-1);  // --> Reduce that entry
  655.             resparts++;
  656.             goto loop;
  657.             }
  658.         // The new section is splitting the old missing section
  659.             // Case-3
  660.             fprintf(fDes,"%ld,%ld\r\n",a,y_begin-1);  // --> First part
  661.             fprintf(fDes,"%ld,%ld\r\n",y_end+1,e);  // --> First part
  662.             resparts++; resparts++;
  663.             goto loop;
  664.         }
  665.  
  666.     if (a==y_begin)  // New part matches this segment
  667.         {
  668.         if (e<y_end)   // Just a smaller section was missed
  669.             {
  670.             // case 4
  671.             goto loop;  // Skip this and analyse next
  672.             }
  673.         if (e==y_end)  // This missing section was exactly -> remove it & done.
  674.             {
  675.             // case 5
  676.             copyrest=1; goto loop;
  677.             }
  678.         if (e>y_end)  // The first part was found
  679.             {
  680.             // case-6
  681.             fprintf(fDes,"%ld,%ld\r\n",y_end+1,e);  // Write the rest
  682.             resparts++;
  683.             copyrest=1; goto loop;
  684.             }
  685.         }
  686.  
  687.     if (a>y_begin)
  688.         {
  689.         if (a>y_end)  // the found section completely in front of this one.
  690.             {
  691.             // Case-7
  692.             fprintf(fDes,"%ld,%ld\r\n",a,e);  // Rewrite it & copy the rest
  693.             resparts++;
  694.             copyrest=1; goto loop;
  695.             }
  696.         if (e<=y_end) // The section was completely found
  697.             {
  698.             // Case-8
  699.             goto loop;  // Analyse the rest
  700.             }
  701.         // The first part of the missing section was found
  702.             // case-9
  703.             fprintf(fDes,"%ld,%ld\r\n",y_end+1,e);  // Reduce it & copy the rest
  704.             resparts++;
  705.             copyrest=1; goto loop;
  706.         }
  707.  
  708. eof1:
  709.     fclose(fSrc); fclose(fDes);
  710.     remove(srcname);
  711.  
  712.     rename(desname,srcname);
  713.  
  714.     return(resparts);
  715.     }
  716.  
  717.  
  718.  
  719.  
  720. char srcmask[260];
  721.  
  722. int DecodeFile(char * fname)
  723.     {
  724.     FILE * fIn;
  725.     char line[8200];
  726.     char * cp;
  727.     char filename[260];
  728.     FILE * fOut;
  729.     int id;
  730.     long flen,wlen;
  731.     char filename2[260];
  732.  
  733.     fIn=fopen(fname,"rb");
  734.     if (fIn==NULL)
  735.         {
  736.         eprint("Cannot open sourcefile (%s) [reason:%d]\r\n",fname,errno);
  737.         errors++;
  738.         return(1);
  739.         }
  740. loop:
  741.     cp=fgets(line,8192,fIn);    // Read source line
  742.     if (cp==NULL) goto eof1;
  743.  
  744.     cp=strrchr(line,'\n');     // Eliminate CRLF
  745.     if (cp) *cp=0;
  746.     cp=strrchr(line,'\r');
  747.     if (cp) *cp=0;
  748.  
  749.     if (strncmp(line,"=ybegin ",8)) goto loop;
  750.  
  751.  
  752.     if (aDsp) print("\r\nTrigger: %s\r\n",line);
  753.  
  754.     // Start of a section found
  755.  
  756.         cp=strstr(line,"name=");
  757.         if (cp==NULL)
  758.             {
  759.             eprint("'name=' not found in =ybegin line. (%s)\r\n",line);
  760.             errors++;
  761.             goto loop;  // Error - filename not found
  762.             }
  763.         strcpy(attname,cp+5);  // Store the filename
  764.         *cp=0; // throw away the filename
  765.  
  766.         cp=strstr(line,"size=");
  767.         if (cp==NULL)
  768.             {
  769.             eprint("'size=' not found in =ybegin line. (%s)\r\n",line);
  770.             errors++;
  771.             goto loop;  // Error - size not found
  772.             }
  773.         y_size=atol(cp+5);
  774.  
  775.         cp=strstr(line,"line=");
  776.         if (cp==NULL)
  777.             {
  778.             eprint("'line=' not found in =ybegin line. (%s)\r\n",line);
  779.             errors++;
  780.             goto loop;  // Error - linelength not found
  781.             }
  782.         y_line=atol(cp+5);
  783.  
  784.         y_part=0;
  785.         cp=strstr(line,"part=");   // Check if this is a multipart message
  786.         if (cp)
  787.             {
  788.             y_part=atol(cp+5);
  789. //            if (y_part != 1) goto loop;   // MUST start with the first part for proper decoding
  790.             }
  791.  
  792.         // Now we can decode the file -- let's assume that this is a valid file
  793.  
  794.         attext[0]=0;
  795.         cp=strrchr(attname,'.');
  796.         if (cp)
  797.             {
  798.             strcpy(attext,cp); *cp=0;
  799.             }
  800.  
  801.         // sprintf(filename,"%s\\decode.tmp",datadir);
  802.         sprintf(filename,"%sdecode.tmp",ad_despath);
  803.  
  804.     // ----- Special Handling for offline decoder (missing parts or mixed sequence)
  805.     if (y_part)
  806.         {
  807.         sprintf(filename ,"%s%s%s(%ld).tmp",ad_despath,attname,attext,y_size);
  808.         sprintf(filename2,"%s%s%s(%ld).dec",ad_despath,attname,attext,y_size);
  809.         }
  810.     // ----------------------------------------------------------------------
  811.  
  812.  
  813.         if (aDsp) print("DesFileName = (%s%s)\r\n",attname,attext);
  814.  
  815.         // 27-03-2001: Set the filename just in case we cannot decode it
  816.         sprintf(ad_desname,"%s\\%s%s",ad_despath,attname,attext);
  817.         // sprintf(ad_desname,"%s%s",attname,attext);
  818.  
  819.         // filelen=0;
  820.  
  821. /*    Not used in standalone decoder
  822.  
  823.         if (ad_crcmode) CrcInit();
  824.         if (ad_cleanmode)
  825.             {
  826.             ad_cleanmode=2;  // This will prevent us from writing more to the clean buffer
  827.             if (aDsp) print("Begin cleaning...\r\n");
  828.             CrcInit();
  829.             }
  830. */
  831.  
  832.         // Check if the target file exists already
  833.         if (y_part)
  834.             {
  835.  
  836.             fOut=fopen(filename2,"rb");
  837.             if (fOut)
  838.                 {
  839.                 flen=filelength(fileno(fOut));
  840.                 fclose(fOut);
  841.                 if (flen==0)
  842.                     {
  843.                     print("Part#%3d duplicate for finished %s \r\n",y_part,ad_desname);
  844.                     goto loop;
  845.                     }
  846.                 }
  847.  
  848.             fOut=fopen(filename,"r+b");
  849.             if (fOut)
  850.                 {
  851.                 flen=filelength(fileno(fOut));
  852.                 if (flen==y_size)
  853.                     {
  854.                     goto already_open;
  855.                     }
  856.                 else
  857.                     {
  858.                     fclose(fOut);
  859.                     eprint("Size mismatch on target multipart file !(act:%ld, new:%ld) (%s)\r\n",flen,y_size,filename);
  860.                     errors++;
  861.                     goto abortus;
  862.                     }
  863.                 }
  864.             else // First time: Create this file & the missing index
  865.                 {
  866.                 fOut=fopen(filename2,"wb");
  867.                 if (fOut==NULL)
  868.                     {
  869.                     eprint("Cannot create part-info-file (%s)\r\n",filename2);
  870.                     errors++;
  871.                     goto abortus;
  872.                     }
  873.                 fprintf(fOut,"%ld,%ld\r\n",1,y_size);  // Everything is missing !
  874.                 fclose(fOut);
  875.                 }
  876.             }
  877.  
  878.         fOut=fopen(filename,"w+b");
  879.         if (fOut==NULL)  // Possibly already exists
  880.             {
  881.             eprint("AutoDecode: Cannot create DesFile (%s)\r\n",filename);
  882.             errors++;
  883.             fclose(fIn);
  884.             return(-1);
  885.             // goto loop;
  886.             }
  887.  
  888.         if (y_part)  // Now create the entire file !
  889.             {
  890.             flen=y_size;
  891.             memset(line,255,8192);
  892.             while (flen>0)
  893.                 {
  894.                 wlen=flen;
  895.                 if (wlen>8192) wlen=8192;
  896.                 id=fwrite(line,wlen,1,fOut);
  897.                 if (id!=1)
  898.                     {
  899.                     eprint("Could not create the target file (disk full?)\r\n");
  900.                     fclose(fOut);
  901.                     fclose(fIn);
  902.                     errors++;
  903.                     return(-2);
  904.                     }
  905.                 flen=flen-wlen;
  906.                 }
  907.             }
  908.     already_open:
  909.  
  910.         // Now decode that file !
  911.  
  912.         id=yDecode(fOut,fIn,y_line,y_size,y_part);
  913.         if (id)
  914.             {
  915.             eprint("yDecode failed (reason: %d)\r\n",id);
  916.             goto abortus;
  917.             }
  918.         sprintf(ad_desname,"%s%s%s",ad_despath,attname,attext); // Create new target name
  919.         if (aDsp) print("yDecode successful\r\n");
  920.         fclose(fOut);
  921.  
  922.         // ----- Special handling for offline multipart
  923.  
  924.         if (y_part)  // Now update the 'missing part file'
  925.             {
  926.             id=AddPart(filename2,y_begin,y_end);
  927.             if (id==0)  // All parts done
  928.                 {
  929.                 print("Complete multipart --> %s\r\n",ad_desname);
  930.                 goto rename_it;
  931.                 }
  932.             if (id>0)
  933.                 {
  934.                 print("Part#%3d: %s --> %s\r\n",y_part,fname,ad_desname);
  935.                 }
  936.             if (id==(-9))
  937.                 {
  938.                 print("Part#%3d of finished %s \r\n",y_part,ad_desname);
  939.                 }
  940.             }
  941.         if (y_part) goto loop;
  942.         // --------------------------------------------
  943.  
  944.     rename_it:
  945.         // Now check if the target file exists already
  946.         id=rename(filename,ad_desname);
  947.         if (id)
  948.             {
  949.             if (errno==35)
  950.                 {
  951.                 eprint("File exists already: (%s)\r\n",ad_desname);
  952.                 errors++;
  953.                 }
  954.             else
  955.                 {
  956.                 eprint("Cannot create target file (%s) [reason: %d]\r\n",ad_desname,errno);
  957.                 errors++;
  958.                 }
  959.             }
  960.         else
  961.             {
  962.             if (y_part==0) print("Decoded:  %s --> %s\r\n",fname,ad_desname);
  963.             if (y_part)    print("Decoded multipart --> %s\r\n",ad_desname);
  964.             }
  965. abortus:
  966.     goto loop;
  967.  
  968.  
  969. eof1:
  970.     fclose(fIn);
  971.     return(0);
  972.     }
  973.  
  974.  
  975.  
  976. void usage(void)
  977. {
  978.     print("\r\n");
  979.     print("Usage: yDecoder v-1.0\r\n\r\n");
  980.     print("ydec filename             (for normal operation) \r\n");
  981.     print("ydec *.txt                (for operation on multiple files)\r\n");
  982.     print("ydec filename  /a         (for all debug output) \r\n");
  983.     print("ydec filename  /a  | more (for all debug output with paging) \r\n");
  984. }
  985.  
  986.  
  987.  
  988. int main(int ac, char * av[])
  989.     {
  990.     APIRET rc;
  991.     HDIR hdir=HDIR_CREATE;
  992.     FILEFINDBUF3 findBuffer;
  993.     ULONG findCount=1;
  994.     char mask[260];
  995.     char * cp;
  996.  
  997.     errors=0;  //  Counter for batch decoder errors
  998.     errfiles=0;
  999.     errparts=0;
  1000.  
  1001.     aDsp=0;            // all debug display
  1002.     datadir[0]=0;      // Target directory is actual directory
  1003.     ad_despath[260]=0;
  1004.  
  1005.     ad_cleanmode=0;    // No special modes for standalone decoder
  1006.     ad_crcmode=0;
  1007.  
  1008.     print("\r\n");
  1009.     print("yDec-v1 (14.Nov.2001) - Public Domain - by Juergen Helbing - www.yenc.org\r\n\r\n");
  1010.  
  1011. //    if (ac>=1) print("[0]: %s\r\n",av[0]);
  1012. //    if (ac>=2) print("[1]: %s\r\n",av[1]);
  1013. //    if (ac>=3) print("[2]: %s\r\n",av[2]);
  1014.  
  1015.     if (ac<2)
  1016.         {
  1017.         print("Missing parameter (filename or filename*.* required) !\r\n");
  1018.         usage();
  1019.         return(1);
  1020.         }
  1021.     if (ac>3)
  1022.         {
  1023.         print("Illegal additional parameters !\r\n");
  1024.         usage();
  1025.         return(1);
  1026.         }
  1027.  
  1028.     if (ac==3)
  1029.         {
  1030.         if (strstr(av[2],"/a")) aDsp=1;
  1031.         }
  1032.  
  1033.     strcpy(mask,av[1]);
  1034.  
  1035.     // local test only
  1036.     //    strcpy(mask,"*.ntx");
  1037.  
  1038.     // Now find all the mesages and decode them
  1039.  
  1040.     if (strchr(mask,'\\')) // Full path found -> is Drag and drop
  1041.         {
  1042.         strcpy(ad_despath,mask);
  1043.         cp=strrchr(ad_despath,'\\');
  1044.         if (cp) { *(cp+1)=0; };  // Path for temp and target files
  1045.  
  1046.         DecodeFile(mask);
  1047.  
  1048.         // For drag and drop support !
  1049.         if (errors==0)
  1050.             {
  1051.             WinMessageBox(HWND_DESKTOP,HWND_DESKTOP,"End of decoder","yDecode",0,MB_OK | MB_INFORMATION);
  1052.             }
  1053.  
  1054.         goto done;
  1055.         }
  1056.  
  1057.     // Seek all matching files
  1058.  
  1059.     // Find all files which are matching the seek-mask
  1060.     rc=DosFindFirst(mask,&hdir,FILE_ARCHIVED|FILE_READONLY,&findBuffer,sizeof(FILEFINDBUF3),&findCount,FIL_STANDARD);
  1061.     if (rc) {
  1062.         print("No files found to match (%s)\r\n",mask);
  1063.         goto done;
  1064.     }
  1065.     do {
  1066.         if (!strstr(findBuffer.achName,".exe")) {
  1067.             if (aDsp) print("Decode file: (%s)\r\n",findBuffer.achName);
  1068.             DecodeFile(findBuffer.achName);
  1069.         }
  1070.         rc=DosFindNext(hdir,&findBuffer,sizeof(FILEFINDBUF3),&findCount);
  1071.     } while(rc==NO_ERROR);
  1072.     DosFindClose(hdir);
  1073.  
  1074. done:
  1075.     if (errors|errfiles|errparts)
  1076.         {
  1077.         print("\r\n");
  1078.         if (errors) print("%d error(s) during decoding.\r\n",errors);
  1079.         if (errfiles) print("%d file(s) with errors stored to disk\r\n",errfiles);
  1080.         if (errparts) print("%d corrupt part(s) detected.\r\n",errparts);
  1081.  
  1082.         WinMessageBox(HWND_DESKTOP,HWND_DESKTOP,"Decoder terminated. \r\n\r\n Errors found !","yDecode",0,MB_OK|MB_ERROR);
  1083.         }
  1084.  
  1085.     return(0);
  1086.     }
  1087.