static bool decode(Decoder& decoder, FormDataElement& element) { uint32_t type; if (!decoder.decodeUInt32(type)) return false; switch (type) { case FormDataElement::data: { element.m_type = FormDataElement::data; Vector<uint8_t> data; if (!decoder.decodeBytes(data)) return false; size_t size = data.size(); element.m_data.resize(size); memcpy(element.m_data.data(), data.data(), size); return true; } case FormDataElement::encodedFile: { element.m_type = FormDataElement::encodedFile; if (!decoder.decodeString(element.m_filename)) return false; if (!decoder.decodeBool(element.m_shouldGenerateFile)) return false; int64_t fileStart; if (!decoder.decodeInt64(fileStart)) return false; if (fileStart < 0) return false; int64_t fileLength; if (!decoder.decodeInt64(fileLength)) return false; if (fileLength < fileStart) return false; double expectedFileModificationTime; if (!decoder.decodeDouble(expectedFileModificationTime)) return false; #if ENABLE(BLOB) element.m_fileStart = fileStart; element.m_fileLength = fileLength; element.m_expectedFileModificationTime = expectedFileModificationTime; #endif return true; } #if ENABLE(BLOB) case FormDataElement::encodedBlob: element.m_type = FormDataElement::encodedBlob; String blobURLString; if (!decoder.decodeString(blobURLString)) return false; element.m_blobURL = KURL(KURL(), blobURLString); return true; #endif } return false; }
static bool decodeElement(Decoder& decoder, FormDataElement& element) { uint32_t type; if (!decoder.decodeUInt32(type)) return false; switch (static_cast<FormDataElement::Type>(type)) { case FormDataElement::Type::Data: { element.m_type = FormDataElement::Type::Data; Vector<uint8_t> data; if (!decoder.decodeBytes(data)) return false; size_t size = data.size(); element.m_data.resize(size); memcpy(element.m_data.data(), data.data(), size); return true; } case FormDataElement::Type::EncodedFile: { element.m_type = static_cast<FormDataElement::Type>(type); String filenameOrURL; if (!decoder.decodeString(filenameOrURL)) return false; if (static_cast<FormDataElement::Type>(type) == FormDataElement::Type::EncodedFile) { if (!decoder.decodeString(element.m_generatedFilename)) return false; if (!decoder.decodeBool(element.m_shouldGenerateFile)) return false; } int64_t fileStart; if (!decoder.decodeInt64(fileStart)) return false; if (fileStart < 0) return false; int64_t fileLength; if (!decoder.decodeInt64(fileLength)) return false; if (fileLength != BlobDataItem::toEndOfFile && fileLength < fileStart) return false; double expectedFileModificationTime; if (!decoder.decodeDouble(expectedFileModificationTime)) return false; element.m_filename = filenameOrURL; element.m_fileStart = fileStart; element.m_fileLength = fileLength; element.m_expectedFileModificationTime = expectedFileModificationTime; return true; } case FormDataElement::Type::EncodedBlob: element.m_type = FormDataElement::Type::EncodedBlob; String blobURLString; if (!decoder.decodeString(blobURLString)) return false; element.m_url = URL(URL(), blobURLString); return true; } return false; }
PassRefPtr<HistoryItem> HistoryItem::decodeBackForwardTree(const String& topURLString, const String& topTitle, const String& topOriginalURLString, Decoder& decoder) { // Since the data stream is not trusted, the decode has to be non-recursive. // We don't want bad data to cause a stack overflow. uint32_t version; if (!decoder.decodeUInt32(version)) return 0; if (version != backForwardTreeEncodingVersion) return 0; String urlString = topURLString; String title = topTitle; String originalURLString = topOriginalURLString; Vector<DecodeRecursionStackElement, 16> recursionStack; recurse: RefPtr<HistoryItem> node = create(urlString, title, 0); node->setOriginalURLString(originalURLString); title = String(); uint64_t size; if (!decoder.decodeUInt64(size)) return 0; size_t i; RefPtr<HistoryItem> child; for (i = 0; i < size; ++i) { if (!decoder.decodeString(originalURLString)) return 0; if (!decoder.decodeString(urlString)) return 0; recursionStack.append(DecodeRecursionStackElement(node.release(), i, size)); goto recurse; resume: node->m_children.append(child.release()); } if (!decoder.decodeInt64(node->m_documentSequenceNumber)) return 0; if (!decoder.decodeUInt64(size)) return 0; for (i = 0; i < size; ++i) { String state; if (!decoder.decodeString(state)) return 0; node->m_documentState.append(state); } if (!decoder.decodeString(node->m_formContentType)) return 0; bool hasFormData; if (!decoder.decodeBool(hasFormData)) return 0; if (hasFormData) { node->m_formData = FormData::decode(decoder); if (!node->m_formData) return 0; } if (!decoder.decodeInt64(node->m_itemSequenceNumber)) return 0; if (!decoder.decodeString(node->m_referrer)) return 0; int32_t x; if (!decoder.decodeInt32(x)) return 0; int32_t y; if (!decoder.decodeInt32(y)) return 0; node->m_scrollPoint = IntPoint(x, y); if (!decoder.decodeFloat(node->m_pageScaleFactor)) return 0; bool hasStateObject; if (!decoder.decodeBool(hasStateObject)) return 0; if (hasStateObject) { Vector<uint8_t> bytes; if (!decoder.decodeBytes(bytes)) return 0; node->m_stateObject = SerializedScriptValue::adopt(bytes); } if (!decoder.decodeString(node->m_target)) return 0; // Simulate recursion with our own stack. if (!recursionStack.isEmpty()) { DecodeRecursionStackElement& element = recursionStack.last(); child = node.release(); node = element.node.release(); i = element.i; size = element.size; recursionStack.removeLast(); goto resume; } return node.release(); }