| 41 | } |
| 42 | |
| 43 | void SaveStringWithCDATA(Writer & writer, std::string s) |
| 44 | { |
| 45 | if (s.empty()) |
| 46 | return; |
| 47 | |
| 48 | // Expat loads XML 1.0 only. Sometimes users copy and paste bookmark descriptions or even names from the web. |
| 49 | // Rarely, in these copy-pasted texts, there are invalid XML1.0 symbols. |
| 50 | // See https://en.wikipedia.org/wiki/Valid_characters_in_XML |
| 51 | // A robust solution requires parsing invalid XML on loading (then users can restore "bad" XML files), see |
| 52 | // https://github.com/organicmaps/organicmaps/issues/3837 |
| 53 | // When a robust solution is implemented, this workaround can be removed for better performance/battery. |
| 54 | // |
| 55 | // This solution is a simple ASCII-range check that does not check symbols from other unicode ranges |
| 56 | // (they will require a more complex and slower approach of converting UTF-8 string to unicode first). |
| 57 | // It should be enough for many cases, according to user reports and wrong characters in their data. |
| 58 | s.erase(std::remove_if(s.begin(), s.end(), |
| 59 | [](unsigned char c) |
| 60 | { |
| 61 | if (c >= 0x20 || c == 0x09 || c == 0x0a || c == 0x0d) |
| 62 | return false; |
| 63 | return true; |
| 64 | }), |
| 65 | s.end()); |
| 66 | |
| 67 | if (s.empty()) |
| 68 | return; |
| 69 | |
| 70 | // According to kml/xml spec, we need to escape special symbols with CDATA. |
| 71 | if (s.find_first_of("<&") != std::string::npos) |
| 72 | writer << "<![CDATA[" << s << "]]>"; |
| 73 | else |
| 74 | writer << s; |
| 75 | } |
| 76 | |
| 77 | std::string const * GetDefaultLanguage(LocalizableString const & lstr) |
| 78 | { |
no test coverage detected