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