diff --git a/src/jdlib/miscutil.cpp b/src/jdlib/miscutil.cpp
index ffa5d7eb3..6fcd95eb1 100644
--- a/src/jdlib/miscutil.cpp
+++ b/src/jdlib/miscutil.cpp
@@ -837,12 +837,13 @@ std::string MISC::regex_unescape( const std::string& str )
}
-//
-// HTMLエスケープ
-//
-// include_url : URL中でもエスケープする( デフォルト = true )
-//
-std::string MISC::html_escape( const std::string& str, const bool include_url )
+/** @brief HTMLで特別な意味を持つ記号(& " < >)を文字実体参照へエスケープする
+ *
+ * @param[in] str エスケープする入力
+ * @param[in] completely URL中でもエスケープする( デフォルト = true )
+ * @return エスケープした結果
+ */
+std::string MISC::html_escape( const std::string& str, const bool completely )
{
if( str.empty() ) return str;
@@ -856,7 +857,7 @@ std::string MISC::html_escape( const std::string& str, const bool include_url )
char tmpchar = str.c_str()[ pos ];
// URL中はエスケープしない場合
- if( ! include_url )
+ if( ! completely )
{
// URLとして扱うかどうか
// エスケープには影響がないので loose_url としておく
@@ -875,17 +876,9 @@ std::string MISC::html_escape( const std::string& str, const bool include_url )
}
}
- // include_url = false でURL中ならエスケープしない
+ // completely = false でURL中ならエスケープしない
if( is_url ) str_out += tmpchar;
- else if( tmpchar == '&' )
- {
- const int bufsize = 64;
- char out_char[ bufsize ];
- int n_in, n_out;
- const int type = DBTREE::decode_char( str.c_str() + pos, n_in, out_char, n_out, false );
- if( type == DBTREE::NODE_NONE ) str_out += "&";
- else str_out += tmpchar;
- }
+ else if( tmpchar == '&' ) str_out += "&";
else if( tmpchar == '\"' ) str_out += """;
else if( tmpchar == '<' ) str_out += "<";
else if( tmpchar == '>' ) str_out += ">";
diff --git a/src/jdlib/miscutil.h b/src/jdlib/miscutil.h
index 985beb882..7ab6c23ca 100644
--- a/src/jdlib/miscutil.h
+++ b/src/jdlib/miscutil.h
@@ -138,9 +138,9 @@ namespace MISC
// 正規表現のメタ文字をアンエスケープ
std::string regex_unescape( const std::string& str );
- // HTMLエスケープ
- // include_url : URL中でもエスケープする( デフォルト = true )
- std::string html_escape( const std::string& str, const bool include_url = true );
+ // HTMLで特別な意味を持つ記号(& " < >)を文字実体参照へエスケープする
+ // completely : URL中でもエスケープする( デフォルト = true )
+ std::string html_escape( const std::string& str, const bool completely = true );
// HTMLアンエスケープ
std::string html_unescape( const std::string& str );
diff --git a/src/message/messageviewbase.cpp b/src/message/messageviewbase.cpp
index 2912864bd..8900e09d2 100644
--- a/src/message/messageviewbase.cpp
+++ b/src/message/messageviewbase.cpp
@@ -880,8 +880,14 @@ void MessageViewBase::slot_switch_page( Gtk::Widget*, guint page )
// URLを除外してエスケープ
const bool include_url = false;
std::string msg;
- if( m_text_message ) msg = MISC::html_escape( m_text_message->get_text(), include_url );
- msg = MISC::replace_str( msg, "\n", "
" );
+ if( m_text_message ) {
+ msg = m_text_message->get_text();
+
+ constexpr bool completely = true;
+ msg = MISC::chref_decode( msg, completely );
+ msg = MISC::html_escape( msg, include_url );
+ msg = MISC::replace_str( msg, "\n", "
" );
+ }
std::stringstream ss;
diff --git a/test/gtest_jdlib_miscutil.cpp b/test/gtest_jdlib_miscutil.cpp
index d897b8916..807fe9392 100644
--- a/test/gtest_jdlib_miscutil.cpp
+++ b/test/gtest_jdlib_miscutil.cpp
@@ -329,6 +329,53 @@ TEST_F(ReplaceNewlinesToStrTest, replace_crlf)
}
+class HtmlEscapeTest : public ::testing::Test {};
+
+TEST_F(HtmlEscapeTest, empty_data)
+{
+ EXPECT_EQ( "", MISC::html_escape( "", false ) );
+ EXPECT_EQ( "", MISC::html_escape( "", true ) );
+}
+
+TEST_F(HtmlEscapeTest, not_escape)
+{
+ EXPECT_EQ( "hello world", MISC::html_escape( "hello world", false ) );
+ EXPECT_EQ( "hello world", MISC::html_escape( "hello world", true ) );
+}
+
+TEST_F(HtmlEscapeTest, escape_amp)
+{
+ EXPECT_EQ( "hello&world", MISC::html_escape( "hello&world", false ) );
+ EXPECT_EQ( "hello&world", MISC::html_escape( "hello&world", true ) );
+}
+
+TEST_F(HtmlEscapeTest, escape_quot)
+{
+ EXPECT_EQ( "hello"world", MISC::html_escape( "hello\"world", false ) );
+ EXPECT_EQ( "hello"world", MISC::html_escape( "hello\"world", true ) );
+}
+
+TEST_F(HtmlEscapeTest, escape_lt)
+{
+ EXPECT_EQ( "hello<world", MISC::html_escape( "helloworld", false ) );
+ EXPECT_EQ( "hello>world", MISC::html_escape( "hello>world", true ) );
+}
+
+TEST_F(HtmlEscapeTest, completely)
+{
+ // URLを含むテキスト
+ const std::string input = "& https://foobar.test/?a=b&c=d& &";
+ EXPECT_EQ( "& https://foobar.test/?a=b&c=d& &", MISC::html_escape( input, true ) );
+ EXPECT_EQ( "& https://foobar.test/?a=b&c=d& &", MISC::html_escape( input, false ) );
+}
+
+
class IsUrlSchemeTest : public ::testing::Test {};
TEST_F(IsUrlSchemeTest, url_none)