Don't break IRC control characters in some encodings

Fix #577
This commit is contained in:
Alexey Sokolov
2014-12-21 17:09:59 +00:00
parent bd9450b99e
commit 8930fc4d7a
6 changed files with 95 additions and 4 deletions
+2 -2
View File
@@ -82,9 +82,9 @@ protected:
CClient* m_pClient;
};
class CClient : public CZNCSock {
class CClient : public CIRCSocket {
public:
CClient() : CZNCSock() {
CClient() : CIRCSocket() {
m_pUser = NULL;
m_pNetwork = NULL;
m_bGotPass = false;
+2 -1
View File
@@ -30,7 +30,8 @@ class CIRCNetwork;
class CClient;
// !Forward Declarations
class CIRCSock : public CZNCSock {
// TODO: This class needs new name
class CIRCSock : public CIRCSocket {
public:
CIRCSock(CIRCNetwork* pNetwork);
virtual ~CIRCSock();
+33
View File
@@ -220,4 +220,37 @@ protected:
CModule* m_pModule; //!< pointer to the module that this sock instance belongs to
};
/**
* @class CIRCSocket
* @brief Base IRC socket for client<->ZNC, and ZNC<->server
*/
class CIRCSocket : public CZNCSock {
public:
#ifdef HAVE_ICU
/**
* @brief Allow IRC control characters to appear even if protocol encoding explicitly disallows them.
*
* E.g. ISO-2022-JP disallows 0x0F, which in IRC means "reset format",
* so by default it gets replaced with U+FFFD ("replacement character").
* https://code.google.com/p/chromium/issues/detail?id=277062#c3
*
* In case if protocol encoding uses these code points for something else, the encoding takes preference,
* and they are not IRC control characters anymore.
*/
void IcuExtToUCallback(
UConverterToUnicodeArgs* toArgs,
const char* codeUnits,
int32_t length,
UConverterCallbackReason reason,
UErrorCode* err) override;
void IcuExtFromUCallback(
UConverterFromUnicodeArgs* fromArgs,
const UChar* codeUnits,
int32_t length,
UChar32 codePoint,
UConverterCallbackReason reason,
UErrorCode* err) override;
#endif
};
#endif /* SOCKET_H */
+1 -1
View File
@@ -54,7 +54,7 @@ bool CIRCSock::IsFloodProtected(double fRate) {
return fRate > FLOOD_MINIMAL_RATE;
}
CIRCSock::CIRCSock(CIRCNetwork* pNetwork) : CZNCSock() {
CIRCSock::CIRCSock(CIRCNetwork* pNetwork) : CIRCSocket() {
m_pNetwork = pNetwork;
m_bAuthed = false;
m_bNamesx = false;
+55
View File
@@ -22,6 +22,10 @@
#include <znc/znc.h>
#include <signal.h>
#ifdef HAVE_ICU
#include <unicode/ucnv_cb.h>
#endif
CZNCSock::CZNCSock(int timeout) : Csock(timeout) {
#ifdef HAVE_LIBSSL
DisableSSLCompression();
@@ -487,3 +491,54 @@ bool CSocket::Listen(unsigned short uPort, bool bSSL, unsigned int uTimeout) {
CModule* CSocket::GetModule() const { return m_pModule; }
/////////////////// !CSocket ///////////////////
#ifdef HAVE_ICU
void CIRCSocket::IcuExtToUCallback(
UConverterToUnicodeArgs* toArgs,
const char* codeUnits,
int32_t length,
UConverterCallbackReason reason,
UErrorCode* err) {
// From http://www.mirc.com/colors.html
// The Control+O key combination in mIRC inserts ascii character 15,
// which turns off all previous attributes, including color, bold, underline, and italics.
//
// \x02 bold
// \x03 mIRC-compatible color
// \x04 RRGGBB color
// \x0F normal/reset (turn off bold, colors, etc.)
// \x12 reverse (weechat)
// \x16 reverse (mirc, kvirc)
// \x1D italic
// \x1F underline
// Also see http://www.visualirc.net/tech-attrs.php
//
// Keep in sync with CUser::AddTimestamp and CIRCSocket::IcuExtFromUCallback
static const std::set<char> scAllowedChars = {'\x02', '\x03', '\x04', '\x0F', '\x12', '\x16', '\x1D', '\x1F'};
if (reason == UCNV_ILLEGAL && length == 1 && scAllowedChars.count(*codeUnits)) {
*err = U_ZERO_ERROR;
UChar c = *codeUnits;
ucnv_cbToUWriteUChars(toArgs, &c, 1, 0, err);
return;
}
Csock::IcuExtToUCallback(toArgs, codeUnits, length, reason, err);
}
void CIRCSocket::IcuExtFromUCallback(
UConverterFromUnicodeArgs* fromArgs,
const UChar* codeUnits,
int32_t length,
UChar32 codePoint,
UConverterCallbackReason reason,
UErrorCode* err) {
// See comment in CIRCSocket::IcuExtToUCallback
static const std::set<UChar32> scAllowedChars = {0x02, 0x03, 0x04, 0x0F, 0x12, 0x16, 0x1D, 0x1F};
if (reason == UCNV_ILLEGAL && scAllowedChars.count(codePoint)) {
*err = U_ZERO_ERROR;
char c = codePoint;
ucnv_cbFromUWriteBytes(fromArgs, &c, 1, 0, err);
return;
}
Csock::IcuExtFromUCallback(fromArgs, codeUnits, length, codePoint, reason, err);
}
#endif
+2
View File
@@ -577,6 +577,8 @@ CString CUser::AddTimestamp(time_t tm, const CString& sStr) const {
// \x1D italic
// \x1F underline
// Also see http://www.visualirc.net/tech-attrs.php
//
// Keep in sync with CIRCSocket::IcuExt__UCallback
if (CString::npos != sRet.find_first_of("\x02\x03\x04\x0F\x12\x16\x1D\x1F")) {
sRet += "\x0F";
}