/**************************************************************************
*** COPYRIGHT (c) 2002 by TransNexus, Inc. ***
*** ***
*** This software is property of TransNexus, Inc. ***
*** This software is freely available under license from TransNexus. ***
*** The license terms and conditions for free use of this software by ***
*** third parties are defined in the OSP Toolkit Software License ***
*** Agreement (LICENSE.txt). Any use of this software by third ***
*** parties, which does not comply with the terms and conditions of the ***
*** OSP Toolkit Software License Agreement is prohibited without ***
*** the prior, express, written consent of TransNexus, Inc. ***
*** ***
*** Thank you for using the OSP ToolKit(TM). Please report any bugs, ***
*** suggestions or feedback to support@transnexus.com ***
*** ***
**************************************************************************/
/*
* ospmime.cpp - mime stuff
*/
#include "osp/ospmime.h"
void
OSPPMimeBodyFree(
OSPTMIMEBODY *ospvMimeBody)
{
int count = 0;
OSPM_DBGENTER(("ENTER: OSPPMimeBodyFree()\n"));
if(ospvMimeBody != (OSPTMIMEBODY *)NULL)
{
if(ospvMimeBody->Boundary != (OSPTMIMEPART *)NULL)
{
OSPPMimePartFree(ospvMimeBody->Boundary);
}
while(count < OSPC_MAX_BODYPARTS)
{
if(ospvMimeBody->BodyParts[count] != (OSPTMIMEPART *)NULL)
{
OSPPMimePartFree(ospvMimeBody->BodyParts[count]);
}
count++;
}
}
OSPM_DBGEXIT(("EXIT : OSPPMimeBodyFree()\n"));
return;
}
int
OSPPMimeBodyPartsParse(
OSPTMIMEPART *ospvBodyData,
OSPTMIMEBODY *ospvMimeBody,
OSPTMIMEPART *ospvBoundary)
{
int errorcode = OSPC_ERR_NO_ERROR;
unsigned char *buf = ospvBodyData->Content;
unsigned currpos = 0;
unsigned bufend = ospvBodyData->Length;
unsigned start = 0;
int found = 0, bfound = 0;
int bresult = -1;
OSPTMIMEPART header;
int partsfound=0;
OSPM_DBGENTER(("ENTER: OSPPMimeBodyPartsParse() bufend == [%d] buf = [%*s]\n",
bufend, bufend, (char *)buf));
OSPM_MEMSET(&header, 0, sizeof(OSPTMIMEPART));
/* strip off body parts, send to parser */
while((partsfound < OSPC_MAX_BODYPARTS) && (currpos < bufend))
{
/* if there is no boundary set, we have text/plain */
if((ospvBoundary != OSPC_OSNULL) &&
(ospvBoundary->Content != OSPC_OSNULL))
{
while((currpos < bufend) &&
(!found))
{
if(buf[currpos] == ospvBoundary->Content[0])
{
/* make sure we really are at the boundary */
bresult = OSPM_MEMCMP(&buf[currpos], ospvBoundary->Content,
ospvBoundary->Length);
if(bresult == 0)
{
found = 1;
break;
}
}
currpos++;
} /* end while(currpos < bufend... */
if(found)
{
/* get past the boundary, CRLF */
currpos += ospvBoundary->Length;
while(currpos < bufend)
{
if((buf[currpos] != '\n') &&
(buf[currpos] != ' ') &&
(buf[currpos] != '\t') &&
(buf[currpos] != '\r'))
{
bfound = 1;
break;
}
currpos++;
}
if(bfound)
{
int cresult = -1;
start = currpos;
/* get to the next boundary (CRLF--boundary) */
while(currpos < bufend)
{
if((buf[currpos] == '\r') &&
(currpos+3 < bufend) &&
(buf[currpos+1] == '\n') &&
(buf[currpos + 2] == '-') &&
(buf[currpos + 3] == '-'))
{
/* make sure we really are at the boundary */
cresult = OSPM_MEMCMP(&buf[currpos+4], ospvBoundary->Content,
ospvBoundary->Length);
if(cresult == 0)
{
/* move past the CRLF */
currpos+=2;
break;
}
}
currpos++;
}
}
}
}
else
{
/* get to the next CRLFCRLF (CRLFCRLF) */
while(currpos < bufend)
{
if((buf[currpos] == '\r') &&
(currpos+3 < bufend) &&
(buf[currpos+1] == '\n') &&
(buf[currpos + 2] == '\r') &&
(buf[currpos + 3] == '\n'))
{
/*now we are in the right spot */
break;
}
currpos++;
}
start = currpos;
/* set currpos to bufend, so we can parse the whole buffer. this is text/plain */
currpos = bufend;
}
if(currpos <= bufend)
{
OSPM_MALLOC(ospvMimeBody->BodyParts[partsfound],
OSPTMIMEPART,
sizeof(OSPTMIMEPART));
if(ospvMimeBody->BodyParts[partsfound] != (OSPTMIMEPART *)NULL)
{
OSPM_MEMSET(ospvMimeBody->BodyParts[partsfound],
0,
sizeof(ospvMimeBody->BodyParts[partsfound]));
errorcode = OSPPMimeBufferParse(
&buf[start],
currpos - start,
&header,
ospvMimeBody->BodyParts[partsfound]);
if (header.Content)
{
OSPM_FREE(header.Content);
header.Content = OSPC_OSNULL;
}
if(errorcode == OSPC_ERR_NO_ERROR)
{
partsfound++;
found = 0;
bfound = 0;
}
else
{
break;
}
}
else
{
errorcode = OSPC_ERR_MIME_MALLOC_FAILED;
OSPM_DBGERRORLOG(errorcode, "malloc failed for body part");
break;
}
}
}
if(errorcode == OSPC_ERR_NO_ERROR)
{
ospvMimeBody->NumBodyParts = partsfound;
}
OSPM_DBGEXIT(("EXIT : OSPPMimeBodyPartsParse()\n"));
return errorcode;
}
/* Pulls apart header from body */
int
OSPPMimeBufferParse(
unsigned char *ospvInputbuffer, /* In - buffer to be parsed */
unsigned ospvSizeOfInputbuffer, /* In - size of buffer to be parsed */
OSPTMIMEPART *ospvHeader, /* Out - Mime header data */
OSPTMIMEPART *ospvBody) /* Out - Mime body data */
{
unsigned char* buffin = ospvInputbuffer;
unsigned buffinend = ospvSizeOfInputbuffer;
unsigned currpos = 0;
unsigned hdrstart = 0;
unsigned hdrlen = 0;
unsigned bdystart = 0;
unsigned bdylen = 0;
int errorcode = OSPC_ERR_NO_ERROR;
OSPM_DBGENTER(("ENTER: OSPPMimeBufferParse()\n"));
/* If first character is a LF (ANSI C or UNIX)
* or if first two characters are CR LF (MIME or DOS),
* there are no headers.
*/
if ((currpos < buffinend) && (buffin[currpos] != '\n')
&& ! ((buffin[currpos] == '\r') && (currpos+1 < buffinend)
&& (buffin[currpos+1] == '\n')))
{
while (currpos < buffinend)
{
/* Is it LF LF ? */
if ((buffin[currpos] == '\n')
&& (currpos+1 < buffinend)
&& (buffin[currpos+1] == '\n'))
{
++hdrlen;
++currpos;
break;
}
/* Is it CR LF CR LF? */
else if ((buffin[currpos] == '\r')
&& (currpos+3 < buffinend)
&& (buffin[currpos+1] == '\n')
&& (buffin[currpos+2] == '\r')
&& (buffin[currpos+3] == '\n'))
{
hdrlen += 2;
currpos += 2;
break;
}
++currpos;
++hdrlen;
}
}
errorcode = OSPPUtilMallocAndCopySubString(ospvInputbuffer,
&(ospvHeader->Content),
hdrstart,
hdrlen);
ospvHeader->Length = hdrlen;
if(errorcode == OSPC_ERR_NO_ERROR)
{
/* Skip blank line
* LF (ANSI C or UNIX)
*/
if (currpos < buffinend && buffin[currpos] == '\n')
{
++currpos;
}
/* CR LF (MIME or DOS) */
else if (currpos < buffinend && buffin[currpos] == '\r'
&& currpos+1 < buffinend && buffin[currpos+1] == '\n')
{
currpos += 2;
}
bdystart = currpos;
bdylen = ospvSizeOfInputbuffer;
/* get rid of whitspace, CRLFs at end of body string */
while (bdylen > bdystart)
{
if ((!isspace(buffin[bdylen-1])) &&
(buffin[bdylen-1] != '\n') &&
(buffin[bdylen-1] != '\r'))
{
break;
}
--bdylen;
}
bdylen = bdylen - bdystart;
errorcode = OSPPUtilMallocAndCopySubString(ospvInputbuffer,
&(ospvBody->Content),
bdystart,
bdylen);
ospvBody->Length = bdylen;
}
OSPM_DBGEXIT(("EXIT : OSPPMimeBufferParse()\n"));
return errorcode;
}
void
OSPPMimeDataFree(
OSPTMIMEMSG *ospvMessage)
{
OSPM_DBGENTER(("ENTER: OSPPMimeDataFree()\n"));
OSPPMimePartFree(ospvMessage->MsgPart);
OSPPMimePartFree(ospvMessage->SigPart);
OSPM_DBGEXIT(("EXIT : OSPPMimeDataFree()\n"));
return;
}
void
OSPPMimeFieldFree(
OSPTMIMEFIELD *ospvField)
{
int count = 0;
OSPM_DBGENTER(("ENTER: OSPPMimeFieldFree()\n"));
if(ospvField != (OSPTMIMEFIELD *)NULL)
{
if(ospvField->Params != (OSPTMIMEPARAM **)NULL)
{
for(count = 0; count < OSPC_MAX_PARAMS;count++)
{
if(ospvField->Params[count] != (OSPTMIMEPARAM *)NULL)
{
OSPPMimeParamFree(ospvField->Params[count]);
OSPM_FREE(ospvField->Params[count]);
ospvField->Params[count] = NULL;
}
}
}
}
OSPM_DBGEXIT(("EXIT : OSPPMimeFieldFree()\n"));
return;
}
int
OSPPMimeMessageBuild(
OSPTMIMEMSG *ospvMessage,
unsigned char **ospvMimeOut,
unsigned *ospvSizeOfMimeOut)
{
int errorcode = OSPC_ERR_NO_ERROR;
unsigned char *next = NULL;
char msgtmp[20];
char sigtmp[20];
int boundln = 0,
mshdrln = 0,
msszln = 0,
sighdrln = 0,
sigszln = 0,
count = 0,
numdelims = 0,
numcrlfs = 0;
if(ospvMessage->SigPart->Length > 0)
{
msszln = sprintf(msgtmp, "%d", ospvMessage->MsgPart->Length);
mshdrln = strlen(OSPC_MIME_MSG_HEADER);
boundln = strlen(OSPC_MIME_BOUNDARY);
sigszln = sprintf(sigtmp, "%d", ospvMessage->SigPart->Length),
sighdrln = strlen(OSPC_MIME_SIG_HEADER);
numdelims = 4;
numcrlfs = 12;
}
OSPM_DBGENTER(("ENTER: OSPPMimeMessageBuild()\n"));
count = (boundln*3) +
mshdrln +
msszln +
ospvMessage->MsgPart->Length +
sighdrln +
sigszln +
ospvMessage->SigPart->Length +
2*numdelims +
2*numcrlfs; /* CRLFs, boundary delimiters */
ospvMessage->Length = count;
*ospvSizeOfMimeOut = ospvMessage->Length;
OSPM_MALLOC(*ospvMimeOut,
unsigned char,
*ospvSizeOfMimeOut);
if(*ospvMimeOut != (unsigned char *)NULL)
{
OSPM_MEMSET(*ospvMimeOut,
0,
*ospvSizeOfMimeOut);
next = *ospvMimeOut;
if(ospvMessage->SigPart->Length > 0)
{
/* CRLF for beginning of boundary */
OSPM_MEMCPY(next,
OSPC_MIME_CRLF,
2);
next += 2;
/* -- for start of boundary */
OSPM_MEMCPY(next,
OSPC_MIME_BOUNDARY_DELIM,
2);
next += 2;
/* boundary */
OSPM_MEMCPY(next,
OSPC_MIME_BOUNDARY,
boundln);
next += boundln;
/* CRLF */
OSPM_MEMCPY(next,
OSPC_MIME_CRLF,
2);
next += 2;
/* Message header */
OSPM_MEMCPY(next,
OSPC_MIME_MSG_HEADER,
mshdrln);
next += mshdrln;
/* Message length */
OSPM_MEMCPY(next,
msgtmp,
msszln);
next+=msszln;
/* CRLF for end of message header */
OSPM_MEMCPY(next,
OSPC_MIME_CRLF,
2);
next += 2;
/* CRLF for beginning of message */
OSPM_MEMCPY(next,
OSPC_MIME_CRLF,
2);
next += 2;
}
/* Message content */
OSPM_MEMCPY(next,
ospvMessage->MsgPart->Content,
ospvMessage->MsgPart->Length);
next+=ospvMessage->MsgPart->Length;
if(ospvMessage->SigPart->Length > 0)
{
/* CRLF for end of message body */
OSPM_MEMCPY(next,
OSPC_MIME_CRLF,
2);
next += 2;
/* CRLF for beginning of boundary */
OSPM_MEMCPY(next,
OSPC_MIME_CRLF,
2);
next += 2;
/* -- for start of boundary */
OSPM_MEMCPY(next,
OSPC_MIME_BOUNDARY_DELIM,
2);
next += 2;
/* boundary */
OSPM_MEMCPY(next,
OSPC_MIME_BOUNDARY,
boundln);
next += boundln;
/* CRLF for end of boundary */
OSPM_MEMCPY(next,
OSPC_MIME_CRLF,
2);
next += 2;
/* Signature Header */
OSPM_MEMCPY(next,
OSPC_MIME_SIG_HEADER,
sighdrln);
next += sighdrln;
/* Signature length */
OSPM_MEMCPY(next,
sigtmp,
sigszln);
next+=sigszln;
/* CRLF for end of signature header */
OSPM_MEMCPY(next,
OSPC_MIME_CRLF,
2);
next += 2;
/* CRLF for beginning of content */
OSPM_MEMCPY(next,
OSPC_MIME_CRLF,
2);
next += 2;
/* Signature content */
OSPM_MEMCPY(next,
ospvMessage->SigPart->Content,
ospvMessage->SigPart->Length);
next+=ospvMessage->SigPart->Length;
/* CRLF for end of signature body */
OSPM_MEMCPY(next,
OSPC_MIME_CRLF,
2);
next += 2;
/* CRLF for start of boundary */
OSPM_MEMCPY(next,
OSPC_MIME_CRLF,
2);
next += 2;
/* -- for start of boundary */
OSPM_MEMCPY(next,
OSPC_MIME_BOUNDARY_DELIM,
2);
next += 2;
/* boundary */
OSPM_MEMCPY(next,
OSPC_MIME_BOUNDARY,
boundln);
next += boundln;
/* -- for end of final boundary */
OSPM_MEMCPY(next,
OSPC_MIME_BOUNDARY_DELIM,
2);
next += 2;
/* CRLF for end of boundary */
OSPM_MEMCPY(next,
OSPC_MIME_CRLF,
2);
next += 2;
}
}
OSPM_DBGEXIT(("EXIT : OSPPMimeMessageBuild()\n"));
return errorcode;
}
int
OSPPMimeMessageCreate(
unsigned char *ospvMessage,
unsigned ospvSizeOfMessage,
unsigned char *ospvSignature,
unsigned ospvSizeOfSignature,
unsigned char **ospvMimeMessage,
unsigned *ospvSizeOfMimeMessage)
{
int errorcode = OSPC_ERR_NO_ERROR;
OSPTMIMEMSG msg;
OSPM_DBGENTER(("ENTER: OSPPMimeMessageCreate()\n"));
/* Initialize the structure to hold the Mime message data */
errorcode = OSPPMimeMessageInit(&msg);
/* Set up the message and signature parts. We will use this function for the
* signature part as well when we get a real signature in */
if(errorcode == OSPC_ERR_NO_ERROR)
{
errorcode = OSPPMimeMessageSetContentAndLength(msg.MsgPart, ospvMessage, ospvSizeOfMessage);
}
if((errorcode == OSPC_ERR_NO_ERROR) && (ospvSignature != OSPC_OSNULL))
{
errorcode = OSPPMimeMessageSetContentAndLength(msg.SigPart, ospvSignature, ospvSizeOfSignature);
}
/* Build the MIME message */
if(errorcode == OSPC_ERR_NO_ERROR)
{
errorcode = OSPPMimeMessageBuild(&msg, ospvMimeMessage, ospvSizeOfMimeMessage);
}
/* Free the structure holding the message data */
OSPPMimeDataFree(&msg);
OSPM_DBGEXIT(("EXIT : OSPPMimeMessageCreate()\n"));
return errorcode;
}
int
OSPPMimeMessageInit(
OSPTMIMEMSG *ospvMessage)
{
int errorcode = OSPC_ERR_NO_ERROR;
OSPM_DBGENTER(("ENTER: OSPPMimeMessageInit()\n"));
if(ospvMessage != (OSPTMIMEMSG *)NULL)
{
OSPM_MEMSET(ospvMessage,
0,
sizeof(OSPTMIMEMSG));
}
else
{
errorcode = OSPC_ERR_MIME_VAR_NOT_FOUND;
OSPM_DBGERRORLOG(errorcode, "no pointer found for mime message");
}
if(errorcode == OSPC_ERR_NO_ERROR)
{
OSPM_MALLOC(ospvMessage->MsgPart,
OSPTMIMEPART,
sizeof(OSPTMIMEPART));
if(ospvMessage->MsgPart == (OSPTMIMEPART *)NULL)
{
errorcode = OSPC_ERR_MIME_MALLOC_FAILED;
OSPM_DBGERRORLOG(errorcode, "can't malloc message part");
}
else
{
OSPM_MEMSET(ospvMessage->MsgPart,
0,
sizeof(OSPTMIMEPART));
}
if(errorcode == OSPC_ERR_NO_ERROR)
{
OSPM_MALLOC(ospvMessage->SigPart,
OSPTMIMEPART,
sizeof(OSPTMIMEPART));
if(ospvMessage->SigPart == (OSPTMIMEPART *)NULL)
{
errorcode = OSPC_ERR_MIME_MALLOC_FAILED;
OSPM_DBGERRORLOG(errorcode, "can't malloc signature part");
}
else
{
OSPM_MEMSET(ospvMessage->SigPart,
0,
sizeof(OSPTMIMEPART));
}
}
if(errorcode == OSPC_ERR_NO_ERROR)
{
ospvMessage->Length = strlen(OSPC_MIME_MSG_HEADER) + strlen(OSPC_MIME_SIG_HEADER);
ospvMessage->NumParts = 2;
}
}
OSPM_DBGEXIT(("EXIT : OSPPMimeMessageInit()\n"));
return errorcode;
}
int
OSPPMimeMessageParse(
unsigned char *ospvMessageBuffer,
unsigned ospvSizeOfMessageBuffer,
unsigned char *ospvContent,
unsigned ospvSizeOfContent,
unsigned char **ospvMessageData,
unsigned *ospvSizeOfMessageData,
unsigned char **ospvSignatureData,
unsigned *ospvSizeOfSignatureData)
{
int errorcode = OSPC_ERR_NO_ERROR,
result = -1;
OSPTMIMEFIELD content;
OSPTMIMEBODY mimebody;
OSPTMIMEPART boundary, body;
unsigned currpos = 0;
OSPM_DBGENTER(("ENTER: OSPPMimeMessageParse()\n"));
OSPM_MEMSET(&mimebody, 0, sizeof(OSPTMIMEBODY));
OSPM_MEMSET(&body, 0, sizeof(OSPTMIMEPART));
OSPM_MEMSET(&boundary, 0, sizeof(OSPTMIMEPART));
OSPM_MEMSET(&content, 0, sizeof(OSPTMIMEFIELD));
/* Make sure we have only the field body without the field name.*/
while((isspace(ospvContent[currpos])) &&
(currpos < ospvSizeOfContent))
{
currpos++;
}
/* if we find a 'c' we have the field name. Get past it */
if(tolower(ospvContent[currpos]) == 'c')
{
while(currpos < ospvSizeOfContent)
{
if(ospvContent[currpos] == ':')
{
break;
}
currpos++;
}
/* get past the ':' */
currpos++;
}
/* Is there anything left? If so, get to the chars */
if(currpos < ospvSizeOfContent)
{
while((isspace(ospvContent[currpos])) &&
(currpos < ospvSizeOfContent))
{
currpos++;
}
}
content.FieldBody.Content = &ospvContent[currpos];
content.FieldBody.Length = ospvSizeOfContent - currpos;
body.Content = ospvMessageBuffer;
body.Length = ospvSizeOfMessageBuffer;
/* Make sure all the parameters meet our criteria, and copy
* the ones we intend to keep into their places
*/
if(errorcode == OSPC_ERR_NO_ERROR)
{
errorcode = OSPPMimeVerifyParameters(&content, &boundary, OSPC_MAIN);
}
/* Pull out the body parts, i.e. the message and the signature */
if(errorcode == OSPC_ERR_NO_ERROR)
{
errorcode = OSPPUtilMemCaseCmp(content.FieldBody.Content,
content.FieldBody.Length,
"text/plain",
strlen("text/plain"),
&result);
if((errorcode == OSPC_ERR_NO_ERROR) &&
(result == 0))
{
/* Possible Optimization -
* When it is not a multibody message, there is no need to allocate memory
* for mimebody.BodyParts[0], we can just set - mimebody.NumBodyParts = 1
* and that will do. Allocating memory for the 0th element is not required.
*/
OSPM_MALLOC(mimebody.BodyParts[0],
OSPTMIMEPART,
sizeof(OSPTMIMEPART));
if(mimebody.BodyParts[0] != (OSPTMIMEPART *)NULL)
{
OSPM_MEMSET(mimebody.BodyParts[0],
0,
sizeof(mimebody.BodyParts[0]));
mimebody.BodyParts[0]->Content = ospvMessageBuffer;
mimebody.BodyParts[0]->Length = ospvSizeOfMessageBuffer;
mimebody.NumBodyParts = 1;
}
}
else
{
errorcode = OSPPMimeBodyPartsParse(&body, &mimebody, &boundary);
}
}
/* Copy the body parts into the buffers to be sent back. Set the length of each */
if(errorcode == OSPC_ERR_NO_ERROR)
{
if(mimebody.NumBodyParts > 0)
{
errorcode = OSPPUtilMallocAndCopySubString(mimebody.BodyParts[0]->Content,
ospvMessageData,
0,
mimebody.BodyParts[0]->Length);
if(errorcode == OSPC_ERR_NO_ERROR)
{
*ospvSizeOfMessageData = mimebody.BodyParts[0]->Length;
if(mimebody.NumBodyParts > 1 )
{
errorcode = OSPPUtilMallocAndCopySubString(mimebody.BodyParts[1]->Content,
ospvSignatureData,
0,
mimebody.BodyParts[1]->Length);
if(errorcode == OSPC_ERR_NO_ERROR)
{
*ospvSizeOfSignatureData = mimebody.BodyParts[1]->Length;
}
}
}
}
else
{
errorcode = OSPC_ERR_MIME_MSG_PARTS_NOT_FOUND;
OSPM_DBGERRORLOG(errorcode, "not enough message parts for full message");
}
}
OSPPMimeFieldFree(&content);
if(strstr((const char *)content.FieldBody.Content, "multipart"))
{
OSPPMimeBodyFree(&mimebody);
}
else
{
OSPM_FREE(mimebody.BodyParts[0]);
}
if (boundary.Content)
{
OSPM_FREE(boundary.Content);
boundary.Content = OSPC_OSNULL;
}
OSPM_DBGEXIT(("EXIT : OSPPMimeMessageParse()\n"));
return errorcode;
}
long __mptr=0;
int
OSPPMimeMessageSetContentAndLength(
OSPTMIMEPART *ospvMimePart,
unsigned char *ospvMsgBuffer,
unsigned ospvSizeOfMsgBuffer)
{
int errorcode = OSPC_ERR_NO_ERROR;
OSPM_DBGENTER(("ENTER: OSPPMimeMessageSetContentAndLength()\n"));
if(ospvSizeOfMsgBuffer > 0)
{
OSPM_MALLOC(ospvMimePart->Content,
unsigned char,
ospvSizeOfMsgBuffer + 1);
if(ospvMimePart->Content != (unsigned char *)NULL)
{
OSPM_MEMCPY(ospvMimePart->Content,
ospvMsgBuffer,
ospvSizeOfMsgBuffer);
ospvMimePart->Length = ospvSizeOfMsgBuffer;
}
else
{
errorcode = OSPC_ERR_MIME_MALLOC_FAILED;
OSPM_DBGERRORLOG(errorcode, "can't malloc msg content part");
}
}
else
{
errorcode = OSPC_ERR_MIME_NO_INPUT;
OSPM_DBGERRORLOG(errorcode, "no data input for msg part");
}
OSPM_DBGEXIT(("EXIT : OSPPMimeMessageSetContentAndLength()\n"));
return errorcode;
}
void
OSPPMimeParamFree(
OSPTMIMEPARAM *ospvParam)
{
OSPM_DBGENTER(("ENTER: OSPPMimeParamFree()\n"));
if(ospvParam != (OSPTMIMEPARAM *)NULL)
{
OSPPMimePartFree(ospvParam->ParamName);
OSPPMimePartFree(ospvParam->ParamValue);
}
OSPM_DBGEXIT(("EXIT : OSPPMimeParamFree()\n"));
return;
}
int
OSPPMimeParamsParse(
OSPTMIMEFIELD *ospvField)
{
int errorcode = OSPC_ERR_NO_ERROR;
unsigned start = 0;
unsigned currpos = 0;
unsigned bufend = ospvField->FieldBody.Length;
unsigned char *bufptr = ospvField->FieldBody.Content;
unsigned count = 0;
unsigned len = 0;
OSPM_DBGENTER(("ENTER: OSPPMimeParamsParse()\n"));
if(bufptr != (unsigned char *)NULL)
{
/* Get past the type/subtype string */
while((bufptr[currpos] != ';') &&
(bufptr[currpos] != '\n') &&
(currpos < bufend))
{
currpos++;
}
/* pass the ; */
if(bufptr[currpos] == ';')
{
currpos++;
/* Now get the name = value pairs and store them */
while((ospvField->NumParams < OSPC_MAX_PARAMS) &&
(currpos < bufend))
{
/* Skip spaces, tabs, newlines, and stray ';' */
while (currpos < bufend)
{
if ((bufptr[currpos] != ' ') &&
(bufptr[currpos] != '\t') &&
(bufptr[currpos] != '\n') &&
(bufptr[currpos] != ';'))
{
break;
}
++currpos;
}
start = currpos;
while(currpos < bufend)
{
if(bufptr[currpos] == '=')
{
break;
}
currpos++;
}
len = currpos - start;
/* remove white space at end */
while(len > 0)
{
if(!isspace(bufptr[currpos-1]))
{
break;
}
--len;
}
/* Create Param structure */
OSPM_MALLOC(ospvField->Params[count],
OSPTMIMEPARAM,
sizeof(OSPTMIMEPARAM));
if(ospvField->Params[count] != (OSPTMIMEPARAM *)NULL)
{
OSPM_MEMSET(ospvField->Params[count],
0,
sizeof(OSPTMIMEPARAM));
/* Create Param Name Structure */
OSPM_MALLOC(ospvField->Params[count]->ParamName,
OSPTMIMEPART,
sizeof(OSPTMIMEPART));
if(ospvField->Params[count]->ParamName != (OSPTMIMEPART *)NULL)
{
OSPM_MEMSET(ospvField->Params[count]->ParamName,
0,
sizeof(OSPTMIMEPART));
errorcode = OSPPUtilMallocAndCopySubString(ospvField->FieldBody.Content,
&(ospvField->Params[count])->ParamName->Content,
start,
len);
}
else
{
errorcode = OSPC_ERR_MIME_MALLOC_FAILED;
OSPM_DBGERRORLOG(errorcode, "malloc failed for param name structure");
}
}
else
{
errorcode = OSPC_ERR_MIME_MALLOC_FAILED;
OSPM_DBGERRORLOG(errorcode, "malloc failed for param structure");
}
/* Now get value */
if(errorcode == OSPC_ERR_NO_ERROR)
{
ospvField->Params[count]->ParamName->Length = len;
if((currpos < bufend) && (bufptr[currpos] == '='))
{
currpos++;
}
/* Skip spaces and tabs */
while (currpos < bufend)
{
if ((bufptr[currpos] != ' ') &&
(bufptr[currpos] != '\t'))
{
break;
}
++currpos;
}
start = currpos;
len = 0;
/* Get value */
while(currpos < bufend)
{
/* ; means we are at the end of the param value
* get rid of it */
if(bufptr[currpos] == ';')
{
break;
}
if(bufptr[currpos] == '\n')
{
/* Are we at the end of the data? */
if(currpos == bufend -1)
{
currpos++;
break;
}
/* Is this really the end of the param value, and not just the end
* of a wrapped line? */
else if ((bufptr[currpos+1] != ' ') &&
(bufptr[currpos+1] != '\t'))
{
currpos++;
break;
}
}
currpos++;
}
/* remove whitespace at end of value */
while(currpos > start)
{
if(!isspace(bufptr[currpos-1]))
{
break;
}
--currpos;
}
len = currpos - start;
/* Create Param Value Structure */
OSPM_MALLOC(ospvField->Params[count]->ParamValue,
OSPTMIMEPART,
sizeof(OSPTMIMEPART));
if(ospvField->Params[count]->ParamValue != (OSPTMIMEPART *)NULL)
{
OSPM_MEMSET(ospvField->Params[count]->ParamValue,
0,
sizeof(OSPTMIMEPART));
errorcode = OSPPUtilMallocAndCopySubString(ospvField->FieldBody.Content,
&(ospvField->Params[count])->ParamValue->Content,
start,
len);
}
else
{
errorcode = OSPC_ERR_MIME_MALLOC_FAILED;
OSPM_DBGERRORLOG(errorcode, "malloc failed for param value structure");
}
if(errorcode == OSPC_ERR_NO_ERROR)
{
ospvField->Params[count]->ParamValue->Length = len;
ospvField->NumParams++;
}
}
count++;
}
if((count == OSPC_MAX_PARAMS) && (currpos != bufend))
{
errorcode = OSPC_ERR_MIME_NO_MORE_SPACE;
OSPM_DBGERRORLOG(errorcode, "no space for this parameter");
}
}
}
OSPM_DBGEXIT(("EXIT : OSPPMimeParamsParse()\n"));
return errorcode;
}
void
OSPPMimePartFree(
OSPTMIMEPART *ospvPart)
{
OSPM_DBGENTER(("ENTER: OSPPMimePartFree()\n"));
if(ospvPart->Content != (unsigned char *)NULL)
{
OSPM_FREE(ospvPart->Content);
ospvPart->Content = OSPC_OSNULL;
}
if(ospvPart != (OSPTMIMEPART *)NULL)
{
OSPM_FREE(ospvPart);
ospvPart = OSPC_OSNULL;
}
OSPM_DBGEXIT(("EXIT : OSPPMimePartFree()\n"));
return;
}
int
OSPPMimeVerifyParameters(
OSPTMIMEFIELD *ospvContent,
OSPTMIMEPART *ospvBoundary,
int ospvHeaderType)
{
int errorcode = OSPC_ERR_NO_ERROR;
unsigned pcount = 0;
int result = 0;
int pfound = 0;
OSPM_DBGENTER(("ENTER: OSPPMimeVerifyParameters()\n"));
switch(ospvHeaderType)
{
case OSPC_MAIN:
/* verify content-type, protocol, micalg, boundary, length */
/* found content-type, now check type and subtype */
errorcode = OSPPUtilMemCaseCmp(ospvContent->FieldBody.Content,
ospvContent->FieldBody.Length,
"multipart/signed",
strlen("multipart/signed"),
&result);
if((errorcode == OSPC_ERR_NO_ERROR) &&
(result == 0))
{
/* Parse parameters into structure for easier compares */
errorcode = OSPPMimeParamsParse(ospvContent);
if(errorcode == OSPC_ERR_NO_ERROR)
{
pcount = 0;
pfound = 0;
/* check protocol */
while((pcount < ospvContent->NumParams) &&
(!pfound))
{
errorcode = OSPPUtilMemCaseCmp( ospvContent->Params[pcount]->ParamName->Content,
ospvContent->Params[pcount]->ParamName->Length,
"protocol",
strlen("protocol"),
&result);
if((errorcode == OSPC_ERR_NO_ERROR) &&
(result == 0))
{
pfound = 1;
break;
}
pcount++;
}
if(pfound)
{
/* copy the protocol string somewhere to save it for SECURITY
* remember to strip off double quotes
*/
}
else
{
errorcode = OSPC_ERR_MIME_PROTOCOL_NOT_FOUND;
OSPM_DBGERRORLOG(errorcode, "protocol parameter not found");
}
}
if(errorcode == OSPC_ERR_NO_ERROR)
{
pcount = 0;
pfound = 0;
/* check micalg */
while((pcount < ospvContent->NumParams) &&
(!pfound))
{
errorcode = OSPPUtilMemCaseCmp( ospvContent->Params[pcount]->ParamName->Content,
ospvContent->Params[pcount]->ParamName->Length,
"micalg",
strlen("micalg"),
&result);
if((errorcode == OSPC_ERR_NO_ERROR) &&
(result == 0))
{
pfound = 1;
break;
}
pcount++;
}
if(pfound)
{
/* copy this out to hand up to SECURITY */
}
else
{
errorcode = OSPC_ERR_MIME_MICALG_NOT_FOUND;
OSPM_DBGERRORLOG(errorcode, "micalg not found");
}
}
if(errorcode == OSPC_ERR_NO_ERROR)
{
pcount = 0;
pfound = 0;
/* get boundary */
while((pcount < ospvContent->NumParams) &&
(!pfound))
{
errorcode = OSPPUtilMemCaseCmp( ospvContent->Params[pcount]->ParamName->Content,
ospvContent->Params[pcount]->ParamName->Length,
"boundary",
strlen("boundary"),
&result);
if((errorcode == OSPC_ERR_NO_ERROR) &&
(result == 0))
{
pfound = 1;
break;
}
pcount++;
}
if(pfound)
{
OSPM_MALLOC(ospvBoundary->Content,
unsigned char,
ospvContent->Params[pcount]->ParamValue->Length);
if(ospvBoundary->Content != (unsigned char *)NULL)
{
OSPM_MEMSET(ospvBoundary->Content,
0,
ospvContent->Params[pcount]->ParamValue->Length);
OSPM_MEMCPY(ospvBoundary->Content,
ospvContent->Params[pcount]->ParamValue->Content,
ospvContent->Params[pcount]->ParamValue->Length);
ospvBoundary->Length = ospvContent->Params[pcount]->ParamValue->Length;
}
else
{
errorcode = OSPC_ERR_MIME_MALLOC_FAILED;
OSPM_DBGERRORLOG(errorcode, "malloc failed for boundary content");
}
} /* end if (pfound) */
else
{
errorcode = OSPC_ERR_MIME_BOUNDARY_NOT_FOUND;
OSPM_DBGERRORLOG(errorcode, "boundary not found");
}
}
else if(result != 0)
{
errorcode = OSPC_ERR_MIME_INVALID_SUBTYPE;
OSPM_DBGERRORLOG(errorcode, "subtype does not match");
}
}
else
{
errorcode = OSPPUtilMemCaseCmp(ospvContent->FieldBody.Content,
ospvContent->FieldBody.Length,
"text/plain",
strlen("text/plain"),
&result);
if(errorcode == OSPC_ERR_NO_ERROR)
{
/* Parse parameters into structure for easier compares */
errorcode = OSPPMimeParamsParse(ospvContent);
}
}
break;
case OSPC_BODY:
/* verify content-type, length */
break;
case OSPC_SIGNATURE:
/* verify content-type, length */
break;
default:
errorcode = OSPC_ERR_MIME_INVALID_TYPE;
OSPM_DBGERRORLOG(errorcode, "invalid header type");
break;
}
OSPM_DBGEXIT(("EXIT : OSPPMimeVerifyParameters()\n"));
return errorcode;
}
int
OSPPUtilMallocAndCopySubString(
unsigned char *ospvSrcString,
unsigned char **ospvDestString,
unsigned ospvStartOfSubString,
unsigned ospvSizeOfSubString)
{
int errorcode = OSPC_ERR_NO_ERROR;
OSPM_DBGENTER(("ENTER: OSPPUtilMallocAndCopySubString()\n"));
if(&ospvSrcString[ospvStartOfSubString] != (unsigned char *)NULL)
{
OSPM_MALLOC(*ospvDestString,
unsigned char,
ospvSizeOfSubString+1);
if(*ospvDestString != (unsigned char *)NULL)
{
OSPM_MEMSET(*ospvDestString,
0,
ospvSizeOfSubString +1);
OSPM_MEMCPY(*ospvDestString,
&ospvSrcString[ospvStartOfSubString],
ospvSizeOfSubString);
}
else
{
errorcode = OSPC_ERR_UTIL_MALLOC_FAILED;
OSPM_DBGERRORLOG(errorcode, "malloc failed for mallocandcopystring");
}
}
else
{
errorcode = OSPC_ERR_UTIL_VALUE_NOT_FOUND;
OSPM_DBGERRORLOG(errorcode, "no string for mallocandcopystring");
}
OSPM_DBGEXIT(("EXIT : OSPPUtilMallocAndCopySubString()\n"));
return errorcode;
}
int
OSPPUtilMemCaseCmp(
unsigned char *ospvMem1,
unsigned ospvLen1,
char *ospvMem2,
unsigned ospvLen2,
int *ospvResult)
{
int errorcode = OSPC_ERR_NO_ERROR;
unsigned count=0;
unsigned len = OSPM_MIN(ospvLen1, ospvLen2);
int char1 = 0;
int char2 = 0;
OSPM_DBGENTER(("ENTER: OSPPUtilMemCaseCmp()\n"));
*ospvResult = 0;
if((ospvMem1 != (unsigned char *)NULL) &&
(ospvMem2 != (char *)NULL))
{
for (count=0; count < len; ++count)
{
char1 = tolower(ospvMem1[count]);
char2 = tolower(ospvMem2[count]);
if (char1 < char2)
{
*ospvResult = -1;
break;
}
else if (char1 > char2)
{
*ospvResult = 1;
break;
}
} /* end for */
}
else
{
errorcode = OSPC_ERR_MIME_INVALID_ARG;
OSPM_DBGERRORLOG(errorcode, "no data for compare");
}
OSPM_DBGEXIT(("EXIT : OSPPUtilMemCaseCmp()\n"));
return errorcode;
}
/* End of file */