📄 smread.c
字号:
* an "extra" block or the second header?
* Note from the programmer: Notice the goto statement.
* Normally I don't like them, but in this case it really works.
*/
if (readCtx->unprocessedData.len ==
VOLT_SECURE_MAIL_BEGIN_BLOCK_LEN + newLineLen)
{
/* If this is the third header (no second header), skip to the
* next part of the read.
*/
if (Z2Memcmp (
readCtx->unprocessedData.data, beginBlk,
VOLT_SECURE_MAIL_BEGIN_BLOCK_LEN) == 0)
{
/* Set up for reading the next part.
*/
status = 0;
readCtx->unprocessedData.len = 0;
goto VoltSecureMailBase64 ;
}
}
/* This is an "extra" header, just Copy it to the extraHeader
* field in the context. Copy the NULL-terminating character as
* well.
*/
status = VT_ERROR_MEMORY;
readCtx->extraHeader.data = (unsigned char *)Z2Realloc (
readCtx->extraHeader.data, readCtx->unprocessedData.len + readCtx->extraHeader.len);
if (readCtx->extraHeader.data == (unsigned char *)0)
break;
Z2Memcpy (
readCtx->extraHeader.data + readCtx->extraHeader.len, readCtx->unprocessedData.data,
readCtx->unprocessedData.len);
readCtx->extraHeader.len += readCtx->unprocessedData.len;
readCtx->unprocessedData.len = 0;
status = 0;
/* If there's no more message to read, return.
*/
if (currentMessageLen == 0)
break;
/* There's more message to read, but we haven't read the BEGIN
* BLOCK header yet, so keep performing this part until we have.
*/
goto VoltSecureMailReadHeader2;
VoltSecureMailBase64:
obj->state = VOLT_SECURE_MAIL_STATE_READ_B64_LEN;
readCtx->unprocessedData.len = 0;
/* If there's no more message to read, return.
*/
if (currentMessageLen == 0)
break;
case VOLT_SECURE_MAIL_STATE_READ_B64_LEN:
/* Any data we read now will be regular message data.
* First, Base64 decode it, then send it to the p7EnvelopedData
* object to read, then any output is sent to the p7SignedData
* object to read.
* Eventually we'll run out of message material and hit the
* footers. We don't want to pass the footers to the Base64
* decoder, so we'll have to check input to make sure the line is
* not a footer.
* What we need to do is decode the first line of the message,
* then we'll have the length of the EnvelopedData.
*/
VoltSecureMailStateReadB64Len:
status = VoltSMGetNextBlock (
obj, &(readCtx->unprocessedData), currentMessage, currentMessageLen,
1, &amountRead, &completeFlag, &newLineLen);
if (status != 0)
break;
*bytesRead += amountRead;
if (completeFlag == 0)
break;
currentMessage = message + *bytesRead;
currentMessageLen = messageLen - *bytesRead;
/* this is to handle the situation where there might have been
* empty new lines either inserted deliberately or by accident
* between -----BEGIN VOLTAGE SECURE BLOCK V1----- block and
* the beginning of the base64 encoded data. Skip all those lines.
*/
if ( (amountRead == newLineLen) &&
(readCtx->unprocessedData.len == 0) )
{
goto VoltSecureMailStateReadB64Len;
}
VoltSecureMailBase64A:
/* Set inputLen to the number of bytes read so far.
*/
obj->inputLen = readCtx->unprocessedData.len;
/* Determine the input and output block sizes of the message.
* First, how many spaces are there to lead off a line?
*/
index = 0;
preSpaceLen = 0;
while (readCtx->unprocessedData.data[index++] == ' ')
preSpaceLen++;
/* How many actual base64 bytes? Don't count spaces or new lines.
*/
valueLen = readCtx->unprocessedData.len - preSpaceLen - newLineLen;
valueLen /= 4;
inBlockLen = valueLen * 3;
/* For each block of input, there will be one line of output,
* which includes space characters and new lines.
*/
outBlockLen = readCtx->unprocessedData.len;
/* Decode this line.
*/
status = DoDecodeUpdateOrFinal (
obj, readCtx, 1, readCtx->unprocessedData.data,
readCtx->unprocessedData.len);
if (status != 0)
break;
/* Get the length of the EnvelopedData.
*/
status = VoltDecodeTagAndLen (
readCtx->unprocessedData.data, readCtx->unprocessedData.len,
&theTag, &lengthLen, &valueLen);
if (status != 0)
break;
/* The length of the entire EnvelopedData is the valueLen plus
* the lengthLen plus the length of the tag (1).
*/
valueLen += (lengthLen + 1);
/* Now determine how long the Base64 encoding of that much data
* will be. First, how many full blocks of input will there be?
*/
inBlocks = valueLen / inBlockLen;
/* How many output bytes will that be? Use lengthLen as a temp
* variable.
*/
lengthLen = inBlocks * outBlockLen;
/* How many bytes in the last line?
*/
leftovers = inBlocks * inBlockLen;
leftovers = valueLen - leftovers;
/* If there are any leftovers, there will be a new line, but
* we'll count number of bytes without the new line characters.
* So if there is going to be another line, add the new line
* characters now.
*/
if (leftovers != 0)
obj->dataLen += newLineLen;
/* How many blocks of 3?
*/
inBlocks = leftovers / 3;
/* For each block of three, there is four bytes of output.
* So far, the total output is the number of full blocks
* (currently in lengthLen) and the leftover blcoks of 3 expanded
* to 4.
*/
valueLen = lengthLen + (inBlocks * 4);
/* How many bytes left over? If there are any bytes left over,
* the encoder will pad to one more block.
*/
inBlocks *= 3;
leftovers -= inBlocks;
if (leftovers != 0)
valueLen += 4;
/* Add in the number of bytes for the last line. Include the
* spaces.
*/
obj->dataLen += valueLen + preSpaceLen;
/* Set the state for the next read. We have data in the
* unprocessedData buffer that needs to go to the Envelope
* object, so set the state for that.
*/
obj->state = VOLT_SECURE_MAIL_STATE_READ_ENV;
goto VoltSecureMailStateReadEnv;
VoltSecureMailStateReadB64:
/* If there's no more message to read, return.
*/
if (currentMessageLen == 0)
break;
case VOLT_SECURE_MAIL_STATE_READ_B64:
/* Read the Base64 data. If the caller passed in data beyond the
* end of the base64 data, don't read it yet.
*/
valueLen = obj->dataLen - obj->inputLen;
if (valueLen > currentMessageLen)
valueLen = currentMessageLen;
/* Decode the data.
*/
status = DoDecodeUpdateOrFinal (
obj, readCtx, obj->dataLen - valueLen, currentMessage, valueLen);
if (status != 0)
break;
obj->inputLen += valueLen;
*bytesRead += valueLen;
currentMessage = message + *bytesRead;
currentMessageLen = messageLen - *bytesRead;
/* The state upon return is either READ_ENV or READ_B64. If
* READ_B64, we've read all the input and there's no more
* processing on it that we can do.
*/
if (obj->state != VOLT_SECURE_MAIL_STATE_READ_ENV)
{
/* If inputLen and dataLen are equal, that means we've read all
* the base64 data. Because the Decode did not set the state to
* READ_ENV, that means there's no more enveloped data (and
* hence no more signed data) to read. Next up:
* VOLT_SECURE_MAIL_STATE_READ_FOOTER_1.
*/
if (obj->dataLen != obj->inputLen)
break;
obj->state = VOLT_SECURE_MAIL_STATE_READ_FOOTER_1;
if (currentMessageLen == 0)
break;
goto VoltSecureMailStateReadFooter1;
}
VoltSecureMailStateReadEnv:
case VOLT_SECURE_MAIL_STATE_READ_ENV:
/* Read the data in the unprocessedData buffer as EnvelopedData.
*/
status = DoEnvelopeRead (obj, readCtx, 1);
if (status != 0)
break;
/* Upon return, the state should be either READ_SIGNED or READ_B64.
*/
if (obj->state == VOLT_SECURE_MAIL_STATE_READ_B64)
goto VoltSecureMailStateReadB64;
case VOLT_SECURE_MAIL_STATE_READ_SIGNED:
status = VoltSMDoSignedDataRead (
obj, readCtx, 1, outputData, bufferSize, outputDataLen);
if (status != 0)
break;
/* If this call read everything in the unprocessedData buffer,
* then there will need to be some more B64 data to read to get
* the next bytes.
*/
obj->state = VOLT_SECURE_MAIL_STATE_READ_B64;
/* At this point, there is either no more data to process, or the
* data to process is footer material.
*/
if (obj->inputLen == obj->dataLen)
obj->state = VOLT_SECURE_MAIL_STATE_READ_FOOTER_1;
/* If there's no more message to read, return.
*/
if (currentMessageLen == 0)
break;
VoltSecureMailStateReadFooter1:
case VOLT_SECURE_MAIL_STATE_READ_FOOTER_1:
/* We're expecting to see
* -----END VOLTAGE SECURE BLOCK V1-----
* Unless this is ZDM attachment.
*/
if (obj->formatType == VOLT_MESSAGE_FORMAT_ZDM_ATTACHMENT)
goto VoltSecureMailStateReadEnvFinal;
status = VoltSMGetNextBlock (
obj, &(readCtx->unprocessedData), currentMessage, currentMessageLen,
8, &amountRead, &completeFlag, &newLineLen);
if (status != 0)
break;
*bytesRead += amountRead;
if (completeFlag == 0)
break;
currentMessage = message + *bytesRead;
currentMessageLen = messageLen - *bytesRead;
/* This code is to handle the situation when there are
* unexpected new lines between the end of the base64 encoded
* data and the beginning of the block
* -----END VOLTAGE SECURE BLOCK V1-----. We don't want to fail
* if this situation arises accidently. So skip all the extra empty
* lines until we find something meaningful.
*/
if ( (amountRead == newLineLen) &&
(readCtx->unprocessedData.data[0] == 0) )
{
readCtx->unprocessedData.len = 0;
goto VoltSecureMailStateReadFooter1;
}
/* We have the next block in the unprocessedData buffer, is this
* the block we expect?
*/
status = VT_ERROR_INVALID_SECURE_MAIL_MSG;
if (readCtx->unprocessedData.len != VOLT_SECURE_MAIL_END_BLOCK_LEN + newLineLen)
break;
if (Z2Memcmp (
readCtx->unprocessedData.data, endBlk,
VOLT_SECURE_MAIL_END_BLOCK_LEN) != 0)
break;
/* Set up the context for the next block.
*/
status = 0;
readCtx->unprocessedData.len = 0;
obj->state = VOLT_SECURE_MAIL_STATE_READ_FOOTER_2;
/* If there's no more message to read, return.
*/
if (currentMessageLen == 0)
break;
VoltSecureMailStateReadFooter2:
case VOLT_SECURE_MAIL_STATE_READ_FOOTER_2:
/* We're expecting to see
* -----END VOLTAGE SECURE MESSAGE V1-----
*/
status = VoltSMGetNextBlock (
obj, &(readCtx->unprocessedData), currentMessage, currentMessageLen,
24, &amountRead, &completeFlag, &newLineLen);
if (status != 0)
break;
*bytesRead += amountRead;
if (completeFlag == 0)
break;
currentMessage = message + *bytesRead;
currentMessageLen = messageLen - *bytesRead;
/* This code is to handle the situation when there are
* unexpected new lines between the block
* -----END VOLTAGE SECURE BLOCK V1-----. and the block
* -----END VOLTAGE MESSAGE BLOCK V1-----.
* We don't want to fail if this situation arises accidently.
* So skip all the extra empty lines until we find something
* meaningful.
*/
if ( (amountRead == newLineLen) &&
(readCtx->unprocessedData.len == 0) )
{
goto VoltSecureMailStateReadFooter2;
}
/* We have the next block in the unprocessedData buffer, is this
* the block we expect?
*/
status = VT_ERROR_INVALID_SECURE_MAIL_MSG;
if (readCtx->unprocessedData.len != VOLT_SECURE_MAIL_END_MESSAGE_LEN + newLineLen)
break;
if (Z2Memcmp (
readCtx->unprocessedData.data, endMsg,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -