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