// ============================================================================ // Internet Character Set Conversion: Input from ISO-2022-KR // ============================================================================ #include "private.h" #include "fechrcnv.h" #include "kscobj.h" #include "codepage.h" /****************************************************************************** ************************** C O N S T R U C T O R ************************** ******************************************************************************/ CInccKscIn::CInccKscIn(UINT uCodePage, int nCodeSet) : CINetCodeConverter(uCodePage, nCodeSet) { Reset(); // initialization return ; } /****************************************************************************** ******************************* R E S E T ********************************* ******************************************************************************/ void CInccKscIn::Reset() { m_pfnConv = ConvMain; m_pfnCleanUp = CleanUpMain; m_fShift = FALSE; // bug #57570, Korean ISP DACOM only labels one designator in the // conversion of a MIME mail. To decode the other part of MIME correctly, // we need to decode the ISO document or MIME message even there is no // designator "esc ) C". m_fKorea = TRUE; m_nESCBytes = 0 ; m_fLeadByte = FALSE ; return ; } /****************************************************************************** ************************* C O N V E R T C H A R ************************* ******************************************************************************/ HRESULT CInccKscIn::ConvertChar(UCHAR tc, int cchSrc) { BOOL fDone = (this->*m_pfnConv)(tc); if (fDone) return S_OK; else return E_FAIL; } /****************************************************************************** ***************************** C L E A N U P ***************************** ******************************************************************************/ BOOL CInccKscIn::CleanUp() { return (this->*m_pfnCleanUp)(); } /****************************************************************************** **************************** C O N V M A I N **************************** ******************************************************************************/ BOOL CInccKscIn::ConvMain(UCHAR tc) { BOOL fDone = TRUE; if (tc == ESC) { m_pfnConv = ConvEsc; m_pfnCleanUp = CleanUpEsc; m_nESCBytes++ ; } else { if (m_fKorea) { switch (tc) { case SO: m_fShift = TRUE; break; case SI: m_fShift = FALSE; m_fLeadByte = FALSE ; break; default: if (m_fShift) { switch (tc) { case ' ': case '\t': case '\n': fDone = Output(tc); break; default: fDone = Output(tc | 0x80); m_fLeadByte = ~m_fLeadByte ; break; } } else { fDone = Output(tc); } break; } } else { fDone = Output(tc); } } return fDone; } /****************************************************************************** ************************ C L E A N U P M A I N ************************ ******************************************************************************/ BOOL CInccKscIn::CleanUpMain() { return TRUE; } /****************************************************************************** ***************************** C O N V E S C ***************************** ******************************************************************************/ BOOL CInccKscIn::ConvEsc(UCHAR tc) { if (tc == ISO2022_IN_CHAR) { m_pfnConv = ConvIsoIn; m_pfnCleanUp = CleanUpIsoIn; m_nESCBytes++ ; return TRUE; } else { m_pfnConv = ConvMain; m_pfnCleanUp = CleanUpMain; m_nESCBytes = 0 ; (void)Output(ESC); if (SUCCEEDED(ConvertChar(tc))) return TRUE; else return FALSE; } } /****************************************************************************** ************************* C L E A N U P E S C ************************* ******************************************************************************/ BOOL CInccKscIn::CleanUpEsc() { m_pfnConv = ConvMain; m_pfnCleanUp = CleanUpMain; m_nESCBytes = 0 ; return Output(ESC); } /****************************************************************************** ************************** C O N V I S O I N ************************** ******************************************************************************/ BOOL CInccKscIn::ConvIsoIn(UCHAR tc) { if (tc == ISO2022_IN_KR_CHAR_1) { m_pfnConv = ConvIsoInKr; m_pfnCleanUp = CleanUpIsoInKr; m_nESCBytes++ ; return TRUE; } else { m_pfnConv = ConvMain; m_pfnCleanUp = CleanUpMain; m_nESCBytes = 0 ; (void)Output(ESC); (void)ConvertChar(ISO2022_IN_CHAR); if (SUCCEEDED(ConvertChar(tc))) return TRUE; else return FALSE; } } /****************************************************************************** ********************** C L E A N U P I S O I N ********************** ******************************************************************************/ BOOL CInccKscIn::CleanUpIsoIn() { m_pfnConv = ConvMain; m_pfnCleanUp = CleanUpMain; m_nESCBytes = 0 ; (void)Output(ESC); (void)ConvertChar(ISO2022_IN_CHAR); return CleanUp(); } /****************************************************************************** *********************** C O N V I S O I N K R *********************** ******************************************************************************/ BOOL CInccKscIn::ConvIsoInKr(UCHAR tc) { m_pfnConv = ConvMain; m_pfnCleanUp = CleanUpMain; m_nESCBytes = 0 ; if (tc == ISO2022_IN_KR_CHAR_2) { m_fKorea = TRUE; return TRUE; } else { (void)Output(ESC); (void)ConvertChar(ISO2022_IN_CHAR); (void)ConvertChar(ISO2022_IN_KR_CHAR_1); if (SUCCEEDED(ConvertChar(tc))) return TRUE; else return FALSE; } } /****************************************************************************** ******************* C L E A N U P I S O I N K R ******************* ******************************************************************************/ BOOL CInccKscIn::CleanUpIsoInKr() { m_pfnConv = ConvMain; m_pfnCleanUp = CleanUpMain; m_nESCBytes = 0 ; (void)Output(ESC); (void)ConvertChar(ISO2022_IN_CHAR); (void)ConvertChar(ISO2022_IN_KR_CHAR_1); return CleanUp(); } int CInccKscIn::GetUnconvertBytes() { if ( m_fLeadByte ) return 1 ; else if ( m_nESCBytes ) return m_nESCBytes < 4 ? m_nESCBytes : 3 ; else return 0 ; } DWORD CInccKscIn::GetConvertMode() { // 0xC431 -> 50225 ISO-2022-KR return ( m_fKorea ? 1 : 0 ) + ( m_fShift ? 2 : 0 ) | 0xC4310000 ; } void CInccKscIn::SetConvertMode(DWORD mode) { Reset(); // initialization if ( mode & 0x00000001 ) m_fKorea = TRUE ; if ( mode & 0x00000002 ) m_fShift = TRUE ; return ; } // ============================================================================ // Internet Character Set Conversion: Output to ISO-2022-KSC // ============================================================================ /****************************************************************************** ************************** C O N S T R U C T O R ************************** ******************************************************************************/ CInccKscOut::CInccKscOut(UINT uCodePage, int nCodeSet, DWORD dwFlag, WCHAR *lpFallBack) : CINetCodeConverter(uCodePage, nCodeSet) { Reset(); // initialization _dwFlag = dwFlag; _lpFallBack = lpFallBack; return ; } /****************************************************************************** ******************************* R E S E T ********************************* ******************************************************************************/ void CInccKscOut::Reset() { m_fDoubleByte = FALSE; m_fShift = FALSE; m_fKorea = FALSE; m_tcLeadByte = 0 ; return ; } /****************************************************************************** ************************* C O N V E R T C H A R ************************* ******************************************************************************/ HRESULT CInccKscOut::ConvertChar(UCHAR tc, int cchSrc) { BOOL fDone = TRUE; HRESULT hr = S_OK; // //IE RAID #103403 weiwu 03/16/00 // //Per Korean PM (sykim), we don't have to prepend iso-2022-kr designator to conversion result string //Also considering that URLMON can't handle encoded ASCII iso-2022-kr string //We now remove following code, if it triggers any compatibility issues, we should re-enable it // #if 0 // put designator to the top of the document if (!m_fKorea) { (void)Output(ESC); (void)Output(ISO2022_IN_CHAR); (void)Output(ISO2022_IN_KR_CHAR_1); (void)Output(ISO2022_IN_KR_CHAR_2); m_fKorea = TRUE; } #endif if (!m_fDoubleByte) { // // We're not using IsDBCSLeadByteEx() due to perf. concern // We should assert that our hard code table match IsDBCSLeadByteEx(), // But, MLang ships with down level platforms and assert won't be valid if there is a range change // if (IS_KOR_LEADBYTE(tc)) { m_fDoubleByte = TRUE; m_tcLeadByte = tc; } else { if (m_fKorea && m_fShift) { (void)Output(SI); m_fShift = FALSE; } fDone = Output(tc); } } else { m_fDoubleByte = FALSE; if (tc > 0x40) { // Check if trail byte indicates Hangeul if (m_tcLeadByte > 0xa0 && tc > 0xa0) { // Check if it's a Wansung if (!m_fShift) { if (!m_fKorea) { (void)Output(ESC); (void)Output(ISO2022_IN_CHAR); (void)Output(ISO2022_IN_KR_CHAR_1); (void)Output(ISO2022_IN_KR_CHAR_2); m_fKorea = TRUE; } (void)Output(SO); m_fShift = TRUE; } (void)Output(m_tcLeadByte & 0x7f); fDone = Output(tc & 0x7f); } else { UCHAR szDefaultChar[3] = {0x3f}; // possible DBCS + null if (_lpFallBack && (_dwFlag & MLCONVCHARF_USEDEFCHAR)) { // only take SBCS, no DBCS character if ( 1 != WideCharToMultiByte(CP_KOR_5601, 0, (LPCWSTR)_lpFallBack, 1, (LPSTR)szDefaultChar, ARRAYSIZE(szDefaultChar), NULL, NULL )) szDefaultChar[0] = 0x3f; } // shift out if we're in DBCS mode if (m_fKorea && m_fShift) { (void)Output(SI); m_fShift = FALSE; } if (_dwFlag & (MLCONVCHARF_NCR_ENTITIZE|MLCONVCHARF_NAME_ENTITIZE)) { char szChar[2]; char szDstStr[10]; WCHAR szwChar[2]; int cCount; szChar[0] = m_tcLeadByte; szChar[1] = tc; if (MultiByteToWideChar(CP_KOR_5601, 0, szChar, 2, szwChar, ARRAYSIZE(szwChar))) { // Output NCR entity Output('&'); Output('#'); _ultoa((unsigned long)szwChar[0], (char*)szDstStr, 10); cCount = lstrlenA(szDstStr); for (int i=0; i< cCount; i++) { Output(szDstStr[i]); } fDone = Output(';'); } else { fDone = Output(szDefaultChar[0]); // use default char hr = S_FALSE; } } else { fDone = Output(szDefaultChar[0]); // use default char hr = S_FALSE; } } } else { if (m_fKorea && m_fShift) { (void)Output(SI); m_fShift = FALSE; } (void)Output(m_tcLeadByte); fDone = Output(tc); } m_tcLeadByte = 0 ; } if (!fDone) hr = E_FAIL; return hr; } /****************************************************************************** ***************************** C L E A N U P ***************************** ******************************************************************************/ BOOL CInccKscOut::CleanUp() { BOOL fDone = TRUE; if ( m_fShift) { fDone = Output(SI); m_fShift = FALSE; } return fDone ; } int CInccKscOut::GetUnconvertBytes() { if (m_tcLeadByte) return 1 ; else return 0 ; } DWORD CInccKscOut::GetConvertMode() { // for output, we don't need write back code page. 0xC431 -> 50225 ISO-2022-KR return ( m_fKorea ? 1 : 0 ) + ( m_fShift ? 2 : 0 ) ; } void CInccKscOut::SetConvertMode(DWORD mode) { Reset(); // initialization if ( mode & 0x00000001 ) m_fKorea = TRUE ; if ( mode & 0x00000002 ) m_fShift = TRUE ; return ; }