bool readString(const char*& data, const char* end, String& result, const char* dbgLabel)
{
    unsigned stringLength;
    if (!readUnsigned(data, end, stringLength)) {
        ALOGW("Not enough data to read string length; tag=\"%s\" end=%p data=%p",
              dbgLabel ? dbgLabel : "<no tag>", end, data);
        return false;
    }

    if (dbgLabel)
        ALOGV("Reading %-16s %d %.*s", dbgLabel, stringLength, stringLength, data);

    // If length was 0, there will be no string content, but still return true
    if (!stringLength) {
        result = String();
        return true;
    }

    if ((end < data) || ((unsigned)(end - data) < stringLength)) {
        ALOGW("Not enough data to read content; tag=\"%s\" end=%p data=%p stringLength=%u",
              dbgLabel ? dbgLabel : "<no tag>", end, data, stringLength);
        return false;
    }

    const unsigned MAX_REASONABLE_STRING_LENGTH = 10000;
    if (stringLength > MAX_REASONABLE_STRING_LENGTH) {
        ALOGW("String length is suspiciously large (>%d); tag=\"%s\" end=%p data=%p stringLength=%u",
              MAX_REASONABLE_STRING_LENGTH, dbgLabel ? dbgLabel : "<no tag>",
              end, data, stringLength);
    }

    bool decodeFailed = false;
    static const WebCore::TextEncoding& encoding = WebCore::UTF8Encoding();
    result = encoding.decode(data, stringLength, true, decodeFailed);
    if (decodeFailed) {
        ALOGW("Decode failed, tag=\"%s\" end=%p data=%p stringLength=%u content=\"%s\"",
              dbgLabel ? dbgLabel : "<no tag>", end, data, stringLength,
              result.utf8().data());
        return false;
    }

    if (stringLength > MAX_REASONABLE_STRING_LENGTH) {
        ALOGW("\tdecodeFailed=%d (flag is ignored) content=\"%s\"",
              decodeFailed, result.utf8().data());
    }

    data += stringLength;
    return true;
}
Exemple #2
0
bool Bitmap::getImageSize(const io::Producer &file, size_t &width, size_t &height) {
	StackBuffer<256> data;
    if (file.seekAndRead(0, data, 30) < 30) {
    	return false;
    }

	if (isPng(data.data(), data.size()) && data.size() >= 24) {
		auto reader = DataReader<ByteOrder::Network>(data.data() + 16, 8);

		width = reader.readUnsigned32();
		height = reader.readUnsigned32();

	    return true;
	} else if(isJpg(data.data(), data.size())) {
		size_t offset = 2;
		uint16_t len = 0;
		uint8_t marker = 0;

		auto reader = DataReader<ByteOrder::Network>(data.data() + 2, data.size() - 2);
		while (reader.is((uint8_t)0xFF)) {
			++ reader;
		}

		marker = reader.readUnsigned();
		len = reader.readUnsigned16();

		while (marker < 0xC0 || marker > 0xCF) {
			offset += 2 + len;
			data.clear();

			if (file.seekAndRead(offset, data, 12) != 12) {
				return false;
			}

			if (data.size() >= 12) {
				reader = data.get<DataReader<ByteOrder::Network>>();

				while (reader.is((uint8_t)0xFF)) {
					++ reader;
				}

				marker = reader.readUnsigned();
				len = reader.readUnsigned16();
			} else {
				reader.clear();
				break;
			}
		}

		if (reader >= 5 && marker >= 0xC0 && marker <= 0xCF) {
			++ reader;
			height = reader.readUnsigned16();
			width = reader.readUnsigned16();
			return true;
		}

		return false;
	} else if (isGif(data.data(), data.size())) {
		auto reader = DataReader<ByteOrder::Little>(data.data() + 6, 4);

		width = reader.readUnsigned16();
		height = reader.readUnsigned16();

	    return true;
	} else if (isWebp(data.data(), data.size())) {
		auto reader = DataReader<ByteOrder::Little>(data.data() + 26, 4);

		width = reader.readUnsigned16();
		height = reader.readUnsigned16();

	    return true;
	} else if (isTiff(data.data(), data.size())) {
		if (memcmp(data.data(), "II", 2) == 0) {
			if (Bitmap_getTiffImageSize<DataReader<ByteOrder::Little>>(data, file, width, height)) {
				return true;
			}
		} else {
			if (Bitmap_getTiffImageSize<DataReader<ByteOrder::Big>>(data, file, width, height)) {
				return true;
			}
		}
	}

    return false;
}
static bool readItemRecursive(WebCore::HistoryItem* newItem,
        const char** pData, int length)
{
    if (!pData || length < HISTORY_MIN_SIZE) {
        ALOGW("readItemRecursive() bad params; pData=%p length=%d", pData, length);
        return false;
    }

    const char* data = *pData;
    const char* end = data + length;
    String content;

    // Read the original url
    if (readString(data, end, content, "Original url"))
        newItem->setOriginalURLString(content);
    else
        return false;

    // Read the url
    if (readString(data, end, content, "Url"))
        newItem->setURLString(content);
    else
        return false;

    // Read the title
    if (readString(data, end, content, "Title"))
        newItem->setTitle(content);
    else
        return false;

    // Generate a new ResourceRequest object for populating form information.
    // Read the form content type
    WTF::String formContentType;
    if (!readString(data, end, formContentType, "Content type"))
        return false;

    // Read the form data size
    unsigned formDataSize;
    if (!readUnsigned(data, end, formDataSize, "Form data size"))
        return false;

    // Read the form data
    WTF::RefPtr<WebCore::FormData> formData;
    if (formDataSize) {
        ALOGV("Reading Form data       %d %.*s", formDataSize, formDataSize, data);
        if ((end < data) || ((size_t)(end - data) < formDataSize)) {
            ALOGW("\tNot enough data to read form data; returning");
            return false;
        }
        formData = WebCore::FormData::create(data, formDataSize);
        data += formDataSize;
        // Read the identifier
        int64_t id;
        if (!readInt64(data, end, id, "Form id"))
            return false;
        if (id)
            formData->setIdentifier(id);
    }

    // Set up the form info
    if (formData != NULL) {
        WebCore::ResourceRequest r;
        r.setHTTPMethod("POST");
        r.setHTTPContentType(formContentType);
        r.setHTTPBody(formData);
        newItem->setFormInfoFromRequest(r);
    }

    // Read the target
    if (readString(data, end, content, "Target"))
        newItem->setTarget(content);
    else
        return false;

    AndroidWebHistoryBridge* bridge = newItem->bridge();
    ALOG_ASSERT(bridge, "There should be a bridge object during inflate");

    // Read the screen scale
    float fValue;
    if (readFloat(data, end, fValue, "Screen scale"))
        bridge->setScale(fValue);
    else
        return false;

    // Read the text wrap scale
    if (readFloat(data, end, fValue, "Text wrap scale"))
        bridge->setTextWrapScale(fValue);
    else
        return false;

    // Read scroll position.
    int scrollX;
    if (!readInt(data, end, scrollX, "Scroll pos x"))
        return false;
    int scrollY;
    if (!readInt(data, end, scrollY, "Scroll pos y"))
        return false;
    newItem->setScrollPoint(IntPoint(scrollX, scrollY));

    // Read the document state
    unsigned docStateCount;
    if (!readUnsigned(data, end, docStateCount, "Doc state count"))
        return false;
    if (docStateCount) {
        // Create a new vector and reserve enough space for the document state.
        WTF::Vector<WTF::String> docState;
        docState.reserveCapacity(docStateCount);
        while (docStateCount--) {
            // Read a document state string
            if (readString(data, end, content, "Document state"))
                docState.append(content);
            else
                return false;
        }
        newItem->setDocumentState(docState);
    }

    // Read is target item
    bool c;
    if (readBool(data, end, c, "Target item"))
        newItem->setIsTargetItem(c);
    else
        return false;

    // Read the child count
    unsigned count;
    if (!readUnsigned(data, end, count, "Child count"))
        return false;
    *pData = data;
    if (count) {
        while (count--) {
            // No need to check the length each time because read_item_recursive
            // will return null if there isn't enough data left to parse.
            WTF::RefPtr<WebCore::HistoryItem> child = WebCore::HistoryItem::create();
            // Set a bridge that will not call into java.
            child->setBridge(new WebHistoryItem(static_cast<WebHistoryItem*>(bridge)));
            // Read the child item.
            if (!readItemRecursive(child.get(), pData, end - data))
                return false;
            child->bridge()->setActive();
            newItem->addChildItem(child);
        }
    }
    return true;
}