fix for utf-8 strings in protocol (it used to be just ACSII coded strings which is not according to the specification of the protocol)

This commit is contained in:
Volker Fischer 2013-01-13 19:56:50 +00:00
parent 606542102a
commit 03a2940cfe
3 changed files with 92 additions and 51 deletions

View File

@ -2,6 +2,8 @@
TODO: Mac OS 64bit support TODO: Mac OS 64bit support
- bug fix: strings in the protocol are now utf-8 coded
3.2.2 3.2.2

View File

@ -734,12 +734,16 @@ void CProtocol::CreateConClientListMes ( const CVector<CChannelShortInfo>& vecCh
for ( int i = 0; i < iNumClients; i++ ) for ( int i = 0; i < iNumClients; i++ )
{ {
// current string size // convert name string to utf-8
const int iCurStrLen = vecChanInfo[i].strName.size(); const QByteArray strUTF8Name = vecChanInfo[i].strName.toUtf8();
// current utf-8 string size
const int iCurStrUTF8Len = strUTF8Name.size();
// size of current list entry // size of current list entry
const int iCurListEntrLen = const int iCurListEntrLen =
1 /* chan ID */ + 4 /* IP addr. */ + 2 /* str. size */ + iCurStrLen; 1 /* chan ID */ + 4 /* IP addr. */ +
2 /* utf-8 str. size */ + iCurStrUTF8Len;
// make space for new data // make space for new data
vecData.Enlarge ( iCurListEntrLen ); vecData.Enlarge ( iCurListEntrLen );
@ -753,7 +757,7 @@ void CProtocol::CreateConClientListMes ( const CVector<CChannelShortInfo>& vecCh
static_cast<uint32_t> ( vecChanInfo[i].iIpAddr ), 4 ); static_cast<uint32_t> ( vecChanInfo[i].iIpAddr ), 4 );
// name string // name string
PutStringOnStream ( vecData, iPos, vecChanInfo[i].strName ); PutStringUTF8OnStream ( vecData, iPos, strUTF8Name );
} }
CreateAndSendMessage ( PROTMESSID_CONN_CLIENTS_LIST, vecData ); CreateAndSendMessage ( PROTMESSID_CONN_CLIENTS_LIST, vecData );
@ -822,17 +826,21 @@ bool CProtocol::EvaluateReqConnClientsList()
void CProtocol::CreateChanNameMes ( const QString strName ) void CProtocol::CreateChanNameMes ( const QString strName )
{ {
int iPos = 0; // init position pointer int iPos = 0; // init position pointer
const int iStrLen = strName.size(); // get string size
// convert name string to utf-8
const QByteArray strUTF8Name = strName.toUtf8();
const int iStrUTF8Len = strUTF8Name.size(); // get utf-8 string size
// size of current list entry // size of current list entry
const int iEntrLen = 2 /* string size */ + iStrLen; const int iEntrLen = 2 /* utf-8 string size */ + iStrUTF8Len;
// build data vector // build data vector
CVector<uint8_t> vecData ( iEntrLen ); CVector<uint8_t> vecData ( iEntrLen );
// name string // name string
PutStringOnStream ( vecData, iPos, strName ); PutStringUTF8OnStream ( vecData, iPos, strUTF8Name );
CreateAndSendMessage ( PROTMESSID_CHANNEL_NAME, vecData ); CreateAndSendMessage ( PROTMESSID_CHANNEL_NAME, vecData );
} }
@ -878,17 +886,21 @@ bool CProtocol::EvaluateReqChanNameMes()
void CProtocol::CreateChatTextMes ( const QString strChatText ) void CProtocol::CreateChatTextMes ( const QString strChatText )
{ {
int iPos = 0; // init position pointer int iPos = 0; // init position pointer
const int iStrLen = strChatText.size(); // get string size
// convert chat text string to utf-8
const QByteArray strUTF8ChatText = strChatText.toUtf8();
const int iStrUTF8Len = strUTF8ChatText.size(); // get utf-8 string size
// size of message body // size of message body
const int iEntrLen = 2 /* string size */ + iStrLen; const int iEntrLen = 2 /* utf-8 string size */ + iStrUTF8Len;
// build data vector // build data vector
CVector<uint8_t> vecData ( iEntrLen ); CVector<uint8_t> vecData ( iEntrLen );
// chat text // chat text
PutStringOnStream ( vecData, iPos, strChatText ); PutStringUTF8OnStream ( vecData, iPos, strUTF8ChatText );
CreateAndSendMessage ( PROTMESSID_CHAT_TEXT, vecData ); CreateAndSendMessage ( PROTMESSID_CHAT_TEXT, vecData );
} }
@ -1197,15 +1209,20 @@ void CProtocol::CreateCLRegisterServerMes ( const CHostAddress& InetAddr,
{ {
int iPos = 0; // init position pointer int iPos = 0; // init position pointer
// convert server info strings to utf-8
const QByteArray strUTF8Name = ServerInfo.strName.toUtf8();
const QByteArray strUTF8Topic = ServerInfo.strTopic.toUtf8();
const QByteArray strUTF8City = ServerInfo.strCity.toUtf8();
// size of current message body // size of current message body
const int iEntrLen = const int iEntrLen =
2 /* port number */ + 2 /* port number */ +
2 /* country */ + 2 /* country */ +
1 /* maximum number of connected clients */ + 1 /* maximum number of connected clients */ +
1 /* is permanent flag */ + 1 /* is permanent flag */ +
2 /* name string size */ + ServerInfo.strName.size() + 2 /* name utf-8 string size */ + strUTF8Name.size() +
2 /* topic string size */ + ServerInfo.strTopic.size() + 2 /* topic utf-8 string size */ + strUTF8Topic.size() +
2 /* city string size */ + ServerInfo.strCity.size(); 2 /* city utf-8 string size */ + strUTF8City.size();
// build data vector // build data vector
CVector<uint8_t> vecData ( iEntrLen ); CVector<uint8_t> vecData ( iEntrLen );
@ -1227,13 +1244,13 @@ void CProtocol::CreateCLRegisterServerMes ( const CHostAddress& InetAddr,
static_cast<uint32_t> ( ServerInfo.bPermanentOnline ), 1 ); static_cast<uint32_t> ( ServerInfo.bPermanentOnline ), 1 );
// name // name
PutStringOnStream ( vecData, iPos, ServerInfo.strName ); PutStringUTF8OnStream ( vecData, iPos, strUTF8Name );
// topic // topic
PutStringOnStream ( vecData, iPos, ServerInfo.strTopic ); PutStringUTF8OnStream ( vecData, iPos, strUTF8Topic );
// city // city
PutStringOnStream ( vecData, iPos, ServerInfo.strCity ); PutStringUTF8OnStream ( vecData, iPos, strUTF8City );
CreateAndImmSendConLessMessage ( PROTMESSID_CLM_REGISTER_SERVER, CreateAndImmSendConLessMessage ( PROTMESSID_CLM_REGISTER_SERVER,
vecData, vecData,
@ -1334,6 +1351,11 @@ void CProtocol::CreateCLServerListMes ( const CHostAddress& InetAddr,
for ( int i = 0; i < iNumServers; i++ ) for ( int i = 0; i < iNumServers; i++ )
{ {
// convert server list strings to utf-8
const QByteArray strUTF8Name = vecServerInfo[i].strName.toUtf8();
const QByteArray strUTF8Topic = vecServerInfo[i].strTopic.toUtf8();
const QByteArray strUTF8City = vecServerInfo[i].strCity.toUtf8();
// size of current list entry // size of current list entry
const int iCurListEntrLen = const int iCurListEntrLen =
4 /* IP address */ + 4 /* IP address */ +
@ -1341,9 +1363,9 @@ void CProtocol::CreateCLServerListMes ( const CHostAddress& InetAddr,
2 /* country */ + 2 /* country */ +
1 /* maximum number of connected clients */ + 1 /* maximum number of connected clients */ +
1 /* is permanent flag */ + 1 /* is permanent flag */ +
2 /* name string size */ + vecServerInfo[i].strName.size() + 2 /* name utf-8 string size */ + strUTF8Name.size() +
2 /* topic string size */ + vecServerInfo[i].strTopic.size() + 2 /* topic utf-8 string size */ + strUTF8Topic.size() +
2 /* city string size */ + vecServerInfo[i].strCity.size(); 2 /* city utf-8 string size */ + strUTF8City.size();
// make space for new data // make space for new data
vecData.Enlarge ( iCurListEntrLen ); vecData.Enlarge ( iCurListEntrLen );
@ -1369,13 +1391,13 @@ void CProtocol::CreateCLServerListMes ( const CHostAddress& InetAddr,
static_cast<uint32_t> ( vecServerInfo[i].bPermanentOnline ), 1 ); static_cast<uint32_t> ( vecServerInfo[i].bPermanentOnline ), 1 );
// name // name
PutStringOnStream ( vecData, iPos, vecServerInfo[i].strName ); PutStringUTF8OnStream ( vecData, iPos, strUTF8Name );
// topic // topic
PutStringOnStream ( vecData, iPos, vecServerInfo[i].strTopic ); PutStringUTF8OnStream ( vecData, iPos, strUTF8Topic );
// city // city
PutStringOnStream ( vecData, iPos, vecServerInfo[i].strCity ); PutStringUTF8OnStream ( vecData, iPos, strUTF8City );
} }
CreateAndImmSendConLessMessage ( PROTMESSID_CLM_SERVER_LIST, CreateAndImmSendConLessMessage ( PROTMESSID_CLM_SERVER_LIST,
@ -1607,9 +1629,11 @@ bool CProtocol::ParseMessageFrame ( const CVector<uint8_t>& vecIn,
// Now check CRC ----------------------------------------------------------- // Now check CRC -----------------------------------------------------------
CCRC CRCObj; CCRC CRCObj;
const int iLenCRCCalc = MESS_HEADER_LENGTH_BYTE + iLenBy; const int iLenCRCCalc = MESS_HEADER_LENGTH_BYTE + iLenBy;
iCurPos = 0; // start from the beginning iCurPos = 0; // start from the beginning
for ( i = 0; i < iLenCRCCalc; i++ ) for ( i = 0; i < iLenCRCCalc; i++ )
{ {
CRCObj.AddByte ( static_cast<uint8_t> ( CRCObj.AddByte ( static_cast<uint8_t> (
@ -1624,7 +1648,9 @@ bool CProtocol::ParseMessageFrame ( const CVector<uint8_t>& vecIn,
// Extract actual data ----------------------------------------------------- // Extract actual data -----------------------------------------------------
vecData.Init ( iLenBy ); vecData.Init ( iLenBy );
iCurPos = MESS_HEADER_LENGTH_BYTE; // start from beginning of data iCurPos = MESS_HEADER_LENGTH_BYTE; // start from beginning of data
for ( i = 0; i < iLenBy; i++ ) for ( i = 0; i < iLenBy; i++ )
{ {
vecData[i] = static_cast<uint8_t> ( vecData[i] = static_cast<uint8_t> (
@ -1646,6 +1672,7 @@ uint32_t CProtocol::GetValFromStream ( const CVector<uint8_t>& vecIn,
Q_ASSERT ( vecIn.Size() >= iPos + iNumOfBytes ); Q_ASSERT ( vecIn.Size() >= iPos + iNumOfBytes );
uint32_t iRet = 0; uint32_t iRet = 0;
for ( int i = 0; i < iNumOfBytes; i++ ) for ( int i = 0; i < iNumOfBytes; i++ )
{ {
iRet |= vecIn[iPos] << ( i * 8 /* size of byte */ ); iRet |= vecIn[iPos] << ( i * 8 /* size of byte */ );
@ -1663,30 +1690,40 @@ bool CProtocol::GetStringFromStream ( const CVector<uint8_t>& vecIn,
/* /*
note: iPos is automatically incremented in this function note: iPos is automatically incremented in this function
*/ */
// check if at least two bytes are available
const int iInLen = vecIn.Size(); const int iInLen = vecIn.Size();
// check if at least two bytes are available
if ( ( iInLen - iPos ) < 2 ) if ( ( iInLen - iPos ) < 2 )
{ {
return true; // return error code return true; // return error code
} }
// number of bytes for string (2 bytes) // number of bytes for utf-8 string (2 bytes)
const int iStrLen = const int iStrUTF8Len =
static_cast<int> ( GetValFromStream ( vecIn, iPos, 2 ) ); static_cast<int> ( GetValFromStream ( vecIn, iPos, 2 ) );
if ( ( ( iInLen - iPos ) < iStrLen ) || // (note that iPos was incremented by 2 in the above code!)
( iStrLen > iMaxStringLen ) ) if ( ( iInLen - iPos ) < iStrUTF8Len )
{ {
return true; // return error code return true; // return error code
} }
// string (n bytes) // string (n bytes)
strOut = ""; QByteArray sStringUTF8;
for ( int i = 0; i < iStrLen; i++ )
for ( int i = 0; i < iStrUTF8Len; i++ )
{ {
// byte-by-byte copying of the string data // byte-by-byte copying of the string data
int iData = static_cast<int> ( GetValFromStream ( vecIn, iPos, 1 ) ); sStringUTF8.append ( static_cast<char> ( GetValFromStream ( vecIn, iPos, 1 ) ) );
strOut += QString ( (char*) &iData ); }
// convert utf-8 byte array in the return string
strOut = QString::fromUtf8 ( sStringUTF8 );
// check length of actual string
if ( strOut.size() > iMaxStringLen )
{
return true; // return error code
} }
return false; // no error return false; // no error
@ -1738,9 +1775,11 @@ void CProtocol::GenMessageFrame ( CVector<uint8_t>& vecOut,
// Encode CRC -------------------------------------------------------------- // Encode CRC --------------------------------------------------------------
CCRC CRCObj; CCRC CRCObj;
iCurPos = 0; // start from beginning iCurPos = 0; // start from beginning
const int iLenCRCCalc = MESS_HEADER_LENGTH_BYTE + iDataLenByte; const int iLenCRCCalc = MESS_HEADER_LENGTH_BYTE + iDataLenByte;
for ( i = 0; i < iLenCRCCalc; i++ ) for ( i = 0; i < iLenCRCCalc; i++ )
{ {
CRCObj.AddByte ( static_cast<uint8_t> ( CRCObj.AddByte ( static_cast<uint8_t> (
@ -1772,22 +1811,22 @@ void CProtocol::PutValOnStream ( CVector<uint8_t>& vecIn,
} }
} }
void CProtocol::PutStringOnStream ( CVector<uint8_t>& vecIn, void CProtocol::PutStringUTF8OnStream ( CVector<uint8_t>& vecIn,
int& iPos, int& iPos,
const QString& sString ) const QByteArray& sStringUTF8 )
{ {
// get the string size // get the utf-8 string size
const int iStrLen = sString.size(); const int iStrUTF8Len = sStringUTF8.size();
// number of bytes for string (2 bytes) // number of bytes for utf-8 string (2 bytes)
PutValOnStream ( vecIn, iPos, PutValOnStream ( vecIn, iPos,
static_cast<uint32_t> ( iStrLen ), 2 ); static_cast<uint32_t> ( iStrUTF8Len ), 2 );
// actual string (n bytes) // actual utf-8 string (n bytes)
for ( int j = 0; j < iStrLen; j++ ) for ( int j = 0; j < iStrUTF8Len; j++ )
{ {
// byte-by-byte copying of the string data // byte-by-byte copying of the utf-8 string data
PutValOnStream ( vecIn, iPos, PutValOnStream ( vecIn, iPos,
static_cast<uint32_t> ( sString[j].toLatin1() ), 1 ); static_cast<uint32_t> ( sStringUTF8[j] ), 1 );
} }
} }

View File

@ -165,14 +165,14 @@ protected:
const int iID, const int iID,
const CVector<uint8_t>& vecData ); const CVector<uint8_t>& vecData );
void PutValOnStream ( CVector<uint8_t>& vecIn, void PutValOnStream ( CVector<uint8_t>& vecIn,
int& iPos, int& iPos,
const uint32_t iVal, const uint32_t iVal,
const int iNumOfBytes ); const int iNumOfBytes );
void PutStringOnStream ( CVector<uint8_t>& vecIn, void PutStringUTF8OnStream ( CVector<uint8_t>& vecIn,
int& iPos, int& iPos,
const QString& sString ); const QByteArray& sStringUTF8 );
uint32_t GetValFromStream ( const CVector<uint8_t>& vecIn, uint32_t GetValFromStream ( const CVector<uint8_t>& vecIn,
int& iPos, int& iPos,