1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/json/string_escape.h" 6 7 #include <string> 8 9 #include "base/strings/string_util.h" 10 #include "base/strings/stringprintf.h" 11 12 namespace base { 13 14 namespace { 15 16 // Try to escape |c| as a "SingleEscapeCharacter" (\n, etc). If successful, 17 // returns true and appends the escape sequence to |dst|. This isn't required 18 // by the spec, but it's more readable by humans than the \uXXXX alternatives. 19 template<typename CHAR> 20 static bool JsonSingleEscapeChar(const CHAR c, std::string* dst) { 21 // WARNING: if you add a new case here, you need to update the reader as well. 22 // Note: \v is in the reader, but not here since the JSON spec doesn't 23 // allow it. 24 switch (c) { 25 case '\b': 26 dst->append("\\b"); 27 break; 28 case '\f': 29 dst->append("\\f"); 30 break; 31 case '\n': 32 dst->append("\\n"); 33 break; 34 case '\r': 35 dst->append("\\r"); 36 break; 37 case '\t': 38 dst->append("\\t"); 39 break; 40 case '\\': 41 dst->append("\\\\"); 42 break; 43 case '"': 44 dst->append("\\\""); 45 break; 46 default: 47 return false; 48 } 49 return true; 50 } 51 52 template <class STR> 53 void JsonDoubleQuoteT(const STR& str, 54 bool put_in_quotes, 55 std::string* dst) { 56 if (put_in_quotes) 57 dst->push_back('"'); 58 59 for (typename STR::const_iterator it = str.begin(); it != str.end(); ++it) { 60 typename ToUnsigned<typename STR::value_type>::Unsigned c = *it; 61 if (!JsonSingleEscapeChar(c, dst)) { 62 if (c < 32 || c > 126 || c == '<' || c == '>') { 63 // 1. Escaping <, > to prevent script execution. 64 // 2. Technically, we could also pass through c > 126 as UTF8, but this 65 // is also optional. It would also be a pain to implement here. 66 unsigned int as_uint = static_cast<unsigned int>(c); 67 base::StringAppendF(dst, "\\u%04X", as_uint); 68 } else { 69 unsigned char ascii = static_cast<unsigned char>(*it); 70 dst->push_back(ascii); 71 } 72 } 73 } 74 75 if (put_in_quotes) 76 dst->push_back('"'); 77 } 78 79 } // namespace 80 81 void JsonDoubleQuote(const std::string& str, 82 bool put_in_quotes, 83 std::string* dst) { 84 JsonDoubleQuoteT(str, put_in_quotes, dst); 85 } 86 87 std::string GetDoubleQuotedJson(const std::string& str) { 88 std::string dst; 89 JsonDoubleQuote(str, true, &dst); 90 return dst; 91 } 92 93 void JsonDoubleQuote(const string16& str, 94 bool put_in_quotes, 95 std::string* dst) { 96 JsonDoubleQuoteT(str, put_in_quotes, dst); 97 } 98 99 std::string GetDoubleQuotedJson(const string16& str) { 100 std::string dst; 101 JsonDoubleQuote(str, true, &dst); 102 return dst; 103 } 104 105 } // namespace base 106