From 8acd7a02aeda01c0ac828b05c36f10bbacaea70e Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sat, 9 Nov 2013 23:20:12 +0100 Subject: Aaaand, I forgot to add files --- src/bridge/colors.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/bridge/colors.cpp (limited to 'src/bridge/colors.cpp') diff --git a/src/bridge/colors.cpp b/src/bridge/colors.cpp new file mode 100644 index 0000000..f49f31f --- /dev/null +++ b/src/bridge/colors.cpp @@ -0,0 +1,20 @@ +#include +#include + +#include + +void remove_irc_colors(std::string& str) +{ + auto it = std::remove_if(str.begin(), str.end(), + [](const char c) + { + if (c == IRC_COLOR_BOLD_CHAR || c == IRC_COLOR_COLOR_CHAR || + c == IRC_COLOR_FIXED_CHAR || c == IRC_COLOR_RESET_CHAR || + c == IRC_COLOR_REVERSE_CHAR || c == IRC_COLOR_REVERSE2_CHAR || + c == IRC_COLOR_UNDERLINE_CHAR || c == IRC_COLOR_ITALIC_CHAR) + return true; + return false; + } + ); + str.erase(it, str.end()); +} -- cgit v1.2.3 From abce2fc92ec80e95066f6362492351b85ad8aef1 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 13 Nov 2013 01:36:30 +0100 Subject: Do not crash on special chars in the content of message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit That’s ugly, and we need to sanitize everything properly, and also handle these special messages. --- src/bridge/colors.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/bridge/colors.cpp') diff --git a/src/bridge/colors.cpp b/src/bridge/colors.cpp index f49f31f..b34ab4a 100644 --- a/src/bridge/colors.cpp +++ b/src/bridge/colors.cpp @@ -11,7 +11,11 @@ void remove_irc_colors(std::string& str) if (c == IRC_COLOR_BOLD_CHAR || c == IRC_COLOR_COLOR_CHAR || c == IRC_COLOR_FIXED_CHAR || c == IRC_COLOR_RESET_CHAR || c == IRC_COLOR_REVERSE_CHAR || c == IRC_COLOR_REVERSE2_CHAR || - c == IRC_COLOR_UNDERLINE_CHAR || c == IRC_COLOR_ITALIC_CHAR) + c == IRC_COLOR_UNDERLINE_CHAR || c == IRC_COLOR_ITALIC_CHAR || + // HACK: until we properly handle things + // like ^AVERSION^A, remove the ^A chars + // here. + c == '\u0001') return true; return false; } -- cgit v1.2.3 From fba01f46468050d4f3b8eb35373ed49a3584868e Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Fri, 22 Nov 2013 21:00:07 +0100 Subject: Remove incomplete implementation of remove_irc_colors --- src/bridge/colors.cpp | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'src/bridge/colors.cpp') diff --git a/src/bridge/colors.cpp b/src/bridge/colors.cpp index b34ab4a..2f30354 100644 --- a/src/bridge/colors.cpp +++ b/src/bridge/colors.cpp @@ -3,22 +3,5 @@ #include -void remove_irc_colors(std::string& str) { - auto it = std::remove_if(str.begin(), str.end(), - [](const char c) - { - if (c == IRC_COLOR_BOLD_CHAR || c == IRC_COLOR_COLOR_CHAR || - c == IRC_COLOR_FIXED_CHAR || c == IRC_COLOR_RESET_CHAR || - c == IRC_COLOR_REVERSE_CHAR || c == IRC_COLOR_REVERSE2_CHAR || - c == IRC_COLOR_UNDERLINE_CHAR || c == IRC_COLOR_ITALIC_CHAR || - // HACK: until we properly handle things - // like ^AVERSION^A, remove the ^A chars - // here. - c == '\u0001') - return true; - return false; - } - ); - str.erase(it, str.end()); } -- cgit v1.2.3 From e6f20d3c0fd4ba8696a4410a366741c9b9f3562d Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Fri, 22 Nov 2013 21:00:32 +0100 Subject: Implement IRC format to xhtml-im conversion The generated XML is very verbose because each IRC formatting tag makes us close a element and reopen it with the new style applied. However, this works quite well and is easy to implement. --- src/bridge/colors.cpp | 162 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) (limited to 'src/bridge/colors.cpp') diff --git a/src/bridge/colors.cpp b/src/bridge/colors.cpp index 2f30354..024121b 100644 --- a/src/bridge/colors.cpp +++ b/src/bridge/colors.cpp @@ -1,7 +1,169 @@ #include +#include +#include + #include #include +#include + +static const char IRC_NUM_COLORS = 16; + +static const char* irc_colors_to_css[IRC_NUM_COLORS] = { + "white", + "black", + "blue", + "green", + "indianred", + "red", + "magenta", + "brown", + "yellow", + "lightgreen", + "cyan", + "lightcyan", + "lightblue", + "lightmagenta", + "gray", + "white", +}; + +#define XHTML_NS "http://www.w3.org/1999/xhtml" + +struct styles_t { + bool strong; + bool underline; + bool italic; + int fg; + int bg; +}; + +/** We keep the currently-applied CSS styles in a structure. Each time a tag + * is found, update this style list, then close the current span XML element + * (if it is open), then reopen it with all the new styles in it. This is + * done this way because IRC formatting does not map well with XML + * (hierarchical tags), it’s a lot easier and cleaner to remove all styles + * and reapply them for each tag, instead of trying to keep a consistent + * hierarchy of span, strong, em etc tags. The generated XML is one-level + * deep only. +*/ +Xmpp::body irc_format_to_xhtmlim(const std::string& s) +{ + if (s.find_first_of(irc_format_char) == std::string::npos) + // there is no special formatting at all + return std::make_tuple(s, nullptr); + + std::string cleaned; + + styles_t styles = {false, false, false, -1, -1}; + + std::unique_ptr result = std::make_unique("body"); + (*result)["xmlns"] = XHTML_NS; + + XmlNode* current_node = result.get(); + std::string::size_type pos_start = 0; + std::string::size_type pos_end; + + while ((pos_end = s.find_first_of(irc_format_char, pos_start)) != std::string::npos) + { + const std::string txt = s.substr(pos_start, pos_end-pos_start); + cleaned += txt; + if (current_node->has_children()) + current_node->get_last_child()->set_tail(txt); + else + current_node->set_inner(txt); + + if (s[pos_end] == IRC_FORMAT_BOLD_CHAR) + styles.strong = !styles.strong; + else if (s[pos_end] == IRC_FORMAT_UNDERLINE_CHAR) + styles.underline = !styles.underline; + else if (s[pos_end] == IRC_FORMAT_ITALIC_CHAR) + styles.italic = !styles.italic; + else if (s[pos_end] == IRC_FORMAT_RESET_CHAR) + styles = {false, false, false, -1, -1}; + else if (s[pos_end] == IRC_FORMAT_REVERSE_CHAR) + { } // TODO + else if (s[pos_end] == IRC_FORMAT_REVERSE2_CHAR) + { } // TODO + else if (s[pos_end] == IRC_FORMAT_FIXED_CHAR) + { } // TODO + else if (s[pos_end] == IRC_FORMAT_COLOR_CHAR) + { + size_t pos = pos_end + 1; + styles.fg = -1; + styles.bg = -1; + // get the first number following the format char + if (pos < s.size() && s[pos] >= '0' && s[pos] <= '9') + { // first digit + styles.fg = s[pos++] - '0'; + if (pos < s.size() && s[pos] >= '0' && s[pos] <= '9') + // second digit + styles.fg = styles.fg * 10 + s[pos++] - '0'; + } + if (pos < s.size() && s[pos] == ',') + { // get bg color after the comma + pos++; + if (pos < s.size() && s[pos] >= '0' && s[pos] <= '9') + { // first digit + styles.bg = s[pos++] - '0'; + if (pos < s.size() && s[pos] >= '0' && s[pos] <= '9') + // second digit + styles.bg = styles.bg * 10 + s[pos++] - '0'; + } + } + pos_end = pos - 1; + } + + // close opened span, if any + if (current_node != result.get()) + { + current_node->close(); + result->add_child(current_node); + current_node = result.get(); + } + // Take all currently-applied style and create a new span with it + std::string styles_str; + if (styles.strong) + styles_str += "font-weight:bold;"; + if (styles.underline) + styles_str += "text-decoration:underline;"; + if (styles.italic) + styles_str += "font-style:italic;"; + if (styles.fg != -1) + styles_str += std::string("color:") + + irc_colors_to_css[styles.fg % IRC_NUM_COLORS] + ";"; + if (styles.bg != -1) + styles_str += std::string("background-color:") + + irc_colors_to_css[styles.bg % IRC_NUM_COLORS] + ";"; + if (!styles_str.empty()) + { + current_node = new XmlNode("span"); + (*current_node)["style"] = styles_str; + } + + pos_start = pos_end + 1; + } + + // If some text remains, without any format char, just append that text at + // the end of the current node + const std::string txt = s.substr(pos_start, pos_end-pos_start); + cleaned += txt; + if (current_node->has_children()) + current_node->get_last_child()->set_tail(txt); + else + current_node->set_inner(txt); + + if (current_node != result.get()) + { + current_node->close(); + result->add_child(current_node); + current_node = result.get(); + } + + + result->close(); + Xmpp::body body_res = std::make_tuple(cleaned, std::move(result)); + return body_res; } -- cgit v1.2.3 From bd7936bdfe799d6b665c4b2bd30a5210592d9ae4 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Thu, 17 Apr 2014 20:37:46 +0200 Subject: No more missing text when converting IRC colors to xhtml-im fix #2496 --- src/bridge/colors.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/bridge/colors.cpp') diff --git a/src/bridge/colors.cpp b/src/bridge/colors.cpp index 024121b..e42c5a3 100644 --- a/src/bridge/colors.cpp +++ b/src/bridge/colors.cpp @@ -71,7 +71,7 @@ Xmpp::body irc_format_to_xhtmlim(const std::string& s) const std::string txt = s.substr(pos_start, pos_end-pos_start); cleaned += txt; if (current_node->has_children()) - current_node->get_last_child()->set_tail(txt); + current_node->get_last_child()->add_to_tail(txt); else current_node->set_inner(txt); -- cgit v1.2.3 From 114007f10dbc77fdc71c34689fc20ce3e3111492 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Fri, 18 Apr 2014 10:45:28 +0200 Subject: Actually do the last commit, but completely this time --- src/bridge/colors.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/bridge/colors.cpp') diff --git a/src/bridge/colors.cpp b/src/bridge/colors.cpp index e42c5a3..aff001e 100644 --- a/src/bridge/colors.cpp +++ b/src/bridge/colors.cpp @@ -73,7 +73,7 @@ Xmpp::body irc_format_to_xhtmlim(const std::string& s) if (current_node->has_children()) current_node->get_last_child()->add_to_tail(txt); else - current_node->set_inner(txt); + current_node->add_to_inner(txt); if (s[pos_end] == IRC_FORMAT_BOLD_CHAR) styles.strong = !styles.strong; @@ -151,9 +151,9 @@ Xmpp::body irc_format_to_xhtmlim(const std::string& s) const std::string txt = s.substr(pos_start, pos_end-pos_start); cleaned += txt; if (current_node->has_children()) - current_node->get_last_child()->set_tail(txt); + current_node->get_last_child()->add_to_tail(txt); else - current_node->set_inner(txt); + current_node->add_to_inner(txt); if (current_node != result.get()) { -- cgit v1.2.3 From c6059e5a215624e205cae401183f3a8bb1bf87d0 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Mon, 28 Apr 2014 18:46:25 +0200 Subject: Upgrade to C++14 --- src/bridge/colors.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/bridge/colors.cpp') diff --git a/src/bridge/colors.cpp b/src/bridge/colors.cpp index aff001e..49f7a39 100644 --- a/src/bridge/colors.cpp +++ b/src/bridge/colors.cpp @@ -1,9 +1,7 @@ #include #include -#include #include - #include #include -- cgit v1.2.3 From f6e6b8905be010d7329316cea4546900ad8a2d19 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Tue, 29 Apr 2014 21:50:13 +0200 Subject: Use C++14 string_literals --- src/bridge/colors.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/bridge/colors.cpp') diff --git a/src/bridge/colors.cpp b/src/bridge/colors.cpp index 49f7a39..6f6d7a9 100644 --- a/src/bridge/colors.cpp +++ b/src/bridge/colors.cpp @@ -6,6 +6,8 @@ #include +using namespace std::string_literals; + static const char IRC_NUM_COLORS = 16; static const char* irc_colors_to_css[IRC_NUM_COLORS] = { @@ -130,10 +132,10 @@ Xmpp::body irc_format_to_xhtmlim(const std::string& s) if (styles.italic) styles_str += "font-style:italic;"; if (styles.fg != -1) - styles_str += std::string("color:") + + styles_str += "color:"s + irc_colors_to_css[styles.fg % IRC_NUM_COLORS] + ";"; if (styles.bg != -1) - styles_str += std::string("background-color:") + + styles_str += "background-color:"s + irc_colors_to_css[styles.bg % IRC_NUM_COLORS] + ";"; if (!styles_str.empty()) { -- cgit v1.2.3 From 3d9183557f3ad9b599c812c03a445453e7d4f703 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Sun, 8 Jun 2014 05:35:36 +0200 Subject: Convert \n to
in xhtml body fix #2539 --- src/bridge/colors.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/bridge/colors.cpp') diff --git a/src/bridge/colors.cpp b/src/bridge/colors.cpp index 6f6d7a9..3aed07c 100644 --- a/src/bridge/colors.cpp +++ b/src/bridge/colors.cpp @@ -77,6 +77,13 @@ Xmpp::body irc_format_to_xhtmlim(const std::string& s) if (s[pos_end] == IRC_FORMAT_BOLD_CHAR) styles.strong = !styles.strong; + else if (s[pos_end] == IRC_FORMAT_NEWLINE_CHAR) + { + XmlNode* br_node = new XmlNode("br"); + br_node->close(); + current_node->add_child(br_node); + cleaned += '\n'; + } else if (s[pos_end] == IRC_FORMAT_UNDERLINE_CHAR) styles.underline = !styles.underline; else if (s[pos_end] == IRC_FORMAT_ITALIC_CHAR) -- cgit v1.2.3 From 720e31a5113c25e48d7754bb812ab84c6c31d1d9 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 17 Dec 2014 13:37:57 +0100 Subject: Fix a few issues reported by static analyzers --- src/bridge/colors.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/bridge/colors.cpp') diff --git a/src/bridge/colors.cpp b/src/bridge/colors.cpp index 3aed07c..3d40ac4 100644 --- a/src/bridge/colors.cpp +++ b/src/bridge/colors.cpp @@ -166,10 +166,8 @@ Xmpp::body irc_format_to_xhtmlim(const std::string& s) { current_node->close(); result->add_child(current_node); - current_node = result.get(); } - result->close(); Xmpp::body body_res = std::make_tuple(cleaned, std::move(result)); return body_res; -- cgit v1.2.3 From e8f22efe34415db0e1e5cb94635b089b18efe055 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Tue, 1 Sep 2015 04:42:12 +0200 Subject: XmlNodes are now always closed Remove the close() method and closed attribute. Remove all the calls to close(). (Save one bool per XmlNode, yay, and save a few ifs and some useless function calls. At best it should be unnoticeably faster and lighter and save a few keystrokes in the future) --- src/bridge/colors.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'src/bridge/colors.cpp') diff --git a/src/bridge/colors.cpp b/src/bridge/colors.cpp index 3d40ac4..bdc34bf 100644 --- a/src/bridge/colors.cpp +++ b/src/bridge/colors.cpp @@ -80,7 +80,6 @@ Xmpp::body irc_format_to_xhtmlim(const std::string& s) else if (s[pos_end] == IRC_FORMAT_NEWLINE_CHAR) { XmlNode* br_node = new XmlNode("br"); - br_node->close(); current_node->add_child(br_node); cleaned += '\n'; } @@ -126,7 +125,6 @@ Xmpp::body irc_format_to_xhtmlim(const std::string& s) // close opened span, if any if (current_node != result.get()) { - current_node->close(); result->add_child(current_node); current_node = result.get(); } @@ -163,12 +161,8 @@ Xmpp::body irc_format_to_xhtmlim(const std::string& s) current_node->add_to_inner(txt); if (current_node != result.get()) - { - current_node->close(); - result->add_child(current_node); - } + result->add_child(current_node); - result->close(); Xmpp::body body_res = std::make_tuple(cleaned, std::move(result)); return body_res; } -- cgit v1.2.3 From f3b3d937ae274d0eec4a737d11ba19a7f4ceef03 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Tue, 1 Sep 2015 14:47:57 +0200 Subject: =?UTF-8?q?Use=20unique=5Fptr=20to=20store=20the=20XmlNode?= =?UTF-8?q?=E2=80=99s=20children?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also fix some constness things --- src/bridge/colors.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'src/bridge/colors.cpp') diff --git a/src/bridge/colors.cpp b/src/bridge/colors.cpp index bdc34bf..66f51ee 100644 --- a/src/bridge/colors.cpp +++ b/src/bridge/colors.cpp @@ -62,7 +62,9 @@ Xmpp::body irc_format_to_xhtmlim(const std::string& s) std::unique_ptr result = std::make_unique("body"); (*result)["xmlns"] = XHTML_NS; + std::unique_ptr current_node_up; XmlNode* current_node = result.get(); + std::string::size_type pos_start = 0; std::string::size_type pos_end; @@ -79,8 +81,7 @@ Xmpp::body irc_format_to_xhtmlim(const std::string& s) styles.strong = !styles.strong; else if (s[pos_end] == IRC_FORMAT_NEWLINE_CHAR) { - XmlNode* br_node = new XmlNode("br"); - current_node->add_child(br_node); + current_node->add_child(std::make_unique("br")); cleaned += '\n'; } else if (s[pos_end] == IRC_FORMAT_UNDERLINE_CHAR) @@ -125,7 +126,7 @@ Xmpp::body irc_format_to_xhtmlim(const std::string& s) // close opened span, if any if (current_node != result.get()) { - result->add_child(current_node); + result->add_child(std::move(current_node_up)); current_node = result.get(); } // Take all currently-applied style and create a new span with it @@ -144,7 +145,8 @@ Xmpp::body irc_format_to_xhtmlim(const std::string& s) irc_colors_to_css[styles.bg % IRC_NUM_COLORS] + ";"; if (!styles_str.empty()) { - current_node = new XmlNode("span"); + current_node_up = std::make_unique("span"); + current_node = current_node_up.get(); (*current_node)["style"] = styles_str; } @@ -161,7 +163,7 @@ Xmpp::body irc_format_to_xhtmlim(const std::string& s) current_node->add_to_inner(txt); if (current_node != result.get()) - result->add_child(current_node); + result->add_child(std::move(current_node_up)); Xmpp::body body_res = std::make_tuple(cleaned, std::move(result)); return body_res; -- cgit v1.2.3