int CEuc::UniToEucjp( const wchar_t* pSrc, const int nSrcLen, char* pDst, bool* pbError ) { int nclen; const unsigned short *pr, *pr_end; unsigned char* pw; bool berror=false, berror_tmp; ECharSet echarset; pr = reinterpret_cast<const unsigned short*>(pSrc); pr_end = reinterpret_cast<const unsigned short*>(pSrc + nSrcLen); pw = reinterpret_cast<unsigned char*>(pDst); while( (nclen = CheckUtf16leChar(reinterpret_cast<const wchar_t*>(pr), pr_end-pr, &echarset, 0)) > 0 ){ // 保護コード switch( echarset ){ case CHARSET_UNI_NORMAL: nclen = 1; break; case CHARSET_UNI_SURROG: nclen = 2; break; default: echarset = CHARSET_BINARY; nclen = 1; } if( echarset != CHARSET_BINARY ){ pw += _UniToEucjp_char( pr, pw, echarset, &berror_tmp ); // 保護コード if( berror_tmp == true ){ berror = true; } pr += nclen; }else{ if( nclen == 1 && IsBinaryOnSurrogate(static_cast<wchar_t>(*pr)) ){ *pw = static_cast<unsigned char>( TextToBin(*pr) & 0x00ff ); ++pw; }else{ // 保護コード berror = true; *pw = '?'; ++pw; } ++pr; } } if( pbError ){ *pbError = berror; } return pw - reinterpret_cast<unsigned char*>(pDst); }
/*! UTF-7 セットBの文字列か @return セットB文字列の長さ @param[out] ppNextChar 次のブロック(UTF-7セットD部分)の先頭文字のポインタが格納される(文字'-'を飛ばす) @note この関数の前に CheckUtf7DPart() が実行される必要がある。 */ int CheckUtf7BPart( const char *pS, const int nLen, char **ppNextChar, bool *pbError, const int nOption ) { const char *pr, *pr_end; bool berror_found, bminus_found; int nchecklen; wchar_t* pdata; int ndatalen, nret; ECharSet echarset; CMemory cmbuffer; if( nLen < 1 ){ if( pbError ){ *pbError = false; } *ppNextChar = const_cast<char*>( pS ); return 0; } berror_found = false; bminus_found = false; pr = pS; pr_end = pS + nLen; for( ; pr < pr_end; ++pr ){ // セットBの文字でなくなるまでループ if( !IsBase64(*pr) ){ if( *pr == '-' ){ bminus_found= true; }else{ bminus_found = false; } break; } } nchecklen = pr - pS; // 保護コード if( nchecklen < 1 ){ nchecklen = 0; } /* ◆ デコード後のデータ長の確認 調査してきたデータ長 nchecklen(= pr - pS) を8で割ってみる. その余りの値から考えられるビット列は… |----------------------------- Base64 表現 --------------------------------------------| 第1バイト 第2バイト 第3バイト 第4バイト 第5バイト 第6バイト 第7バイト 第8バイト 残り1文字 00xx xxxx 00xx xxxx 00xx xx00 --- --- --- --- --- 残り2文字 00xx xxxx 00xx xxxx 00xx xxxx 00xx xxxx 00xx xxxx 00xx 0000 --- --- 残り3文字 00xx xxxx 00xx xxxx 00xx xxxx 00xx xxxx 00xx xxxx 00xx xxxx 00xx xxxx 00xx xxxx 上記3通りのいづれにも当てはまらない場合は全データを落とす(不正バイトとする). */ const char *pr_ = pr - 1; switch( nchecklen % 8 ){ case 0: break; case 3: if( Base64ToVal(pr_[0]) & 0x03 ){ berror_found = true; } break; case 6: if( Base64ToVal(pr_[0]) & 0x0f ){ berror_found = true; } break; case 8: // nchecklen == 0 の場合 break; default: berror_found = true; } if( UC_LOOSE == (nOption & UC_LOOSE) ){ goto EndFunc; } // UTF-7文字列 "+-" のチェック if( pr < pr_end && (nchecklen < 1 && bminus_found != true) ){ // 読み取りポインタがデータの終端を指していなくて // 確認できた Set B 文字列の長さがゼロの場合は、 // 必ず終端文字 '-' が存在していることを確認する。 berror_found = true; } // 実際にデコードして内容を確認する。 if( berror_found == true || nchecklen < 1 ){ goto EndFunc; } cmbuffer.AllocBuffer( nchecklen ); pdata = reinterpret_cast<wchar_t*>( cmbuffer.GetRawPtr() ); if( pdata == NULL ){ goto EndFunc; } ndatalen = _DecodeBase64(pS, nchecklen, reinterpret_cast<char*>(pdata)) / sizeof(wchar_t); CMemory::SwapHLByte( reinterpret_cast<char*>(pdata), ndatalen*sizeof(wchar_t) ); for( int i = 0; i < ndatalen; i += nret ){ nret = CheckUtf16leChar( &pdata[i], ndatalen - i, &echarset, nOption & UC_NONCHARACTER ); if( echarset == CHARSET_BINARY ){ berror_found = true; goto EndFunc; } if( nret == 1 && IsUtf7SetD(pdata[i]) ){ berror_found = true; goto EndFunc; } } EndFunc:; if( pbError ){ *pbError = berror_found; } if( (berror_found == false || UC_LOOSE == (nOption & UC_LOOSE)) && (pr < pr_end && bminus_found == true) ){ // '-' をスキップ。 *ppNextChar = const_cast<char*>(pr) + 1; }else{ *ppNextChar = const_cast<char*>(pr); } return nchecklen; }