/** * Translate a "rows" or "cols" spec into an array of nsFramesetSpecs */ nsresult HTMLFrameSetElement::ParseRowCol(const nsAString & aValue, int32_t& aNumSpecs, UniquePtr<nsFramesetSpec[]>* aSpecs) { if (aValue.IsEmpty()) { aNumSpecs = 0; *aSpecs = nullptr; return NS_OK; } static const char16_t sAster('*'); static const char16_t sPercent('%'); static const char16_t sComma(','); nsAutoString spec(aValue); // remove whitespace (Bug 33699) and quotation marks (bug 224598) // also remove leading/trailing commas (bug 31482) spec.StripChars(" \n\r\t\"\'"); spec.Trim(","); // Count the commas. Don't count more than X commas (bug 576447). static_assert(NS_MAX_FRAMESET_SPEC_COUNT * sizeof(nsFramesetSpec) < (1 << 30), "Too many frameset specs allowed to allocate"); int32_t commaX = spec.FindChar(sComma); int32_t count = 1; while (commaX != kNotFound && count < NS_MAX_FRAMESET_SPEC_COUNT) { count++; commaX = spec.FindChar(sComma, commaX + 1); } auto specs = MakeUniqueFallible<nsFramesetSpec[]>(count); if (!specs) { *aSpecs = nullptr; aNumSpecs = 0; return NS_ERROR_OUT_OF_MEMORY; } // Pre-grab the compat mode; we may need it later in the loop. bool isInQuirks = InNavQuirksMode(OwnerDoc()); // Parse each comma separated token int32_t start = 0; int32_t specLen = spec.Length(); for (int32_t i = 0; i < count; i++) { // Find our comma commaX = spec.FindChar(sComma, start); NS_ASSERTION(i == count - 1 || commaX != kNotFound, "Failed to find comma, somehow"); int32_t end = (commaX == kNotFound) ? specLen : commaX; // Note: If end == start then it means that the token has no // data in it other than a terminating comma (or the end of the spec). // So default to a fixed width of 0. specs[i].mUnit = eFramesetUnit_Fixed; specs[i].mValue = 0; if (end > start) { int32_t numberEnd = end; char16_t ch = spec.CharAt(numberEnd - 1); if (sAster == ch) { specs[i].mUnit = eFramesetUnit_Relative; numberEnd--; } else if (sPercent == ch) { specs[i].mUnit = eFramesetUnit_Percent; numberEnd--; // check for "*%" if (numberEnd > start) { ch = spec.CharAt(numberEnd - 1); if (sAster == ch) { specs[i].mUnit = eFramesetUnit_Relative; numberEnd--; } } } // Translate value to an integer nsAutoString token; spec.Mid(token, start, numberEnd - start); // Treat * as 1* if ((eFramesetUnit_Relative == specs[i].mUnit) && (0 == token.Length())) { specs[i].mValue = 1; } else { // Otherwise just convert to integer. nsresult err; specs[i].mValue = token.ToInteger(&err); if (NS_FAILED(err)) { specs[i].mValue = 0; } } // Treat 0* as 1* in quirks mode (bug 40383) if (isInQuirks) { if ((eFramesetUnit_Relative == specs[i].mUnit) && (0 == specs[i].mValue)) { specs[i].mValue = 1; } } // Catch zero and negative frame sizes for Nav compatibility // Nav resized absolute and relative frames to "1" and // percent frames to an even percentage of the width // //if (isInQuirks && (specs[i].mValue <= 0)) { // if (eFramesetUnit_Percent == specs[i].mUnit) { // specs[i].mValue = 100 / count; // } else { // specs[i].mValue = 1; // } //} else { // In standards mode, just set negative sizes to zero if (specs[i].mValue < 0) { specs[i].mValue = 0; } start = end + 1; } } aNumSpecs = count; // Transfer ownership to caller here *aSpecs = Move(specs); return NS_OK; }
bool HTMLTableCellElement::ParseAttribute(int32_t aNamespaceID, nsIAtom* aAttribute, const nsAString& aValue, nsAttrValue& aResult) { if (aNamespaceID == kNameSpaceID_None) { /* ignore these attributes, stored simply as strings abbr, axis, ch, headers */ if (aAttribute == nsGkAtoms::charoff) { /* attributes that resolve to integers with a min of 0 */ return aResult.ParseIntWithBounds(aValue, 0); } if (aAttribute == nsGkAtoms::colspan) { bool res = aResult.ParseIntWithBounds(aValue, -1); if (res) { int32_t val = aResult.GetIntegerValue(); // reset large colspan values as IE and opera do // quirks mode does not honor the special html 4 value of 0 if (val > MAX_COLSPAN || val < 0 || (0 == val && InNavQuirksMode(OwnerDoc()))) { aResult.SetTo(1); } } return res; } if (aAttribute == nsGkAtoms::rowspan) { bool res = aResult.ParseIntWithBounds(aValue, -1, MAX_ROWSPAN); if (res) { int32_t val = aResult.GetIntegerValue(); // quirks mode does not honor the special html 4 value of 0 if (val < 0 || (0 == val && InNavQuirksMode(OwnerDoc()))) { aResult.SetTo(1); } } return res; } if (aAttribute == nsGkAtoms::height) { return aResult.ParseSpecialIntValue(aValue); } if (aAttribute == nsGkAtoms::width) { return aResult.ParseSpecialIntValue(aValue); } if (aAttribute == nsGkAtoms::align) { return ParseTableCellHAlignValue(aValue, aResult); } if (aAttribute == nsGkAtoms::bgcolor) { return aResult.ParseColor(aValue); } if (aAttribute == nsGkAtoms::scope) { return aResult.ParseEnumValue(aValue, kCellScopeTable, false); } if (aAttribute == nsGkAtoms::valign) { return ParseTableVAlignValue(aValue, aResult); } } return nsGenericHTMLElement::ParseBackgroundAttribute(aNamespaceID, aAttribute, aValue, aResult) || nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue, aResult); }