Repository: ericsson/codechecker
Issue: Commenting on an issue using quotes results to the error "No closing quotation"

I select any issue and mark it as "confirmed", entering a message in the comment box that includes at least a single quote. For example:
```
test
quotes'blah
```

Then I refresh the page and try to expand the comment section on the right hand side. I get a red error box, while on the server console I get:

```
[WARNING][2020-12-10 17:27:21] {server} [1468928] <140291968911104> - report_server.py:145 wrapper() - getComments:
No closing quotation
```

Changed files:
web/tests/functional/comment/test_comment.py, web/server/codechecker_server/api/report_server.py

diff --git a/web/server/codechecker_server/api/report_server.py b/web/server/codechecker_server/api/report_server.py
index c2d3f41c..d2f40d51 100644
--- a/web/server/codechecker_server/api/report_server.py
+++ b/web/server/codechecker_server/api/report_server.py
@@ -716,12 +716,23 @@ def get_comment_msg(comment):
     """
     context = webserver_context.get_context()
     message = comment.message.decode('utf-8')
-    sys_comment = comment_kind_from_thrift_type(
-        ttypes.CommentKind.SYSTEM)
+    sys_comment = comment_kind_from_thrift_type(ttypes.CommentKind.SYSTEM)
+
     if comment.kind == sys_comment:
-        elements = shlex.split(message)
-        system_comment = context.system_comment_map.get(
-            elements[0])
+        try:
+            elements = shlex.split(message)
+        except ValueError:
+            # In earlier CodeChecker we saved system comments
+            # without escaping special characters such as
+            # quotes. This is kept only for backward
+            # compatibility reason.
+            message = message \\
+                .replace("'", "\\\\'") \\
+                .replace('"', '\\\\"')
+
+            elements = shlex.split(message)
+
+        system_comment = context.system_comment_map.get(elements[0])
         if system_comment:
             for idx, value in enumerate(elements[1:]):
                 system_comment = system_comment.replace(
@@ -896,17 +907,6 @@ def sort_run_data_query(query, sort_mode):
     return query
 
 
-def escape_whitespaces(s, whitespaces=None):
-    if not whitespaces:
-        whitespaces = [' ', '\\n', '\\t', '\\r']
-
-    escaped = s
-    for w in whitespaces:
-        escaped = escaped.replace(w, '\\\\{0}'.format(w))
-
-    return escaped
-
-
 def get_failed_files_query(session, run_ids, query_fields,
                            extra_sub_query_fields=None):
     """
@@ -1611,14 +1611,13 @@ class ThriftRequestHandler(object):
 
         # Create a system comment if the review status or the message
         # is changed.
-        old_review_status = escape_whitespaces(old_status.capitalize())
-        new_review_status = \\
-            escape_whitespaces(review_status.status.capitalize())
+        old_review_status = old_status.capitalize()
+        new_review_status = review_status.status.capitalize()
         if message:
             system_comment_msg = \\
                 'rev_st_changed_msg {0} {1} {2}'.format(
                     old_review_status, new_review_status,
-                    escape_whitespaces(message))
+                    shlex.quote(message))
         else:
             system_comment_msg = 'rev_st_changed {0} {1}'.format(
                 old_review_status, new_review_status)
@@ -1784,8 +1783,8 @@ class ThriftRequestHandler(object):
                 message = comment.message.decode('utf-8')
                 if message != content:
                     system_comment_msg = 'comment_changed {0} {1}'.format(
-                        escape_whitespaces(message),
-                        escape_whitespaces(content))
+                        shlex.quote(message),
+                        shlex.quote(content))
 
                     system_comment = \\
                         self.__add_comment(comment.bug_hash,
diff --git a/web/tests/functional/comment/test_comment.py b/web/tests/functional/comment/test_comment.py
index 58cdbb2c..5a596ef0 100644
--- a/web/tests/functional/comment/test_comment.py
+++ b/web/tests/functional/comment/test_comment.py
@@ -160,7 +160,7 @@ class TestComment(unittest.TestCase):
         self.assertEqual(num_comment, 1)
 
         # Edit the message of the first remaining comment
-        new_msg = 'New msg'
+        new_msg = "New msg'\\"`"
         success = self._cc_client.updateComment(comments[0].id, new_msg)
         self.assertTrue(success)
         logging.debug('Comment edited successfully')