/******************************************************************************
* Module : UUdecode --- Test for and decode a uuencoded text.
*
* Author : John W. M. Stevens
******************************************************************************/
#include "compiler.h"
#include "unpost.h"
#include "regexp.h"
#include "parse.h"
#include "uudec.h"
#define DEC_CHAR(c) (((c) - ' ') & 0x3f)
#define CHK_SUM_MASK 0x3f
static int FixBitNetTwiddleFlag = 0;
/*-----------------------------------------------------------------------------
| Routine : UULnDec() --- UU decode a line.
|
| Inputs : LnLen - Length of line.
| Line - Pointer to the line buffer.
| Outputs : Bfr - Points to buffer for decoded output.
-----------------------------------------------------------------------------*/
static
int UULnDec(int LnLen,
char *Line,
BYTE *Bfr)
{
register int i;
register int j;
auto int RecLen;
auto int tmp;
auto int Shift;
/* Zero out buffer. */
RecLen = DEC_CHAR( *Line );
memset(Bfr, 0, RecLen);
/* Do actual line decoding. Skip first character, as it is line
* length.
*/
for (i = 1, j = 0, Shift = 2;
i <= LnLen;
i++)
{
/* Get six bits. */
tmp = DEC_CHAR( Line[i] );
/* Put into buffer. */
Bfr[j] |= tmp << Shift;
if (Shift > 2)
Bfr[j - 1] |= tmp >> (8 - Shift);
/* Increment byte pointer if neccesary. */
if (Shift < 6)
j++;
/* Adjust shift size. */
Shift = (Shift + 2) & 0x7;
}
/* Return size of buffer. */
return( RecLen );
}
/*-----------------------------------------------------------------------------
| Routine : ChkUUChars() --- Check that a line of the proper length has
| the proper characters.
|
| Inputs : LnLen - Length of line.
| Line - Pointer to the line buffer.
| Outputs : Line - Pointer to the line buffer with fixes.
|
| Returns : Returns TRUE - This is a uuencoded line.
| FALSE - This is not a uudecoded line.
-----------------------------------------------------------------------------*/
static
int ChkUUChars(int LnLen,
char *Line)
{
register int i;
/* Loop through line, checking that all characters are in proper
* range.
*/
for (i = 0; i < LnLen; i++)
if (Line[i] == '~' && FixBitNetTwiddleFlag)
Line[i] = '^';
else if (Line[i] < ' ' || Line[i] > '`')
return( NOT_UU_LINE );
/* Return that this is an encoded line. */
return( IS_UU_LINE );
}
/*-----------------------------------------------------------------------------
| Routine : ChkUULine() --- Check to see if this is a UUencoded line.
|
| Inputs : Line - Pointer to line buffer.
| Outputs : RetStrs - Pointer to array of sub strings.
| EncLen - Length of unencoded line in bytes.
|
| Returns : Returns IS_UU_LINE - This is a uuencoded line.
| NOT_UU_LINE - This is not a uuencoded line.
| UU_SPACE - This is a valid uuencoded empty line.
| UU_BEGIN - This is a uuencode begin line.
| UU_END - This is a uuencode end line.
-----------------------------------------------------------------------------*/
CHK_UU_ENC ChkUULine(char *Line,
char ***RetStrs,
int *EncLen)
{
auto int RecLen;
auto int BfrLen;
/* Check for a character in the range of 0x20 to 0x60 inclusive. */
if ((*Line >= ' ' && *Line <= 'M') || *Line == '`')
{
/* Get record length. */
RecLen = DEC_CHAR( *Line );
/* Get line length. */
BfrLen = strlen( Line );
/* Calculate the line length based on the record size character. */
if (*Line == 'M')
*EncLen = 60;
else if (*Line == ' ' || *Line == '`')
*EncLen = 0;
else
{
/* This is a short line, so calculate the lenght that it's
* record length character says it should have.
*
* The first calculation assumes that for any number of
* bytes between 1 and 3 inclusive, that the UU encoder
* always spits out four characters.
*/
if (RecLen % 3)
*EncLen = 4 * (RecLen / 3 + 1);
else
*EncLen = 4 * (RecLen / 3);
/* If the UU encoder spits out less than four characters
* for 1 or 2 bytes, then we need a different calculation.
*/
if (BfrLen != *EncLen + 1 && BfrLen != *EncLen + 2)
*EncLen = 4 * (RecLen / 3) + (RecLen % 3 + 1);
}
/* Check for short or long buffer. */
if (BfrLen != *EncLen + 1 && BfrLen != *EncLen + 2)
return( NOT_UU_LINE );
/* Check for the expected UU characters. */
if (ChkUUChars(BfrLen, Line) == NOT_UU_LINE)
return( NOT_UU_LINE );
/* Return one of two different flags. */
if (RecLen == 0)
return( UU_SPACE );
return( IS_UU_LINE );
}
else
{
/* Test for a begin line. */
if ( MatchBegin(Line, RetStrs) )
return( UU_BEGIN );
/* Test for end line. */
if ( MatchEnd( Line ) )
return( UU_END );
}
/* This is not a UUencoded line. */
return( NOT_UU_LINE );
}
/*-----------------------------------------------------------------------------
| Routine : DecUULine() --- Decode a UU encoded line.
|
| Inputs : Line - Pointer to line buffer.
| Outputs : Len - Number of bytes in the buffer.
| Bfr - Points to buffer for decoded output.
|
| Returns : Returns IS_UU_LINE - This is a uuencoded line.
| NOT_UU_LINE - This is not a uuencoded line.
| UU_SPACE - This is a valid uuencoded empty line.
| UU_BEGIN - This is a uuencode begin line.
| UU_END - This is a uuencode end line.
-----------------------------------------------------------------------------*/
CHK_UU_ENC DecUULine(char *Line,
int *Len,
BYTE *Bfr)
{
auto int EncLen;
auto CHK_UU_ENC UULnType;
auto char **RetStrs;
/* If this is not a uuencoded line, then it cannot be decoded.
* Check it first.
*/
*Len = 0;
UULnType = ChkUULine(Line, &RetStrs, &EncLen);
if (UULnType != IS_UU_LINE)
return( UULnType );
/* Do actual UU decode. */
*Len = UULnDec(EncLen, Line, Bfr);
/* Return the type of line this is. */
return( IS_UU_LINE );
}
/*-----------------------------------------------------------------------------
| Routine : DecTruncUULn() --- Decode a possibly truncated UU encoded
| line.
|
| Inputs : Line - Pointer to line buffer.
| Outputs : Len - Number of bytes in the buffer.
| Bfr - Points to buffer for decoded output.
-----------------------------------------------------------------------------*/
void DecTruncUULn(char *Line,
int *Len,
BYTE *Bfr)
{
register int i;
auto int RecLen;
auto int BfrLen;
auto int EncLen;
/* Get line length. */
BfrLen = strlen( Line );
/* Calculate the line length. */
RecLen = DEC_CHAR( *Line );
if (RecLen % 3)
EncLen = 4 * (RecLen / 3 + 1);
else
EncLen = 4 * (RecLen / 3);
/* If the actual line is shorter than the record length indicates
* it ought to be, then pad with spaces.
*/
if (BfrLen <= EncLen)
{
/* Loop, putting spaces at end. */
for (i = BfrLen; i <= EncLen; i++)
Line[i] = '`';
Line[i] = '\0';
}
/* Do actual UU line decode. */
*Len = UULnDec(EncLen, Line, Bfr);
}
syntax highlighted by Code2HTML, v. 0.9.1