home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume36 / unpost / part05 / uudec.c < prev   
Encoding:
C/C++ Source or Header  |  1993-04-18  |  8.3 KB  |  263 lines

  1. /******************************************************************************
  2. * Module    :   UUdecode --- Test for and decode a uuencoded text.
  3. *
  4. * Author    :   John W. M. Stevens
  5. ******************************************************************************/
  6.  
  7. #include    "compiler.h"
  8.  
  9. #include    "unpost.h"
  10. #include    "regexp.h"
  11. #include    "parse.h"
  12. #include    "uudec.h"
  13.  
  14. #define     DEC_CHAR(c)     (((c) - ' ') & 0x3f)
  15. #define     CHK_SUM_MASK    0x3f
  16.  
  17. static  int     FixBitNetTwiddleFlag = 0;
  18.  
  19. /*-----------------------------------------------------------------------------
  20. | Routine   :   UULnDec() --- UU decode a line.
  21. |
  22. | Inputs    :   LnLen   - Length of line.
  23. |               Line    - Pointer to the line buffer.
  24. | Outputs   :   Bfr     - Points to buffer for decoded output.
  25. -----------------------------------------------------------------------------*/
  26.  
  27. static
  28. int     UULnDec(int     LnLen,
  29.                 char    *Line,
  30.                 BYTE    *Bfr)
  31. {
  32.     register    int     i;
  33.     register    int     j;
  34.     auto        int     RecLen;
  35.     auto        int     tmp;
  36.     auto        int     Shift;
  37.  
  38.     /*  Zero out buffer.    */
  39.     RecLen = DEC_CHAR( *Line );
  40.     memset(Bfr, 0, RecLen);
  41.  
  42.     /*  Do actual line decoding.  Skip first character, as it is line
  43.     *   length.
  44.     */
  45.     for (i = 1, j = 0, Shift = 2;
  46.          i <= LnLen;
  47.          i++)
  48.     {
  49.         /*  Get six bits.   */
  50.         tmp = DEC_CHAR( Line[i] );
  51.  
  52.         /*  Put into buffer.    */
  53.         Bfr[j] |= tmp << Shift;
  54.         if (Shift > 2)
  55.             Bfr[j - 1] |= tmp >> (8 - Shift);
  56.  
  57.         /*  Increment byte pointer if neccesary.    */
  58.         if (Shift < 6)
  59.             j++;
  60.  
  61.         /*  Adjust shift size.  */
  62.         Shift = (Shift + 2) & 0x7;
  63.     }
  64.  
  65.     /*  Return size of buffer.  */
  66.     return( RecLen );
  67. }
  68.  
  69. /*-----------------------------------------------------------------------------
  70. | Routine   :   ChkUUChars() --- Check that a line of the proper length has
  71. |               the proper characters.
  72. |
  73. | Inputs    :   LnLen   - Length of line.
  74. |               Line    - Pointer to the line buffer.
  75. | Outputs   :   Line    - Pointer to the line buffer with fixes.
  76. |
  77. | Returns   :   Returns TRUE    - This is a uuencoded line.
  78. |                       FALSE   - This is not a uudecoded line.
  79. -----------------------------------------------------------------------------*/
  80.  
  81. static
  82. int     ChkUUChars(int  LnLen,
  83.                    char *Line)
  84. {
  85.     register    int     i;
  86.  
  87.     /*  Loop through line, checking that all characters are in proper
  88.     *   range.
  89.     */
  90.     for (i = 0; i < LnLen; i++)
  91.         if (Line[i] == '~' && FixBitNetTwiddleFlag)
  92.             Line[i] = '^';
  93.         else if (Line[i] < ' ' || Line[i] > '`')
  94.             return( NOT_UU_LINE );
  95.  
  96.     /*  Return that this is an encoded line.    */
  97.     return( IS_UU_LINE );
  98. }
  99.  
  100. /*-----------------------------------------------------------------------------
  101. | Routine   :   ChkUULine() --- Check to see if this is a UUencoded line.
  102. |
  103. | Inputs    :   Line    - Pointer to line buffer.
  104. | Outputs   :   RetStrs - Pointer to array of sub strings.
  105. |               EncLen  - Length of unencoded line in bytes.
  106. |
  107. | Returns   :   Returns IS_UU_LINE  - This is a uuencoded line.
  108. |                       NOT_UU_LINE - This is not a uuencoded line.
  109. |                       UU_SPACE    - This is a valid uuencoded empty line.
  110. |                       UU_BEGIN    - This is a uuencode begin line.
  111. |                       UU_END      - This is a uuencode end line.
  112. -----------------------------------------------------------------------------*/
  113.  
  114. CHK_UU_ENC  ChkUULine(char  *Line,
  115.                       char  ***RetStrs,
  116.                       int   *EncLen)
  117. {
  118.     auto        int     RecLen;
  119.     auto        int     BfrLen;
  120.  
  121.     /*  Check for a character in the range of 0x20 to 0x60 inclusive.   */
  122.     if ((*Line >= ' ' && *Line <= 'M') || *Line == '`')
  123.     {
  124.         /*  Get record length.  */
  125.         RecLen = DEC_CHAR( *Line );
  126.  
  127.         /*  Get line length.    */
  128.         BfrLen = strlen( Line );
  129.  
  130.         /*  Calculate the line length based on the record size character.   */
  131.         if (*Line == 'M')
  132.             *EncLen = 60;
  133.         else if (*Line == ' ' || *Line == '`')
  134.             *EncLen = 0;
  135.         else
  136.         {
  137.             /*  This is a short line, so calculate the lenght that it's
  138.             *   record length character says it should have.
  139.             *
  140.             *   The first calculation assumes that for any number of
  141.             *   bytes between 1 and 3 inclusive, that the UU encoder
  142.             *   always spits out four characters.
  143.             */
  144.             if (RecLen % 3)
  145.                 *EncLen = 4 * (RecLen / 3 + 1);
  146.             else
  147.                 *EncLen = 4 * (RecLen / 3);
  148.  
  149.             /*  If the UU encoder spits out less than four characters
  150.             *   for 1 or 2 bytes, then we need a different calculation.
  151.             */
  152.             if (BfrLen != *EncLen + 1 && BfrLen != *EncLen + 2)
  153.                 *EncLen = 4 * (RecLen / 3) + (RecLen % 3 + 1);
  154.         }
  155.  
  156.         /*  Check for short or long buffer. */
  157.         if (BfrLen != *EncLen + 1 && BfrLen != *EncLen + 2)
  158.             return( NOT_UU_LINE );
  159.  
  160.         /*  Check for the expected UU characters.   */
  161.         if (ChkUUChars(BfrLen, Line) == NOT_UU_LINE)
  162.             return( NOT_UU_LINE );
  163.  
  164.         /*  Return one of two different flags.    */
  165.         if (RecLen == 0)
  166.             return( UU_SPACE );
  167.         return( IS_UU_LINE );
  168.     }
  169.     else
  170.     {
  171.         /*  Test for a begin line.  */
  172.         if ( MatchBegin(Line, RetStrs) )
  173.             return( UU_BEGIN );
  174.  
  175.         /*  Test for end line.  */
  176.         if ( MatchEnd( Line ) )
  177.             return( UU_END );
  178.     }
  179.  
  180.     /*  This is not a UUencoded line.   */
  181.     return( NOT_UU_LINE );
  182. }
  183.  
  184. /*-----------------------------------------------------------------------------
  185. | Routine   :   DecUULine() --- Decode a UU encoded line.
  186. |
  187. | Inputs    :   Line    - Pointer to line buffer.
  188. | Outputs   :   Len     - Number of bytes in the buffer.
  189. |               Bfr     - Points to buffer for decoded output.
  190. |
  191. | Returns   :   Returns IS_UU_LINE  - This is a uuencoded line.
  192. |                       NOT_UU_LINE - This is not a uuencoded line.
  193. |                       UU_SPACE    - This is a valid uuencoded empty line.
  194. |                       UU_BEGIN    - This is a uuencode begin line.
  195. |                       UU_END      - This is a uuencode end line.
  196. -----------------------------------------------------------------------------*/
  197.  
  198. CHK_UU_ENC  DecUULine(char  *Line,
  199.                       int   *Len,
  200.                       BYTE  *Bfr)
  201. {
  202.     auto        int         EncLen;
  203.     auto        CHK_UU_ENC  UULnType;
  204.     auto        char        **RetStrs;
  205.  
  206.     /*  If this is not a uuencoded line, then it cannot be decoded.
  207.     *   Check it first.
  208.     */
  209.     *Len = 0;
  210.     UULnType = ChkUULine(Line, &RetStrs, &EncLen);
  211.     if (UULnType != IS_UU_LINE)
  212.         return( UULnType );
  213.  
  214.     /*  Do actual UU decode.    */
  215.     *Len = UULnDec(EncLen, Line, Bfr);
  216.  
  217.     /*  Return the type of line this is.    */
  218.     return( IS_UU_LINE );
  219. }
  220.  
  221. /*-----------------------------------------------------------------------------
  222. | Routine   :   DecTruncUULn() --- Decode a possibly truncated UU encoded
  223. |               line.
  224. |
  225. | Inputs    :   Line    - Pointer to line buffer.
  226. | Outputs   :   Len     - Number of bytes in the buffer.
  227. |               Bfr     - Points to buffer for decoded output.
  228. -----------------------------------------------------------------------------*/
  229.  
  230. void        DecTruncUULn(char   *Line,
  231.                          int    *Len,
  232.                          BYTE   *Bfr)
  233. {
  234.     register    int         i;
  235.     auto        int         RecLen;
  236.     auto        int         BfrLen;
  237.     auto        int         EncLen;
  238.  
  239.     /*  Get line length.    */
  240.     BfrLen = strlen( Line );
  241.  
  242.     /*  Calculate the line length.  */
  243.     RecLen = DEC_CHAR( *Line );
  244.     if (RecLen % 3)
  245.         EncLen = 4 * (RecLen / 3 + 1);
  246.     else
  247.         EncLen = 4 * (RecLen / 3);
  248.  
  249.     /*  If the actual line is shorter than the record length indicates
  250.     *   it ought to be, then pad with spaces.
  251.     */
  252.     if (BfrLen <= EncLen)
  253.     {
  254.         /*  Loop, putting spaces at end.    */
  255.         for (i = BfrLen; i <= EncLen; i++)
  256.             Line[i] = '`';
  257.         Line[i] = '\0';
  258.     }
  259.  
  260.     /*  Do actual UU line decode.   */
  261.     *Len = UULnDec(EncLen, Line, Bfr);
  262. }
  263.