/* * Create an emsMIMEtype structure to hold MIME information. Structure is * initialized to values provided in RFC822 content-type header line. This * includes all parameter name-value pairs. * * NOTE: The user of this function is responsible for calling * free_mime_type() on returned structure. * * Args: * content_type [IN] The RFC822 content-type string to parse * * Returns: Pointer to the created emsMIMEtype structure, NULL if error. */ emsMIMEtypeP parse_make_mime_type(const char *content_type) { const char *kPrefixStr = "Content-Type:"; const unsigned int kPrefixStrLen = strlen(kPrefixStr); if (cistrncmp(content_type, kPrefixStr, kPrefixStrLen) != 0) return NULL; char *cp = (char *) content_type + kPrefixStrLen; char *mime_type = NULL, *mime_subtype = NULL; mime_type = rfc822_extract_token(&cp); if ((strlen(mime_type) > 0) && ((*cp++) == '/')) { mime_subtype = rfc822_extract_token(&cp); if (strlen(mime_subtype) > 0) { // We have a type/subtype, so create emsMIMEtype structure emsMIMEtypeP mimePtr = make_mime_type(mime_type, mime_subtype, NULL); safefree(mime_type); safefree(mime_subtype); if (mimePtr) { char *name = NULL, *value = NULL; do { if ((*cp++) != ';') // Skip semi-colon break; if (!(name = rfc822_extract_token(&cp))) break; if ((*cp++) != '=') // Skip equals break; if (!(value = rfc822_extract_token(&cp))) break; if ((strlen(name) > 0) && (strlen(value) > 0)) add_mime_parameter(mimePtr, name, value); safefree(name); safefree(value); } while (*cp); safefree(name); safefree(value); return mimePtr; } } } // If we get here then something went wrong // Do complete cleanup safefree(mime_type); safefree(mime_subtype); return (NULL); // ERROR }
/* DoParsePart (static) * * Private function used to pipe the output of 1847 parsing into a file. */ static int DoParsePart(BufTypePtr pInBuf, FILE *fOut, emsMIMEtypeP *mimePtr, int bDeMime, PartParseStatePtr pState) { if (!pInBuf) // Input buf NULL indicates 'cleanup' { if (!pState->bFoundHeader) return (FALSE); else return (TRUE); } if (!pState->bFoundHeader) { resetpos_buf(pState->pSearchBuf); if (pState->nPrevEndMatch > 0) { /* Check for completion of span */ // If doesn't continue match, returns zero // otherwise returns number of chars of pSearchBuf that have been matched unsigned int nNewMatched = completecount_buf(pInBuf, pState->pSearchBuf, pState->nPrevEndMatch); if (nNewMatched == buflen_buf(pState->pSearchBuf)) /* complete match made */ { pState->bFoundHeader = TRUE; pState->nPrevEndMatch = 0; bufncat_buf(pState->pBuf, pInBuf, (buflen_buf(pState->pSearchBuf) - (pState->nPrevEndMatch))); } else if (nNewMatched != 0) /* Continued to match, but not completed yet -- the input buffer is smaller than the pSearchBuf */ { bufncat_buf(pState->pBuf, pInBuf, poslen_buf(pInBuf)); pState->nPrevEndMatch = nNewMatched; return (TRUE); } else /* No match continuation */ { pState->nPrevEndMatch = 0; } } resetpos_buf(pState->pSearchBuf); // Still not found -- no span if (!pState->bFoundHeader) { // Find match of pSearchBuf, either complete or end-spanning // return number of chars to skip before match unsigned int nSkip = skipcount_buf(pInBuf, pState->pSearchBuf); unsigned int nRemain = poslen_buf(pInBuf) - nSkip; if (nRemain == 0) // Not found { bufncat_buf(pState->pBuf, pInBuf, poslen_buf(pInBuf)); return (TRUE); } else if (nRemain > buflen_buf(pState->pSearchBuf)) /* Found 'complete' */ { pState->bFoundHeader = TRUE; bufncat_buf(pState->pBuf, pInBuf, (nSkip + buflen_buf(pState->pSearchBuf)) ); } else // Partial possible { pState->nPrevEndMatch = nRemain; bufncat_buf(pState->pBuf, pInBuf, poslen_buf(pInBuf)); return (TRUE); } } // ---------- Now we know it is found ---------- unsigned int nLen = buflen_buf(pState->pBuf); char *pHeader = (char *) malloc(nLen + 1); strncpy(pHeader, getbuf_buf(pState->pBuf), nLen); { char *pCT = rfc822_extract_header(pHeader, "Content-Type:"); if (mimePtr) { if (pCT) { *mimePtr = parse_make_mime_type(pCT); } else { *mimePtr = make_mime_type("text", "plain", "1.0"); } } safefree(pCT); } if (bDeMime) { { char *pCTE = rfc822_extract_cte(pHeader); if (pCTE) pState->cte = rfc822_parse_cte(pCTE); else pState->cte = CTE_NONE; /* No CTE header, so no encoding */ safefree(pCTE); } switch (pState->cte) { // BASE64 case CTE_Base64: { // BASE64 expands about 1/3 unsigned int preEncBufLen = ((kBufferSize * 10) / 6); pState->preEncBuffer = (char *) malloc(preEncBufLen); pState->d64state = (Dec64Ptr) malloc(sizeof(Dec64)); // Used by Decode64() pState->d64state->decoderState = 0; pState->d64state->invalCount = 0; pState->d64state->padCount = 0; pState->d64state->partial = 0; pState->d64state->wasCR = FALSE; } break; // QUOTED-PRINTABLE case CTE_QP: { // QP expands max of 3 times unsigned int preEncBufLen = (kBufferSize * 4); pState->preEncBuffer = (char *) malloc(preEncBufLen); pState->dQPstate = (DecQPPtr) malloc(sizeof(EncQP)); pState->dQPstate->CurState = qpNormal; pState->dQPstate->cLastChar = 0; } break; // Otherwise, no encoding default: break; } } else { fwrite(getbuf_buf(pState->pBuf), sizeof(char), nLen, fOut); } safefree(pHeader) free_buf(pState->pBuf); } // ---------- Now we know it is found and header is init'd ---------- long errorcnt; switch (pState->cte) { case CTE_Base64: { unsigned int nReadLen = Decode64(getpos_buf(pInBuf), poslen_buf(pInBuf), pState->preEncBuffer, pState->d64state, &errorcnt); fwrite(pState->preEncBuffer, sizeof(char), nReadLen, fOut); } break; case CTE_QP: { unsigned int nReadLen = DecodeQP(getpos_buf(pInBuf), poslen_buf(pInBuf), pState->preEncBuffer, pState->dQPstate, &errorcnt); fwrite(pState->preEncBuffer, sizeof(char), nReadLen, fOut); } break; default: /* 7bit, 8bit, binary, none */ { fwrite(getpos_buf(pInBuf), sizeof(char), poslen_buf(pInBuf), fOut); } break; } return (TRUE); }