1 /* 2 * Copyright (C) 2010 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "config.h" 32 #include "platform/JSONValues.h" 33 34 #include "platform/Decimal.h" 35 #include "wtf/MathExtras.h" 36 #include "wtf/text/StringBuilder.h" 37 38 namespace WebCore { 39 40 namespace { 41 42 const char* const nullString = "null"; 43 const char* const trueString = "true"; 44 const char* const falseString = "false"; 45 46 inline bool escapeChar(UChar c, StringBuilder* dst) 47 { 48 switch (c) { 49 case '\b': dst->append("\\b", 2); break; 50 case '\f': dst->append("\\f", 2); break; 51 case '\n': dst->append("\\n", 2); break; 52 case '\r': dst->append("\\r", 2); break; 53 case '\t': dst->append("\\t", 2); break; 54 case '\\': dst->append("\\\\", 2); break; 55 case '"': dst->append("\\\"", 2); break; 56 default: 57 return false; 58 } 59 return true; 60 } 61 62 inline void doubleQuoteString(const String& str, StringBuilder* dst) 63 { 64 dst->append('"'); 65 for (unsigned i = 0; i < str.length(); ++i) { 66 UChar c = str[i]; 67 if (!escapeChar(c, dst)) { 68 if (c < 32 || c > 126 || c == '<' || c == '>') { 69 // 1. Escaping <, > to prevent script execution. 70 // 2. Technically, we could also pass through c > 126 as UTF8, but this 71 // is also optional. It would also be a pain to implement here. 72 unsigned symbol = static_cast<unsigned>(c); 73 String symbolCode = String::format("\\u%04X", symbol); 74 dst->append(symbolCode); 75 } else { 76 dst->append(c); 77 } 78 } 79 } 80 dst->append('"'); 81 } 82 83 } // anonymous namespace 84 85 bool JSONValue::asBoolean(bool*) const 86 { 87 return false; 88 } 89 90 bool JSONValue::asNumber(double*) const 91 { 92 return false; 93 } 94 95 bool JSONValue::asNumber(long*) const 96 { 97 return false; 98 } 99 100 bool JSONValue::asNumber(int*) const 101 { 102 return false; 103 } 104 105 bool JSONValue::asNumber(unsigned long*) const 106 { 107 return false; 108 } 109 110 bool JSONValue::asNumber(unsigned*) const 111 { 112 return false; 113 } 114 115 bool JSONValue::asString(String*) const 116 { 117 return false; 118 } 119 120 bool JSONValue::asValue(RefPtr<JSONValue>* output) 121 { 122 *output = this; 123 return true; 124 } 125 126 bool JSONValue::asObject(RefPtr<JSONObject>*) 127 { 128 return false; 129 } 130 131 bool JSONValue::asArray(RefPtr<JSONArray>*) 132 { 133 return false; 134 } 135 136 PassRefPtr<JSONObject> JSONValue::asObject() 137 { 138 return nullptr; 139 } 140 141 PassRefPtr<JSONArray> JSONValue::asArray() 142 { 143 return nullptr; 144 } 145 146 String JSONValue::toJSONString() const 147 { 148 StringBuilder result; 149 result.reserveCapacity(512); 150 writeJSON(&result); 151 return result.toString(); 152 } 153 154 void JSONValue::writeJSON(StringBuilder* output) const 155 { 156 ASSERT(m_type == TypeNull); 157 output->append(nullString, 4); 158 } 159 160 bool JSONBasicValue::asBoolean(bool* output) const 161 { 162 if (type() != TypeBoolean) 163 return false; 164 *output = m_boolValue; 165 return true; 166 } 167 168 bool JSONBasicValue::asNumber(double* output) const 169 { 170 if (type() != TypeNumber) 171 return false; 172 *output = m_doubleValue; 173 return true; 174 } 175 176 bool JSONBasicValue::asNumber(long* output) const 177 { 178 if (type() != TypeNumber) 179 return false; 180 *output = static_cast<long>(m_doubleValue); 181 return true; 182 } 183 184 bool JSONBasicValue::asNumber(int* output) const 185 { 186 if (type() != TypeNumber) 187 return false; 188 *output = static_cast<int>(m_doubleValue); 189 return true; 190 } 191 192 bool JSONBasicValue::asNumber(unsigned long* output) const 193 { 194 if (type() != TypeNumber) 195 return false; 196 *output = static_cast<unsigned long>(m_doubleValue); 197 return true; 198 } 199 200 bool JSONBasicValue::asNumber(unsigned* output) const 201 { 202 if (type() != TypeNumber) 203 return false; 204 *output = static_cast<unsigned>(m_doubleValue); 205 return true; 206 } 207 208 void JSONBasicValue::writeJSON(StringBuilder* output) const 209 { 210 ASSERT(type() == TypeBoolean || type() == TypeNumber); 211 if (type() == TypeBoolean) { 212 if (m_boolValue) 213 output->append(trueString, 4); 214 else 215 output->append(falseString, 5); 216 } else if (type() == TypeNumber) { 217 if (!std::isfinite(m_doubleValue)) { 218 output->append(nullString, 4); 219 return; 220 } 221 output->append(Decimal::fromDouble(m_doubleValue).toString()); 222 } 223 } 224 225 bool JSONString::asString(String* output) const 226 { 227 *output = m_stringValue; 228 return true; 229 } 230 231 void JSONString::writeJSON(StringBuilder* output) const 232 { 233 ASSERT(type() == TypeString); 234 doubleQuoteString(m_stringValue, output); 235 } 236 237 JSONObjectBase::~JSONObjectBase() 238 { 239 } 240 241 bool JSONObjectBase::asObject(RefPtr<JSONObject>* output) 242 { 243 COMPILE_ASSERT(sizeof(JSONObject) == sizeof(JSONObjectBase), cannot_cast); 244 *output = static_cast<JSONObject*>(this); 245 return true; 246 } 247 248 PassRefPtr<JSONObject> JSONObjectBase::asObject() 249 { 250 return openAccessors(); 251 } 252 253 void JSONObjectBase::setBoolean(const String& name, bool value) 254 { 255 setValue(name, JSONBasicValue::create(value)); 256 } 257 258 void JSONObjectBase::setNumber(const String& name, double value) 259 { 260 setValue(name, JSONBasicValue::create(value)); 261 } 262 263 void JSONObjectBase::setString(const String& name, const String& value) 264 { 265 setValue(name, JSONString::create(value)); 266 } 267 268 void JSONObjectBase::setValue(const String& name, PassRefPtr<JSONValue> value) 269 { 270 ASSERT(value); 271 if (m_data.set(name, value).isNewEntry) 272 m_order.append(name); 273 } 274 275 void JSONObjectBase::setObject(const String& name, PassRefPtr<JSONObject> value) 276 { 277 ASSERT(value); 278 if (m_data.set(name, value).isNewEntry) 279 m_order.append(name); 280 } 281 282 void JSONObjectBase::setArray(const String& name, PassRefPtr<JSONArray> value) 283 { 284 ASSERT(value); 285 if (m_data.set(name, value).isNewEntry) 286 m_order.append(name); 287 } 288 289 JSONObject* JSONObjectBase::openAccessors() 290 { 291 COMPILE_ASSERT(sizeof(JSONObject) == sizeof(JSONObjectBase), cannot_cast); 292 return static_cast<JSONObject*>(this); 293 } 294 295 JSONObjectBase::iterator JSONObjectBase::find(const String& name) 296 { 297 return m_data.find(name); 298 } 299 300 JSONObjectBase::const_iterator JSONObjectBase::find(const String& name) const 301 { 302 return m_data.find(name); 303 } 304 305 bool JSONObjectBase::getBoolean(const String& name, bool* output) const 306 { 307 RefPtr<JSONValue> value = get(name); 308 if (!value) 309 return false; 310 return value->asBoolean(output); 311 } 312 313 bool JSONObjectBase::getString(const String& name, String* output) const 314 { 315 RefPtr<JSONValue> value = get(name); 316 if (!value) 317 return false; 318 return value->asString(output); 319 } 320 321 PassRefPtr<JSONObject> JSONObjectBase::getObject(const String& name) const 322 { 323 RefPtr<JSONValue> value = get(name); 324 if (!value) 325 return nullptr; 326 return value->asObject(); 327 } 328 329 PassRefPtr<JSONArray> JSONObjectBase::getArray(const String& name) const 330 { 331 RefPtr<JSONValue> value = get(name); 332 if (!value) 333 return nullptr; 334 return value->asArray(); 335 } 336 337 PassRefPtr<JSONValue> JSONObjectBase::get(const String& name) const 338 { 339 Dictionary::const_iterator it = m_data.find(name); 340 if (it == m_data.end()) 341 return nullptr; 342 return it->value; 343 } 344 345 void JSONObjectBase::remove(const String& name) 346 { 347 m_data.remove(name); 348 for (size_t i = 0; i < m_order.size(); ++i) { 349 if (m_order[i] == name) { 350 m_order.remove(i); 351 break; 352 } 353 } 354 } 355 356 void JSONObjectBase::writeJSON(StringBuilder* output) const 357 { 358 output->append('{'); 359 for (size_t i = 0; i < m_order.size(); ++i) { 360 Dictionary::const_iterator it = m_data.find(m_order[i]); 361 ASSERT_WITH_SECURITY_IMPLICATION(it != m_data.end()); 362 if (i) 363 output->append(','); 364 doubleQuoteString(it->key, output); 365 output->append(':'); 366 it->value->writeJSON(output); 367 } 368 output->append('}'); 369 } 370 371 JSONObjectBase::JSONObjectBase() 372 : JSONValue(TypeObject) 373 , m_data() 374 , m_order() 375 { 376 } 377 378 JSONArrayBase::~JSONArrayBase() 379 { 380 } 381 382 bool JSONArrayBase::asArray(RefPtr<JSONArray>* output) 383 { 384 COMPILE_ASSERT(sizeof(JSONArrayBase) == sizeof(JSONArray), cannot_cast); 385 *output = static_cast<JSONArray*>(this); 386 return true; 387 } 388 389 PassRefPtr<JSONArray> JSONArrayBase::asArray() 390 { 391 COMPILE_ASSERT(sizeof(JSONArrayBase) == sizeof(JSONArray), cannot_cast); 392 return static_cast<JSONArray*>(this); 393 } 394 395 void JSONArrayBase::writeJSON(StringBuilder* output) const 396 { 397 output->append('['); 398 for (Vector<RefPtr<JSONValue> >::const_iterator it = m_data.begin(); it != m_data.end(); ++it) { 399 if (it != m_data.begin()) 400 output->append(','); 401 (*it)->writeJSON(output); 402 } 403 output->append(']'); 404 } 405 406 JSONArrayBase::JSONArrayBase() 407 : JSONValue(TypeArray) 408 , m_data() 409 { 410 } 411 412 void JSONArrayBase::pushBoolean(bool value) 413 { 414 m_data.append(JSONBasicValue::create(value)); 415 } 416 417 void JSONArrayBase::pushInt(int value) 418 { 419 m_data.append(JSONBasicValue::create(value)); 420 } 421 422 void JSONArrayBase::pushNumber(double value) 423 { 424 m_data.append(JSONBasicValue::create(value)); 425 } 426 427 void JSONArrayBase::pushString(const String& value) 428 { 429 m_data.append(JSONString::create(value)); 430 } 431 432 void JSONArrayBase::pushValue(PassRefPtr<JSONValue> value) 433 { 434 ASSERT(value); 435 m_data.append(value); 436 } 437 438 void JSONArrayBase::pushObject(PassRefPtr<JSONObject> value) 439 { 440 ASSERT(value); 441 m_data.append(value); 442 } 443 444 void JSONArrayBase::pushArray(PassRefPtr<JSONArray> value) 445 { 446 ASSERT(value); 447 m_data.append(value); 448 } 449 450 PassRefPtr<JSONValue> JSONArrayBase::get(size_t index) 451 { 452 ASSERT_WITH_SECURITY_IMPLICATION(index < m_data.size()); 453 return m_data[index]; 454 } 455 456 } // namespace WebCore 457