Home | History | Annotate | Download | only in json
      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