/** * Decodes a BASE64 encoded data block. Returns True if string has been * successfully decoded, or False if it cannot be decoded (or memory * allocation fails). Does not destroy the original contents of the * buffer */ STATIC Bool BASE64_InternalDecode(Base64Decode * decode) { /* remember the original length so that we can undo the damage */ Buffer* out = decode->out; size_t origLen = (out ? BUFFER_Size(out) : 0); /* read the bulk of the data */ int n; Bool ok = True; I8u chunk[4]; while ((n = BASE64_ReadChunk(decode, chunk)) == 4) { if (out) { if (!BUFFER_PutByte(out,BASE64_DECODE_1(chunk[0],chunk[1])) || !BUFFER_PutByte(out,BASE64_DECODE_2(chunk[1],chunk[2])) || !BUFFER_PutByte(out,BASE64_DECODE_3(chunk[2],chunk[3]))) { /* out of memory */ ok = False; break; } } } /* deal with the trailer */ if (out && ok) { switch (n) { case 0: break; case 1: /* premature end of BASE64 stream */ decode->flags |= FLAG_ERROR; break; case 2: if (!BUFFER_PutByte(out,BASE64_DECODE_1(chunk[0],chunk[1]))) { /* out of memory */ ok = False; } break; case 3: if (!BUFFER_PutByte(out,BASE64_DECODE_1(chunk[0],chunk[1])) || !BUFFER_PutByte(out,BASE64_DECODE_2(chunk[1],chunk[2]))) { /* out of memory */ ok = False; } break; case 4: if (!BUFFER_PutByte(out,BASE64_DECODE_1(chunk[0],chunk[1])) || !BUFFER_PutByte(out,BASE64_DECODE_2(chunk[1],chunk[2])) || !BUFFER_PutByte(out,BASE64_DECODE_3(chunk[2],chunk[3]))) { /* out of memory */ ok = False; } break; } } /* return True if the input was a valid BASE64 sequence */ if ((decode->flags & FLAG_ERROR) || !ok) { if (out) { BUFFER_Unput(out,BUFFER_Size(out)-origLen); ASSERT(BUFFER_Size(out) == (int)origLen); } return False; } else { return True; } }
/***************************************************************************** * FUNCTION * applib_base64_part_decode_append * DESCRIPTION * This function accepts next part of source data; * decode them from BASE64 format * PARAMETERS * cntx [IN] point to the applib_base64_part_context * src [IN] pointer to the input buffer * srcl [IN] length of the input buffer * dest [IN/OUT] pointer to the output buffer * destl [IN] length of the output buffer * RETURNS * negative: Invalid paramter. * ow: the number of bytes written to output buffer. *****************************************************************************/ kal_int32 applib_base64_part_decode_append( applib_base64_part_context* cntx, const kal_char *src, kal_int32 *srcl, kal_char *dst, kal_int32 dstl) { /*----------------------------------------------------------------*/ /* Local Variables */ /*----------------------------------------------------------------*/ kal_char c; kal_int32 i_input,i_output; /*----------------------------------------------------------------*/ /* Code Body */ /*----------------------------------------------------------------*/ if (cntx == NULL || (cntx->finish_flag && cntx->buf_cnt > 4) || (!cntx->finish_flag && cntx->buf_cnt > 3) || srcl == NULL || (*srcl > 0 && src == NULL)) { BASE64_ASSERT(0); return -1; } if (cntx->finish_flag) { /* the "=" had been reached before */ if (!cntx->illpad_flag) { check_illegal_pad(cntx,src,*srcl); } return 0; } /* * begin decode this part content * Skip all NOT BASE64 CHARACTER * End the decode if '=' was founded. */ i_input = i_output = 0; while(i_input < *srcl) { /* assert check */ BASE64_ASSERT(cntx->buf_cnt <= 3); c = BASE64_DECODE_TABLE[(kal_uint8)(src[i_input++])]; if (c == DWSP) { continue; } else if (c == DNIL) { cntx->illchr_flag = 1; continue; } else if (c == DPAD) { cntx->finish_flag = 1; if (cntx->buf_cnt < 2) { BASE64_WARING(); cntx->illpad_flag = 1; break; } if (i_output + cntx->buf_cnt - 1 > dstl) { /* output buffer is NOT enough */ /* roll back */ cntx->finish_flag = 0; i_input--; break; } if (cntx->buf_cnt == 2) { BASE64_DECODE_2((dst+i_output),cntx->buf); } else { BASE64_DECODE_3((dst+i_output),cntx->buf); } i_output += cntx->buf_cnt - 1; cntx->buf[cntx->buf_cnt++] = c; check_illegal_pad(cntx,src+i_input,*srcl-i_input); i_input = *srcl; /* all data have been processed */ break; } else { /* Decode the bytes upto 4-group */ cntx->buf[cntx->buf_cnt++] = c; /* four bytes readed,DECODE IT */ if (cntx->buf_cnt < 4) { continue; } if (i_output + 3 > dstl) { /* roll back */ cntx->buf_cnt--; i_input--; break; } BASE64_DECODE_4((dst+i_output),cntx->buf); i_output += 3; cntx->buf_cnt = 0; } /* assert check */ BASE64_ASSERT(cntx->buf_cnt <= 3); } if (*srcl != i_input) { /* warning */ BASE64_WARING(); } *srcl = i_input; return i_output; }