mirror of
https://github.com/Basilisk-Development-Team/UXP-mirror.git
synced 2026-11-05 01:10:14 -05:00
Compare commits
23
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6b18be917d | ||
|
|
037cc5f614 | ||
|
|
4a68bbbd53 | ||
|
|
5762097bc2 | ||
|
|
e86caa48f5 | ||
|
|
612a8991df | ||
|
|
5c991eadc0 | ||
|
|
38e09d2368 | ||
|
|
8fea2ad823 | ||
|
|
c4339b14dc | ||
|
|
bae7a6ec8f | ||
|
|
d42616bb12 | ||
|
|
5f290d1097 | ||
|
|
a0b10f4375 | ||
|
|
1d7ba07673 | ||
|
|
f51bc72a14 | ||
|
|
e8644b494f | ||
|
|
0acf5cb1a1 | ||
|
|
f2d027343a | ||
|
|
eaf2a4ac4b | ||
|
|
aa6a599aa4 | ||
|
|
f385a5e06c | ||
|
|
559e0dbdc5 |
No files matched your search
+17230
-8908
File diff suppressed because it is too large.
Load diff
+969
-295
File diff suppressed because it is too large.
Load diff
@@ -695,7 +695,7 @@ nsContentList::ContentAppended(nsIDocument* aDocument, nsIContent* aContainer,
|
||||
!MayContainRelevantNodes(aContainer) ||
|
||||
(!aFirstNewContent->HasChildren() &&
|
||||
!aFirstNewContent->GetNextSibling() &&
|
||||
!MatchSelf(aFirstNewContent))) {
|
||||
!MatchSelf<MatchSelfMode::Insertion>(aFirstNewContent))) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -731,7 +731,7 @@ nsContentList::ContentAppended(nsIDocument* aDocument, nsIContent* aContainer,
|
||||
// The new stuff is somewhere in the middle of our list; check
|
||||
// whether we need to invalidate
|
||||
for (nsIContent* cur = aFirstNewContent; cur; cur = cur->GetNextSibling()) {
|
||||
if (MatchSelf(cur)) {
|
||||
if (MatchSelf<MatchSelfMode::Insertion>(cur)) {
|
||||
// Uh-oh. We're gonna have to add elements into the middle
|
||||
// of our list. That's not worth the effort.
|
||||
SetDirty();
|
||||
@@ -788,7 +788,7 @@ nsContentList::ContentInserted(nsIDocument *aDocument,
|
||||
if (mState != LIST_DIRTY &&
|
||||
MayContainRelevantNodes(NODE_FROM(aContainer, aDocument)) &&
|
||||
nsContentUtils::IsInSameAnonymousTree(mRootNode, aChild) &&
|
||||
MatchSelf(aChild)) {
|
||||
MatchSelf<MatchSelfMode::Insertion>(aChild)) {
|
||||
SetDirty();
|
||||
}
|
||||
|
||||
@@ -808,7 +808,7 @@ nsContentList::ContentRemoved(nsIDocument *aDocument,
|
||||
if (mState != LIST_DIRTY &&
|
||||
MayContainRelevantNodes(NODE_FROM(aContainer, aDocument)) &&
|
||||
nsContentUtils::IsInSameAnonymousTree(mRootNode, aChild) &&
|
||||
MatchSelf(aChild)) {
|
||||
MatchSelf<MatchSelfMode::Removal>(aChild)) {
|
||||
SetDirty();
|
||||
}
|
||||
|
||||
@@ -853,6 +853,7 @@ nsContentList::Match(Element *aElement)
|
||||
ni->Equals(mXMLMatchAtom, mMatchNameSpaceId);
|
||||
}
|
||||
|
||||
template <nsContentList::MatchSelfMode Mode>
|
||||
bool
|
||||
nsContentList::MatchSelf(nsIContent *aContent)
|
||||
{
|
||||
@@ -864,8 +865,20 @@ nsContentList::MatchSelf(nsIContent *aContent)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Match(aContent->AsElement()))
|
||||
auto matches = [&](Element* aElement) {
|
||||
if (Match(aElement)) {
|
||||
return true;
|
||||
}
|
||||
if constexpr (Mode == MatchSelfMode::Removal) {
|
||||
return mFunc == nsContentUtils::MatchClassNames &&
|
||||
aElement->IsSVGElement() && aElement->MayHaveClass();
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
if (matches(aContent->AsElement())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!mDeep)
|
||||
return false;
|
||||
@@ -873,7 +886,7 @@ nsContentList::MatchSelf(nsIContent *aContent)
|
||||
for (nsIContent* cur = aContent->GetFirstChild();
|
||||
cur;
|
||||
cur = cur->GetNextNode(aContent)) {
|
||||
if (cur->IsElement() && Match(cur->AsElement())) {
|
||||
if (cur->IsElement() && matches(cur->AsElement())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,6 +367,15 @@ protected:
|
||||
* @return whether we match
|
||||
*/
|
||||
bool Match(mozilla::dom::Element *aElement);
|
||||
|
||||
enum class MatchSelfMode : uint8_t {
|
||||
Insertion,
|
||||
// Also accept SVG elements that may have a class. SMIL can change their
|
||||
// class without notification, so they can be in the list without
|
||||
// matching now. Needed when aContent leaves the subtree.
|
||||
Removal,
|
||||
};
|
||||
|
||||
/**
|
||||
* See if anything in the subtree rooted at aContent, including
|
||||
* aContent itself, matches our criterion.
|
||||
@@ -374,6 +383,7 @@ protected:
|
||||
* @param aContent the root of the subtree to match against
|
||||
* @return whether we match something in the tree rooted at aContent
|
||||
*/
|
||||
template <MatchSelfMode Mode>
|
||||
bool MatchSelf(nsIContent *aContent);
|
||||
|
||||
/**
|
||||
|
||||
@@ -2073,6 +2073,10 @@ public:
|
||||
aClasses);
|
||||
}
|
||||
|
||||
static bool MatchClassNames(mozilla::dom::Element* aElement,
|
||||
int32_t aNamespaceID,
|
||||
nsIAtom* aAtom, void* aData);
|
||||
|
||||
/**
|
||||
* Returns a presshell for this document, if there is one. This will be
|
||||
* aDoc's direct presshell if there is one, otherwise we'll look at all
|
||||
@@ -3012,9 +3016,6 @@ private:
|
||||
|
||||
static void DropFragmentParsers();
|
||||
|
||||
static bool MatchClassNames(mozilla::dom::Element* aElement,
|
||||
int32_t aNamespaceID,
|
||||
nsIAtom* aAtom, void* aData);
|
||||
static void DestroyClassNameArray(void* aData);
|
||||
static void* AllocClassMatchingInfo(nsINode* aRootNode,
|
||||
const nsString* aClasses);
|
||||
|
||||
@@ -921,7 +921,7 @@ private:
|
||||
// List of nodes referred to by mEntryTable so we can sort them
|
||||
// For a specific pseudo element, we use its parent element as the
|
||||
// batch target, so they will be put in the same EntryArray.
|
||||
nsTArray<nsINode*> mBatchTargets;
|
||||
nsTArray<nsCOMPtr<nsINode>> mBatchTargets;
|
||||
};
|
||||
|
||||
inline
|
||||
|
||||
@@ -138,7 +138,9 @@ GetJSValFromKeyPathString(JSContext* aCx,
|
||||
// only through getters but we still want to support them for key
|
||||
// extraction. So they need to be handled manually.
|
||||
Blob* blob;
|
||||
if (NS_SUCCEEDED(UNWRAP_OBJECT(Blob, &obj, blob))) {
|
||||
// UNWRAP_OBJECT calls might mutate this.
|
||||
JS::Rooted<JSObject*> blobObj(aCx, obj);
|
||||
if (NS_SUCCEEDED(UNWRAP_OBJECT(Blob, &blobObj, blob))) {
|
||||
if (token.EqualsLiteral("size")) {
|
||||
ErrorResult rv;
|
||||
uint64_t size = blob->GetSize(rv);
|
||||
|
||||
@@ -1554,8 +1554,7 @@ FilterNodeTileSoftware::SetAttribute(uint32_t aIndex,
|
||||
const IntRect &aSourceRect)
|
||||
{
|
||||
MOZ_ASSERT(aIndex == ATT_TILE_SOURCE_RECT);
|
||||
mSourceRect = IntRect(int32_t(aSourceRect.x), int32_t(aSourceRect.y),
|
||||
int32_t(aSourceRect.width), int32_t(aSourceRect.height));
|
||||
mSourceRect = aSourceRect;
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
@@ -1595,14 +1594,24 @@ FilterNodeTileSoftware::Render(const IntRect& aRect)
|
||||
typedef std::map<IntRect, RefPtr<DataSourceSurface>, CompareIntRects> InputMap;
|
||||
InputMap inputs;
|
||||
|
||||
auto IntRectToInt64Rect = [](const IntRect& aRect) {
|
||||
return RectTyped<UnknownUnits, int64_t>(aRect.X(), aRect.Y(), aRect.Width(),
|
||||
aRect.Height());
|
||||
};
|
||||
|
||||
IntPoint startIndex = TileIndex(mSourceRect, aRect.TopLeft());
|
||||
IntPoint endIndex = TileIndex(mSourceRect, aRect.BottomRight());
|
||||
for (int32_t ix = startIndex.x; ix <= endIndex.x; ix++) {
|
||||
for (int32_t iy = startIndex.y; iy <= endIndex.y; iy++) {
|
||||
IntPoint sourceToDestOffset(ix * mSourceRect.width,
|
||||
iy * mSourceRect.height);
|
||||
IntRect destRect = aRect.Intersect(mSourceRect + sourceToDestOffset);
|
||||
IntRect srcRect = destRect - sourceToDestOffset;
|
||||
auto sourceToDestOffset = PointTyped<UnknownUnits, int64_t>(
|
||||
ix * mSourceRect.Width(), iy * mSourceRect.Height());
|
||||
auto destRect64 = IntRectToInt64Rect(aRect).Intersect(
|
||||
IntRectToInt64Rect(mSourceRect) + sourceToDestOffset);
|
||||
auto srcRect64 = destRect64 - sourceToDestOffset;
|
||||
IntRect destRect, srcRect;
|
||||
if (!destRect64.ToIntRect(&destRect) || !srcRect64.ToIntRect(&srcRect)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (srcRect.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -3940,6 +3940,8 @@ js::Unbox(JSContext* cx, HandleObject obj, MutableHandleValue vp)
|
||||
vp.setString(obj->as<StringObject>().unbox());
|
||||
else if (obj->is<DateObject>())
|
||||
vp.set(obj->as<DateObject>().UTCTime());
|
||||
else if (obj->is<BigIntObject>())
|
||||
vp.setBigInt(obj->as<BigIntObject>().unbox());
|
||||
else
|
||||
vp.setUndefined();
|
||||
|
||||
|
||||
+3
-7
@@ -158,6 +158,8 @@ class JSObject : public js::gc::Cell
|
||||
* object will have its group constructed lazily as needed by analysis.
|
||||
*/
|
||||
bool isSingleton() const {
|
||||
// In some cases, group_ might be null.
|
||||
if (!group_) return false;
|
||||
return group_->singleton();
|
||||
}
|
||||
|
||||
@@ -895,10 +897,6 @@ GetElementNoGC(JSContext* cx, JSObject* obj, JSObject* receiver, uint32_t index,
|
||||
* try. Long story short, if you just want bog-standard assignment, pass
|
||||
* `ObjectValue(*obj)` as receiver. Or better, use one of the signatures that
|
||||
* doesn't have a receiver parameter.
|
||||
*
|
||||
* Callers pass obj != receiver e.g. when a proxy is involved, obj is the
|
||||
* proxy's target, and the proxy is using SetProperty to finish an assignment
|
||||
* that started out as `receiver[id] = v`, by delegating it to obj.
|
||||
*/
|
||||
inline bool
|
||||
SetProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
|
||||
@@ -1269,9 +1267,7 @@ FromPropertyDescriptorToObject(JSContext* cx, Handle<JS::PropertyDescriptor> des
|
||||
extern bool
|
||||
IsDelegate(JSContext* cx, HandleObject obj, const Value& v, bool* result);
|
||||
|
||||
// obj is a JSObject*, but we root it immediately up front. We do it
|
||||
// that way because we need a Rooted temporary in this method anyway.
|
||||
extern bool
|
||||
bool
|
||||
IsDelegateOfObject(JSContext* cx, HandleObject protoObj, JSObject* obj, bool* result);
|
||||
|
||||
/* Wrap boolean, number or string as Boolean, Number or String object. */
|
||||
|
||||
+3
-1
@@ -3954,7 +3954,9 @@ JSScript::traceChildren(JSTracer* trc)
|
||||
|
||||
if (hasObjects()) {
|
||||
ObjectArray* objarray = objects();
|
||||
TraceRange(trc, objarray->length, objarray->vector, "objects");
|
||||
if (objarray && objarray->length > 0 && objarray->vector) {
|
||||
TraceRange(trc, objarray->length, objarray->vector, "objects");
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT_IF(sourceObject(), MaybeForwarded(sourceObject())->compartment() == compartment());
|
||||
|
||||
@@ -1373,16 +1373,18 @@ intrinsic_MoveTypedArrayElements(JSContext* cx, unsigned argc, Value* vp)
|
||||
MOZ_ASSERT((UINT32_MAX >> ElementShift) >= count);
|
||||
uint32_t byteSize = count << ElementShift;
|
||||
|
||||
#ifdef DEBUG
|
||||
{
|
||||
uint32_t viewByteLength = tarray->byteLength();
|
||||
MOZ_ASSERT(byteSize <= viewByteLength);
|
||||
MOZ_ASSERT(byteDest < viewByteLength);
|
||||
MOZ_ASSERT(byteSrc < viewByteLength);
|
||||
MOZ_ASSERT(byteDest <= viewByteLength - byteSize);
|
||||
MOZ_ASSERT(byteSrc <= viewByteLength - byteSize);
|
||||
if (byteSize > viewByteLength ||
|
||||
byteDest >= viewByteLength ||
|
||||
byteSrc >= viewByteLength ||
|
||||
byteDest > viewByteLength - byteSize ||
|
||||
byteSrc > viewByteLength - byteSize) {
|
||||
JS_ReportErrorNumberASCII(
|
||||
cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_OUT_OF_BOUNDS);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
SharedMem<uint8_t*> data = tarray->viewDataEither().cast<uint8_t*>();
|
||||
jit::AtomicOperations::memmoveSafeWhenRacy(data + byteDest, data + byteSrc, byteSize);
|
||||
|
||||
@@ -2166,20 +2166,20 @@ nsFrameSelection::CommonPageMove(bool aForward,
|
||||
//get the frame from the scrollable view
|
||||
|
||||
nsIFrame* scrolledFrame = aScrollableFrame->GetScrolledFrame();
|
||||
if (!scrolledFrame) [[unlikely]] {
|
||||
if MOZ_UNLIKELY(!scrolledFrame) {
|
||||
return;
|
||||
}
|
||||
|
||||
// find out where the caret is.
|
||||
// we should know mDesiredPos value of nsFrameSelection, but I havent seen that behavior in other windows applications yet.
|
||||
nsISelection* domSel = GetSelection(SelectionType::eNormal);
|
||||
if (!domSel) [[unlikely]] {
|
||||
if MOZ_UNLIKELY(!domSel) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsRect caretPos;
|
||||
nsIFrame* caretFrame = nsCaret::GetGeometry(domSel, &caretPos);
|
||||
if (!caretFrame) [[unlikely]] {
|
||||
if MOZ_UNLIKELY(!caretFrame) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2200,7 +2200,7 @@ nsFrameSelection::CommonPageMove(bool aForward,
|
||||
desiredPoint.y = caretPos.y + caretPos.height/2;
|
||||
nsIFrame::ContentOffsets offsets = scrolledFrame->GetContentOffsetsFromPoint(desiredPoint);
|
||||
|
||||
if (!offsets.content) [[unlikely]] {
|
||||
if MOZ_UNLIKELY(!offsets.content) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2846,7 +2846,12 @@ nsFrameSelection::UnselectCells(nsIContent *aTableContent,
|
||||
if (!mDomSelections[index])
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsTableWrapperFrame* tableFrame = do_QueryFrame(aTableContent->GetPrimaryFrame());
|
||||
// This is needed as an nsTableWrapperFrame as we use this to know we can
|
||||
// static cast tableFrame to nsTableWrapperFrame.
|
||||
nsTableWrapperFrame* tableWrapperFrame = do_QueryFrame(aTableContent->GetPrimaryFrame());
|
||||
|
||||
// Declared as weak frame, as the frame may be freed during a call to a listener.
|
||||
nsWeakFrame tableFrame(tableWrapperFrame);
|
||||
if (!tableFrame)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
@@ -2878,6 +2883,9 @@ nsFrameSelection::UnselectCells(nsIContent *aTableContent,
|
||||
curColIndex < minColIndex || curColIndex > maxColIndex) {
|
||||
|
||||
mDomSelections[index]->RemoveRange(range);
|
||||
if (!tableFrame.IsAlive()) {
|
||||
return NS_OK;
|
||||
}
|
||||
// Since we've removed the range, decrement pointer to next range
|
||||
mSelectedCellIndex--;
|
||||
}
|
||||
@@ -2885,21 +2893,30 @@ nsFrameSelection::UnselectCells(nsIContent *aTableContent,
|
||||
} else {
|
||||
// Remove cell from selection if it belongs to the given cells range or
|
||||
// it is spanned onto the cells range.
|
||||
|
||||
MOZ_ASSERT(tableFrame.IsAlive());
|
||||
// In general, static casting to another table type is not a good idea,
|
||||
// but it is valid here due to the earlier do_QueryFrame() that
|
||||
// established that tableFrame is an nsTableWrapperFrame*.
|
||||
auto tempTableFrame = static_cast<nsTableWrapperFrame*>(tableFrame.GetFrame());
|
||||
nsTableCellFrame* cellFrame =
|
||||
tableFrame->GetCellFrameAt(curRowIndex, curColIndex);
|
||||
tempTableFrame->GetCellFrameAt(curRowIndex, curColIndex);
|
||||
|
||||
uint32_t origRowIndex = cellFrame->RowIndex();
|
||||
uint32_t origColIndex = cellFrame->ColIndex();
|
||||
uint32_t actualRowSpan =
|
||||
tableFrame->GetEffectiveRowSpanAt(origRowIndex, origColIndex);
|
||||
tempTableFrame->GetEffectiveRowSpanAt(origRowIndex, origColIndex);
|
||||
uint32_t actualColSpan =
|
||||
tableFrame->GetEffectiveColSpanAt(curRowIndex, curColIndex);
|
||||
tempTableFrame->GetEffectiveColSpanAt(curRowIndex, curColIndex);
|
||||
if (origRowIndex <= static_cast<uint32_t>(maxRowIndex) && maxRowIndex >= 0 &&
|
||||
origRowIndex + actualRowSpan - 1 >= static_cast<uint32_t>(minRowIndex) &&
|
||||
origColIndex <= static_cast<uint32_t>(maxColIndex) && maxColIndex >= 0 &&
|
||||
origColIndex + actualColSpan - 1 >= static_cast<uint32_t>(minColIndex)) {
|
||||
|
||||
mDomSelections[index]->RemoveRange(range);
|
||||
if (!tableFrame.IsAlive()) {
|
||||
return NS_OK;
|
||||
}
|
||||
// Since we've removed the range, decrement pointer to next range
|
||||
mSelectedCellIndex--;
|
||||
}
|
||||
@@ -2925,7 +2942,12 @@ nsFrameSelection::AddCellsToSelection(nsIContent *aTableContent,
|
||||
if (!mDomSelections[index])
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsTableWrapperFrame* tableFrame = do_QueryFrame(aTableContent->GetPrimaryFrame());
|
||||
// This is needed as an nsTableWrapperFrame as we use this to know we can
|
||||
// static cast tableFrame to nsTableWrapperFrame.
|
||||
nsTableWrapperFrame* tableWrapperFrame = do_QueryFrame(aTableContent->GetPrimaryFrame());
|
||||
|
||||
// Declared as weak frame, as the frame may be freed during a call to a listener.
|
||||
nsWeakFrame tableFrame(tableWrapperFrame);
|
||||
if (!tableFrame) // Check that |table| is a table.
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
@@ -2936,7 +2958,12 @@ nsFrameSelection::AddCellsToSelection(nsIContent *aTableContent,
|
||||
uint32_t col = aStartColumnIndex;
|
||||
while(true)
|
||||
{
|
||||
nsTableCellFrame* cellFrame = tableFrame->GetCellFrameAt(row, col);
|
||||
MOZ_ASSERT(tableFrame.IsAlive());
|
||||
// In general, static casting to another table type is not a good idea,
|
||||
// but it is valid here due to the earlier do_QueryFrame() that
|
||||
// established that tableFrame is an nsTableWrapperFrame*.
|
||||
nsTableCellFrame* cellFrame =
|
||||
static_cast<nsTableWrapperFrame*>(tableFrame.GetFrame())->GetCellFrameAt(row, col);
|
||||
|
||||
// Skip cells that are spanned from previous locations or are already selected
|
||||
if (cellFrame) {
|
||||
@@ -2944,7 +2971,9 @@ nsFrameSelection::AddCellsToSelection(nsIContent *aTableContent,
|
||||
uint32_t origCol = cellFrame->ColIndex();
|
||||
if (origRow == row && origCol == col && !cellFrame->IsSelected()) {
|
||||
result = SelectCellElement(cellFrame->GetContent());
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (NS_FAILED(result) || !tableFrame.IsAlive()) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Done when we reach end column
|
||||
|
||||
@@ -333,12 +333,10 @@ void vp8_build_inter16x16_predictors_mb(MACROBLOCKD *x, unsigned char *dst_y,
|
||||
_16x16mv.as_mv.row &= x->fullpixel_mask;
|
||||
_16x16mv.as_mv.col &= x->fullpixel_mask;
|
||||
|
||||
if (2 * _16x16mv.as_mv.col < (x->mb_to_left_edge - (19 << 3)) ||
|
||||
2 * _16x16mv.as_mv.col > x->mb_to_right_edge + (18 << 3) ||
|
||||
2 * _16x16mv.as_mv.row < (x->mb_to_top_edge - (19 << 3)) ||
|
||||
2 * _16x16mv.as_mv.row > x->mb_to_bottom_edge + (18 << 3)) {
|
||||
return;
|
||||
}
|
||||
/* Rounding to full-pel can move the chroma MV outside the border tap
|
||||
* window even though the luma MV was already clamped, so clamp again to
|
||||
* keep the reference read in bounds and ensure dst_u/dst_v are written. */
|
||||
clamp_uvmv_to_umv_border(&_16x16mv.as_mv, x);
|
||||
|
||||
pre_stride >>= 1;
|
||||
offset = (_16x16mv.as_mv.row >> 3) * pre_stride + (_16x16mv.as_mv.col >> 3);
|
||||
|
||||
@@ -111,9 +111,11 @@ nsJARProtocolHandler::GetDefaultPort(int32_t *result)
|
||||
NS_IMETHODIMP
|
||||
nsJARProtocolHandler::GetProtocolFlags(uint32_t *result)
|
||||
{
|
||||
// URI_LOADABLE_BY_ANYONE, since it's our inner URI that will matter
|
||||
// anyway.
|
||||
*result = URI_NORELATIVE | URI_NOAUTH | URI_LOADABLE_BY_ANYONE;
|
||||
// A jar: URI is only ever as loadable as the inner URI it
|
||||
// wraps, and security checks consult the innermost URI. Claim
|
||||
// the restrictive flag here so that consumers which look at the
|
||||
// jar: handler alone don't treat it as web-loadable.
|
||||
*result = URI_NORELATIVE | URI_NOAUTH | URI_IS_LOCAL_FILE;
|
||||
/* Although jar uris have their own concept of relative urls
|
||||
it is very different from the standard behaviour, so we
|
||||
have to say norelative here! */
|
||||
|
||||
@@ -2573,7 +2573,7 @@ pref("layout.css.legacy-negation-pseudo.enabled", false);
|
||||
pref("layout.css.is-where-pseudo.enabled", true);
|
||||
|
||||
// Is support for the :has() selector enabled?
|
||||
pref("layout.css.has-pseudo.enabled", true);
|
||||
pref("layout.css.has-pseudo.enabled", false);
|
||||
|
||||
// Is support for the ::slotted() selector enabled?
|
||||
pref("layout.css.slotted-pseudo.enabled", true);
|
||||
@@ -4516,6 +4516,9 @@ pref("html5.flushtimer.initialdelay", 120);
|
||||
// Time in milliseconds between the time a network buffer is seen and the
|
||||
// timer firing when the timer has already fired previously in this parse.
|
||||
pref("html5.flushtimer.subsequentdelay", 120);
|
||||
// Determine whether strict (standards-compliant) subtree node checking is
|
||||
// enabled for forms. See UXP issue #3197
|
||||
pref("html5.forms.standards_compliant", true);
|
||||
|
||||
// Push/Pop/Replace State prefs
|
||||
pref("browser.history.maxStateObjectSize", 655360);
|
||||
|
||||
@@ -3,11 +3,17 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsMIMEHeaderParamImpl.h"
|
||||
|
||||
#include <string.h>
|
||||
#include "prmem.h"
|
||||
|
||||
#include "mozilla/Base64.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/TextUtils.h"
|
||||
#include "mozilla/dom/EncodingUtils.h"
|
||||
|
||||
#include "prprf.h"
|
||||
#include "plstr.h"
|
||||
#include "plbase64.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsMemory.h"
|
||||
#include "nsTArray.h"
|
||||
@@ -16,18 +22,20 @@
|
||||
#include "nsIUTF8ConverterService.h"
|
||||
#include "nsUConvCID.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsMIMEHeaderParamImpl.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsNativeCharsetUtils.h"
|
||||
#include "nsError.h"
|
||||
#include "nsIUnicodeDecoder.h"
|
||||
#include "mozilla/dom/EncodingUtils.h"
|
||||
|
||||
using mozilla::dom::EncodingUtils;
|
||||
using mozilla::Maybe;
|
||||
using mozilla::Nothing;
|
||||
using mozilla::Some;
|
||||
|
||||
|
||||
// static functions declared below are moved from mailnews/mime/src/comi18n.cpp
|
||||
|
||||
static char *DecodeQ(const char *, uint32_t);
|
||||
static Maybe<nsCString> DecodeQ(const char *, uint32_t);
|
||||
static bool Is7bitNonAsciiString(const char *, uint32_t);
|
||||
static void CopyRawHeader(const char *, uint32_t, const char *, nsACString &);
|
||||
static nsresult DecodeRFC2047Str(const char *, const char *, bool, nsACString&);
|
||||
@@ -48,8 +56,7 @@ nsMIMEHeaderParamImpl::GetParameter(const nsACString& aHeaderVal,
|
||||
const char *aParamName,
|
||||
const nsACString& aFallbackCharset,
|
||||
bool aTryLocaleCharset,
|
||||
char **aLang, nsAString& aResult)
|
||||
{
|
||||
char **aLang, nsAString& aResult) {
|
||||
return DoGetParameter(aHeaderVal, aParamName, MIME_FIELD_ENCODING,
|
||||
aFallbackCharset, aTryLocaleCharset, aLang, aResult);
|
||||
}
|
||||
@@ -59,8 +66,7 @@ nsMIMEHeaderParamImpl::GetParameterHTTP(const nsACString& aHeaderVal,
|
||||
const char *aParamName,
|
||||
const nsACString& aFallbackCharset,
|
||||
bool aTryLocaleCharset,
|
||||
char **aLang, nsAString& aResult)
|
||||
{
|
||||
char **aLang, nsAString& aResult) {
|
||||
return DoGetParameter(aHeaderVal, aParamName, HTTP_FIELD_ENCODING,
|
||||
aFallbackCharset, aTryLocaleCharset, aLang, aResult);
|
||||
}
|
||||
@@ -94,76 +100,75 @@ nsMIMEHeaderParamImpl::DoGetParameter(const nsACString& aHeaderVal,
|
||||
ParamDecoding aDecoding,
|
||||
const nsACString& aFallbackCharset,
|
||||
bool aTryLocaleCharset,
|
||||
char **aLang, nsAString& aResult)
|
||||
{
|
||||
aResult.Truncate();
|
||||
nsresult rv;
|
||||
char **aLang, nsAString& aResult) {
|
||||
aResult.Truncate();
|
||||
nsresult rv;
|
||||
|
||||
// get parameter (decode RFC 2231/5987 when applicable, as specified by
|
||||
// aDecoding (5987 being a subset of 2231) and return charset.)
|
||||
nsXPIDLCString med;
|
||||
nsXPIDLCString charset;
|
||||
rv = DoParameterInternal(aHeaderVal, aParamName, aDecoding,
|
||||
getter_Copies(charset), aLang, getter_Copies(med));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
// get parameter (decode RFC 2231/5987 when applicable, as specified by
|
||||
// aDecoding (5987 being a subset of 2231) and return charset.)
|
||||
nsXPIDLCString med;
|
||||
nsXPIDLCString charset;
|
||||
rv = DoParameterInternal(aHeaderVal, aParamName, aDecoding,
|
||||
getter_Copies(charset), aLang, getter_Copies(med));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// convert to UTF-8 after charset conversion and RFC 2047 decoding
|
||||
// if necessary.
|
||||
// convert to UTF-8 after charset conversion and RFC 2047 decoding
|
||||
// if necessary.
|
||||
|
||||
nsAutoCString str1;
|
||||
rv = internalDecodeParameter(med, charset.get(), nullptr, false,
|
||||
// was aDecoding == MIME_FIELD_ENCODING
|
||||
// see bug 875615
|
||||
true,
|
||||
str1);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsAutoCString str1;
|
||||
rv = internalDecodeParameter(med, charset.get(), nullptr, false,
|
||||
// was aDecoding == MIME_FIELD_ENCODING
|
||||
// see bug 875615
|
||||
true,
|
||||
str1);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!aFallbackCharset.IsEmpty())
|
||||
{
|
||||
nsAutoCString charset;
|
||||
EncodingUtils::FindEncodingForLabel(aFallbackCharset, charset);
|
||||
nsAutoCString str2;
|
||||
nsCOMPtr<nsIUTF8ConverterService>
|
||||
cvtUTF8(do_GetService(NS_UTF8CONVERTERSERVICE_CONTRACTID));
|
||||
if (cvtUTF8 &&
|
||||
NS_SUCCEEDED(cvtUTF8->ConvertStringToUTF8(str1,
|
||||
PromiseFlatCString(aFallbackCharset).get(), false,
|
||||
!charset.EqualsLiteral("UTF-8"),
|
||||
1, str2))) {
|
||||
CopyUTF8toUTF16(str2, aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsUTF8(str1)) {
|
||||
CopyUTF8toUTF16(str1, aResult);
|
||||
if (!aFallbackCharset.IsEmpty()) {
|
||||
nsAutoCString charset;
|
||||
EncodingUtils::FindEncodingForLabel(aFallbackCharset, charset);
|
||||
nsAutoCString str2;
|
||||
nsCOMPtr<nsIUTF8ConverterService> cvtUTF8(do_GetService(NS_UTF8CONVERTERSERVICE_CONTRACTID));
|
||||
if (cvtUTF8 &&
|
||||
NS_SUCCEEDED(cvtUTF8->ConvertStringToUTF8(str1,
|
||||
PromiseFlatCString(aFallbackCharset).get(),
|
||||
false,
|
||||
!charset.EqualsLiteral("UTF-8"),
|
||||
1,
|
||||
str2))) {
|
||||
CopyUTF8toUTF16(str2, aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (aTryLocaleCharset && !NS_IsNativeUTF8())
|
||||
return NS_CopyNativeToUnicode(str1, aResult);
|
||||
|
||||
CopyASCIItoUTF16(str1, aResult);
|
||||
if (IsUTF8(str1)) {
|
||||
CopyUTF8toUTF16(str1, aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aTryLocaleCharset && !NS_IsNativeUTF8()) {
|
||||
return NS_CopyNativeToUnicode(str1, aResult);
|
||||
}
|
||||
|
||||
CopyASCIItoUTF16(str1, aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// remove backslash-encoded sequences from quoted-strings
|
||||
// modifies string in place, potentially shortening it
|
||||
void RemoveQuotedStringEscapes(char *src)
|
||||
{
|
||||
char *dst = src;
|
||||
// modifies aValue, potentially shortening it
|
||||
void RemoveQuotedStringEscapes(nsCString& aValue) {
|
||||
nsAutoCString unescaped;
|
||||
unescaped.SetCapacity(aValue.Length());
|
||||
|
||||
for (char *c = src; *c; ++c)
|
||||
{
|
||||
if (c[0] == '\\' && c[1])
|
||||
{
|
||||
for (uint32_t i = 0; i < aValue.Length(); ++i) {
|
||||
if (aValue[i] == '\\' && i + 1 < aValue.Length()) {
|
||||
// skip backslash if not at end
|
||||
++c;
|
||||
++i;
|
||||
}
|
||||
*dst++ = *c;
|
||||
unescaped.Append(aValue[i]);
|
||||
}
|
||||
*dst = 0;
|
||||
aValue = std::move(unescaped);
|
||||
}
|
||||
|
||||
// true is character is a hex digit
|
||||
@@ -176,12 +181,13 @@ bool IsHexDigit(char aChar)
|
||||
(c >= '0' && c <= '9');
|
||||
}
|
||||
|
||||
// validate that a C String containing %-escapes is syntactically valid
|
||||
bool IsValidPercentEscaped(const char *aValue, int32_t len)
|
||||
{
|
||||
for (int32_t i = 0; i < len; i++) {
|
||||
// validate that a string containing %-escapes is syntactically valid
|
||||
bool IsValidPercentEscaped(const nsACString& aValue) {
|
||||
for (uint32_t i = 0; i < aValue.Length(); i++) {
|
||||
if (aValue[i] == '%') {
|
||||
if (!IsHexDigit(aValue[i + 1]) || !IsHexDigit(aValue[i + 2])) {
|
||||
if (i + 2 >= aValue.Length() ||
|
||||
!IsHexDigit(aValue[i + 1]) ||
|
||||
!IsHexDigit(aValue[i + 2])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -189,6 +195,21 @@ bool IsValidPercentEscaped(const char *aValue, int32_t len)
|
||||
return true;
|
||||
}
|
||||
|
||||
// A NUL anywhere in a decoded value would silently truncate it in any later
|
||||
// C-string based processing. Note that this is stricter than
|
||||
// ContainsTrailingCharPastNull, which tolerates a value whose tail past the
|
||||
// NUL is only more NULs.
|
||||
static bool ContainsNull(const nsACString& aValue) {
|
||||
return aValue.Contains('\0');
|
||||
}
|
||||
|
||||
// Percent-decode aValue in place (which happens whether or not this succeeds),
|
||||
// returning false if the decoded value contains a NUL.
|
||||
static bool UnescapeRejectingNull(nsCString& aValue) {
|
||||
NS_UnescapeURL(aValue);
|
||||
return !ContainsNull(aValue);
|
||||
}
|
||||
|
||||
// Support for continuations (RFC 2231, Section 3)
|
||||
|
||||
// only a sane number supported
|
||||
@@ -220,59 +241,41 @@ class Continuation {
|
||||
bool wasQuotedString;
|
||||
};
|
||||
|
||||
// combine segments into a single string, returning the allocated string
|
||||
// (or nullptr) while emptying the list
|
||||
char *combineContinuations(nsTArray<Continuation>& aArray)
|
||||
{
|
||||
// Sanity check
|
||||
if (aArray.Length() == 0)
|
||||
return nullptr;
|
||||
// combine segments into a single string, up to the first segment that is
|
||||
// missing. Returns Nothing() if that leaves nothing at all, or, with
|
||||
// aContainedNull set, if percent-decoding a segment produced a NUL.
|
||||
Maybe<nsCString> combineContinuations(const nsTArray<Continuation>& aArray,
|
||||
bool& aContainedNull) {
|
||||
nsCString result;
|
||||
|
||||
// Get an upper bound for the length
|
||||
uint32_t length = 0;
|
||||
for (uint32_t i = 0; i < aArray.Length(); i++) {
|
||||
length += aArray[i].length;
|
||||
}
|
||||
for (const Continuation& cont : aArray) {
|
||||
if (!cont.value) break;
|
||||
|
||||
// Allocate
|
||||
char *result = (char *) moz_xmalloc(length + 1);
|
||||
|
||||
// Concatenate
|
||||
if (result) {
|
||||
*result = '\0';
|
||||
|
||||
for (uint32_t i = 0; i < aArray.Length(); i++) {
|
||||
Continuation cont = aArray[i];
|
||||
if (! cont.value) break;
|
||||
|
||||
char *c = result + strlen(result);
|
||||
strncat(result, cont.value, cont.length);
|
||||
if (cont.needsPercentDecoding) {
|
||||
nsUnescape(c);
|
||||
}
|
||||
if (cont.wasQuotedString) {
|
||||
RemoveQuotedStringEscapes(c);
|
||||
nsAutoCString segment(cont.value, cont.length);
|
||||
if (cont.needsPercentDecoding) {
|
||||
if (!UnescapeRejectingNull(segment)) {
|
||||
aContainedNull = true;
|
||||
return Nothing();
|
||||
}
|
||||
}
|
||||
|
||||
// return null if empty value
|
||||
if (*result == '\0') {
|
||||
free(result);
|
||||
result = nullptr;
|
||||
if (cont.wasQuotedString) {
|
||||
RemoveQuotedStringEscapes(segment);
|
||||
}
|
||||
} else {
|
||||
// Handle OOM
|
||||
NS_WARNING("Out of memory\n");
|
||||
result.Append(segment);
|
||||
}
|
||||
|
||||
return result;
|
||||
// no result if empty value
|
||||
if (result.IsEmpty()) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
return Some(std::move(result));
|
||||
}
|
||||
|
||||
// add a continuation, return false on error if segment already has been seen
|
||||
bool addContinuation(nsTArray<Continuation>& aArray, uint32_t aIndex,
|
||||
const char *aValue, uint32_t aLength,
|
||||
bool aNeedsPercentDecoding, bool aWasQuotedString)
|
||||
{
|
||||
bool aNeedsPercentDecoding, bool aWasQuotedString) {
|
||||
if (aIndex < aArray.Length() && aArray[aIndex].value) {
|
||||
NS_WARNING("duplicate RC2231 continuation segment #\n");
|
||||
return false;
|
||||
@@ -299,8 +302,7 @@ bool addContinuation(nsTArray<Continuation>& aArray, uint32_t aIndex,
|
||||
}
|
||||
|
||||
// parse a segment number; return -1 on error
|
||||
int32_t parseSegmentNumber(const char *aValue, int32_t aLen)
|
||||
{
|
||||
int32_t parseSegmentNumber(const char *aValue, int32_t aLen) {
|
||||
if (aLen < 1) {
|
||||
NS_WARNING("segment number missing\n");
|
||||
return -1;
|
||||
@@ -332,20 +334,16 @@ int32_t parseSegmentNumber(const char *aValue, int32_t aLen)
|
||||
|
||||
// validate a given octet sequence for compliance with the specified
|
||||
// encoding
|
||||
bool IsValidOctetSequenceForCharset(nsACString& aCharset, const char *aOctets)
|
||||
{
|
||||
nsCOMPtr<nsIUTF8ConverterService> cvtUTF8(do_GetService
|
||||
(NS_UTF8CONVERTERSERVICE_CONTRACTID));
|
||||
bool IsValidOctetSequenceForCharset(nsACString& aCharset, const nsACString& aOctets) {
|
||||
nsCOMPtr<nsIUTF8ConverterService> cvtUTF8(do_GetService(NS_UTF8CONVERTERSERVICE_CONTRACTID));
|
||||
if (!cvtUTF8) {
|
||||
NS_WARNING("Can't get UTF8ConverterService\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
nsAutoCString tmpRaw;
|
||||
tmpRaw.Assign(aOctets);
|
||||
nsAutoCString tmpDecoded;
|
||||
|
||||
nsresult rv = cvtUTF8->ConvertStringToUTF8(tmpRaw,
|
||||
nsresult rv = cvtUTF8->ConvertStringToUTF8(aOctets,
|
||||
PromiseFlatCString(aCharset).get(),
|
||||
false, false, 1, tmpDecoded);
|
||||
|
||||
@@ -371,8 +369,7 @@ nsMIMEHeaderParamImpl::GetParameterInternal(const nsACString& aHeaderValue,
|
||||
const char* aParamName,
|
||||
char** aCharset,
|
||||
char** aLang,
|
||||
char** aResult)
|
||||
{
|
||||
char** aResult) {
|
||||
return DoParameterInternal(aHeaderValue, aParamName, MIME_FIELD_ENCODING,
|
||||
aCharset, aLang, aResult);
|
||||
}
|
||||
@@ -384,9 +381,7 @@ nsMIMEHeaderParamImpl::DoParameterInternal(const nsACString& aHeaderValue,
|
||||
ParamDecoding aDecoding,
|
||||
char** aCharset,
|
||||
char** aLang,
|
||||
char** aResult)
|
||||
{
|
||||
|
||||
char** aResult) {
|
||||
if (aHeaderValue.IsEmpty() || !aResult) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
@@ -405,8 +400,12 @@ nsMIMEHeaderParamImpl::DoParameterInternal(const nsACString& aHeaderValue,
|
||||
|
||||
*aResult = nullptr;
|
||||
|
||||
if (aCharset) *aCharset = nullptr;
|
||||
if (aLang) *aLang = nullptr;
|
||||
if (aCharset) {
|
||||
*aCharset = nullptr;
|
||||
}
|
||||
if (aLang) {
|
||||
*aLang = nullptr;
|
||||
}
|
||||
|
||||
nsAutoCString charset;
|
||||
|
||||
@@ -415,8 +414,8 @@ nsMIMEHeaderParamImpl::DoParameterInternal(const nsACString& aHeaderValue,
|
||||
bool acceptContinuations = true;
|
||||
|
||||
// skip leading white space.
|
||||
for (; *str && nsCRT::IsAsciiSpace(*str); ++str)
|
||||
;
|
||||
for (; *str && nsCRT::IsAsciiSpace(*str); ++str) { }
|
||||
|
||||
const char *start = str;
|
||||
|
||||
// aParamName is empty. return the first (possibly) _unnamed_ 'parameter'
|
||||
@@ -429,9 +428,7 @@ nsMIMEHeaderParamImpl::DoParameterInternal(const nsACString& aHeaderValue,
|
||||
if (str == start)
|
||||
return NS_ERROR_FIRST_HEADER_FIELD_COMPONENT_EMPTY;
|
||||
|
||||
*aResult = (char *) nsMemory::Clone(start, (str - start) + 1);
|
||||
NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
|
||||
(*aResult)[str - start] = '\0'; // null-terminate
|
||||
*aResult = ToNewCString(Substring(start, str - start));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -465,9 +462,14 @@ nsMIMEHeaderParamImpl::DoParameterInternal(const nsACString& aHeaderValue,
|
||||
// collect results for the different algorithms (plain filename,
|
||||
// RFC5987/2231-encoded filename, + continuations) separately and decide
|
||||
// which to use at the end
|
||||
char *caseAResult = nullptr;
|
||||
char *caseBResult = nullptr;
|
||||
char *caseCDResult = nullptr;
|
||||
Maybe<nsCString> caseAResult;
|
||||
Maybe<nsCString> caseBResult;
|
||||
Maybe<nsCString> caseCDResult;
|
||||
|
||||
// set when percent-decoding produced a NUL, which makes us reject the
|
||||
// parameter outright rather than fall back to a value the sender did not
|
||||
// intend to be used
|
||||
bool containedNull = false;
|
||||
|
||||
// collect continuation segments
|
||||
nsTArray<Continuation> segments;
|
||||
@@ -548,15 +550,14 @@ nsMIMEHeaderParamImpl::DoParameterInternal(const nsACString& aHeaderValue,
|
||||
|
||||
// if the parameter spans across multiple lines we have to strip out the
|
||||
// line continuation -- jht 4/29/98
|
||||
nsAutoCString tempStr(valueStart, valueEnd - valueStart);
|
||||
nsCString tempStr(valueStart, valueEnd - valueStart);
|
||||
tempStr.StripChars("\r\n");
|
||||
char *res = ToNewCString(tempStr);
|
||||
NS_ENSURE_TRUE(res, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
if (isQuotedString)
|
||||
RemoveQuotedStringEscapes(res);
|
||||
if (isQuotedString) {
|
||||
RemoveQuotedStringEscapes(tempStr);
|
||||
}
|
||||
|
||||
caseAResult = res;
|
||||
caseAResult.emplace(std::move(tempStr));
|
||||
// keep going, we may find a RFC 2231/5987 encoded alternative
|
||||
}
|
||||
// case B, C, and D
|
||||
@@ -645,19 +646,16 @@ nsMIMEHeaderParamImpl::DoParameterInternal(const nsACString& aHeaderValue,
|
||||
// non-empty value part
|
||||
if (rawValLength > 0) {
|
||||
if (!caseBResult && caseB) {
|
||||
if (!IsValidPercentEscaped(rawValStart, rawValLength)) {
|
||||
nsCString rawVal(rawValStart, rawValLength);
|
||||
if (!IsValidPercentEscaped(rawVal)) {
|
||||
goto increment_str;
|
||||
}
|
||||
|
||||
// allocate buffer for the raw value
|
||||
char *tmpResult = (char *) nsMemory::Clone(rawValStart, rawValLength + 1);
|
||||
if (!tmpResult) {
|
||||
goto increment_str;
|
||||
if (!UnescapeRejectingNull(rawVal)) {
|
||||
containedNull = true;
|
||||
break;
|
||||
}
|
||||
*(tmpResult + rawValLength) = 0;
|
||||
|
||||
nsUnescape(tmpResult);
|
||||
caseBResult = tmpResult;
|
||||
caseBResult.emplace(std::move(rawVal));
|
||||
} else {
|
||||
// caseC
|
||||
bool added = addContinuation(segments, 0, rawValStart,
|
||||
@@ -701,44 +699,45 @@ increment_str:
|
||||
while (nsCRT::IsAsciiSpace(*str)) ++str;
|
||||
}
|
||||
|
||||
caseCDResult = combineContinuations(segments);
|
||||
if (!containedNull) {
|
||||
caseCDResult = combineContinuations(segments, containedNull);
|
||||
}
|
||||
|
||||
if (containedNull) {
|
||||
// Percent-decoding produced a NUL, which would truncate the value.
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (caseBResult && !charsetB.IsEmpty()) {
|
||||
// check that the 2231/5987 result decodes properly given the
|
||||
// specified character set
|
||||
if (!IsValidOctetSequenceForCharset(charsetB, caseBResult))
|
||||
caseBResult = nullptr;
|
||||
if (!IsValidOctetSequenceForCharset(charsetB, *caseBResult)) {
|
||||
caseBResult.reset();
|
||||
}
|
||||
}
|
||||
|
||||
if (caseCDResult && !charsetCD.IsEmpty()) {
|
||||
// check that the 2231/5987 result decodes properly given the
|
||||
// specified character set
|
||||
if (!IsValidOctetSequenceForCharset(charsetCD, caseCDResult))
|
||||
caseCDResult = nullptr;
|
||||
if (!IsValidOctetSequenceForCharset(charsetCD, *caseCDResult)) {
|
||||
caseCDResult.reset();
|
||||
}
|
||||
}
|
||||
|
||||
if (caseBResult) {
|
||||
// prefer simple 5987 format over 2231 with continuations
|
||||
*aResult = caseBResult;
|
||||
caseBResult = nullptr;
|
||||
*aResult = ToNewCString(*caseBResult);
|
||||
charset.Assign(charsetB);
|
||||
}
|
||||
else if (caseCDResult) {
|
||||
// prefer 2231/5987 with or without continuations over plain format
|
||||
*aResult = caseCDResult;
|
||||
caseCDResult = nullptr;
|
||||
*aResult = ToNewCString(*caseCDResult);
|
||||
charset.Assign(charsetCD);
|
||||
}
|
||||
else if (caseAResult) {
|
||||
*aResult = caseAResult;
|
||||
caseAResult = nullptr;
|
||||
*aResult = ToNewCString(*caseAResult);
|
||||
}
|
||||
|
||||
// free unused stuff
|
||||
free(caseAResult);
|
||||
free(caseBResult);
|
||||
free(caseCDResult);
|
||||
|
||||
// if we have a result
|
||||
if (*aResult) {
|
||||
// then return charset and lang as well
|
||||
@@ -825,23 +824,6 @@ bool IsRFC5987AttrChar(char aChar)
|
||||
c == '_' || c == '`' || c == '|' || c == '~');
|
||||
}
|
||||
|
||||
// percent-decode a value
|
||||
// returns false on failure
|
||||
bool PercentDecode(nsACString& aValue)
|
||||
{
|
||||
char *c = (char *) moz_xmalloc(aValue.Length() + 1);
|
||||
if (!c) {
|
||||
return false;
|
||||
}
|
||||
|
||||
strcpy(c, PromiseFlatCString(aValue).get());
|
||||
nsUnescape(c);
|
||||
aValue.Assign(c);
|
||||
free(c);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Decode a parameter value using the encoding defined in RFC 5987
|
||||
//
|
||||
// charset "'" [ language ] "'" value-chars
|
||||
@@ -909,8 +891,8 @@ nsMIMEHeaderParamImpl::DecodeRFC5987Param(const nsACString& aParamVal,
|
||||
}
|
||||
|
||||
// percent-decode
|
||||
if (!PercentDecode(value)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
if (!UnescapeRejectingNull(value)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
// return the encoding
|
||||
@@ -999,52 +981,44 @@ nsMIMEHeaderParamImpl::DecodeParameter(const nsACString& aParamValue,
|
||||
(0x41 <= uint8_t(c) && uint8_t(c) <= 0x46) || \
|
||||
(0x61 <= uint8_t(c) && uint8_t(c) <= 0x66))
|
||||
|
||||
// Decode Q encoding (RFC 2047).
|
||||
// Decode Q encoding (RFC 2047). Returns Nothing() on bad syntax.
|
||||
// static
|
||||
char *DecodeQ(const char *in, uint32_t length)
|
||||
{
|
||||
char *out, *dest = 0;
|
||||
Maybe<nsCString> DecodeQ(const char* in, uint32_t length) {
|
||||
nsCString dest;
|
||||
dest.SetCapacity(length);
|
||||
|
||||
out = dest = (char *)PR_Calloc(length + 1, sizeof(char));
|
||||
if (dest == nullptr)
|
||||
return nullptr;
|
||||
while (length > 0) {
|
||||
unsigned c = 0;
|
||||
switch (*in) {
|
||||
case '=':
|
||||
// check if |in| in the form of '=hh' where h is [0-9a-fA-F].
|
||||
if (length < 3 || !ISHEXCHAR(in[1]) || !ISHEXCHAR(in[2]))
|
||||
goto badsyntax;
|
||||
PR_sscanf(in + 1, "%2X", &c);
|
||||
*out++ = (char) c;
|
||||
in += 3;
|
||||
length -= 3;
|
||||
break;
|
||||
case '=':
|
||||
// check if |in| in the form of '=hh' where h is [0-9a-fA-F].
|
||||
if (length < 3 || !ISHEXCHAR(in[1]) || !ISHEXCHAR(in[2])) {
|
||||
return Nothing();
|
||||
}
|
||||
PR_sscanf(in + 1, "%2X", &c);
|
||||
dest.Append((char)c);
|
||||
in += 3;
|
||||
length -= 3;
|
||||
break;
|
||||
|
||||
case '_':
|
||||
*out++ = ' ';
|
||||
in++;
|
||||
length--;
|
||||
break;
|
||||
case '_':
|
||||
dest.Append(' ');
|
||||
in++;
|
||||
length--;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (*in & 0x80) goto badsyntax;
|
||||
*out++ = *in++;
|
||||
length--;
|
||||
default:
|
||||
if (*in & 0x80) {
|
||||
return Nothing();
|
||||
}
|
||||
dest.Append(*in++);
|
||||
length--;
|
||||
}
|
||||
}
|
||||
*out++ = '\0';
|
||||
|
||||
for (out = dest; *out ; ++out) {
|
||||
if (*out == '\t')
|
||||
*out = ' ';
|
||||
}
|
||||
dest.ReplaceChar('\t', ' ');
|
||||
|
||||
return dest;
|
||||
|
||||
badsyntax:
|
||||
PR_Free(dest);
|
||||
return nullptr;
|
||||
return Some(std::move(dest));
|
||||
}
|
||||
|
||||
// check if input is HZ (a 7bit encoding for simplified Chinese : RFC 1842))
|
||||
@@ -1154,17 +1128,25 @@ void CopyRawHeader(const char *aInput, uint32_t aLen,
|
||||
nsresult DecodeQOrBase64Str(const char *aEncoded, size_t aLen, char aQOrBase64,
|
||||
const char *aCharset, nsACString &aResult)
|
||||
{
|
||||
char *decodedText;
|
||||
nsCString decodedText;
|
||||
NS_ASSERTION(aQOrBase64 == 'Q' || aQOrBase64 == 'B', "Should be 'Q' or 'B'");
|
||||
if(aQOrBase64 == 'Q')
|
||||
decodedText = DecodeQ(aEncoded, aLen);
|
||||
else if (aQOrBase64 == 'B') {
|
||||
decodedText = PL_Base64Decode(aEncoded, aLen, nullptr);
|
||||
if(aQOrBase64 == 'Q') {
|
||||
Maybe<nsCString> decoded = DecodeQ(aEncoded, aLen);
|
||||
if (!decoded) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
decodedText = std::move(*decoded);
|
||||
} else if (aQOrBase64 == 'B') {
|
||||
if (NS_FAILED(
|
||||
mozilla::Base64Decode(Substring(aEncoded, aLen), decodedText))) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
} else {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (!decodedText) {
|
||||
if (ContainsNull(decodedText)) {
|
||||
// a NUL would truncate the decoded value
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
@@ -1174,12 +1156,11 @@ nsresult DecodeQOrBase64Str(const char *aEncoded, size_t aLen, char aQOrBase64,
|
||||
nsAutoCString utf8Text;
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// skip ASCIIness/UTF8ness test if aCharset is 7bit non-ascii charset.
|
||||
rv = cvtUTF8->ConvertStringToUTF8(nsDependentCString(decodedText),
|
||||
rv = cvtUTF8->ConvertStringToUTF8(decodedText,
|
||||
aCharset,
|
||||
IS_7BIT_NON_ASCII_CHARSET(aCharset),
|
||||
true, 1, utf8Text);
|
||||
}
|
||||
PR_Free(decodedText);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -279,6 +279,7 @@ nsHttpNTLMAuth::ChallengeReceived(nsIHttpAuthenticableChannel *channel,
|
||||
if (PL_strcasecmp(challenge, "NTLM") == 0) {
|
||||
nsCOMPtr<nsISupports> module;
|
||||
|
||||
mAllowDefaultCredentials = CanUseDefaultCredentials(channel, isProxyAuth);
|
||||
// Check to see if we should default to our generic NTLM auth module
|
||||
// through UseGenericNTLM. (We use native auth by default if the
|
||||
// system provides it.) If *sessionState is non-null, we failed to
|
||||
@@ -288,7 +289,7 @@ nsHttpNTLMAuth::ChallengeReceived(nsIHttpAuthenticableChannel *channel,
|
||||
// Check for approved default credentials hosts and proxies. If
|
||||
// *continuationState is non-null, the last authentication attempt
|
||||
// failed so skip default credential use.
|
||||
if (!*continuationState && CanUseDefaultCredentials(channel, isProxyAuth)) {
|
||||
if (!*continuationState && mAllowDefaultCredentials) {
|
||||
// Try logging in with the user's default credentials. If
|
||||
// successful, |identityInvalid| is false, which will trigger
|
||||
// a default credentials attempt once we return.
|
||||
@@ -399,6 +400,13 @@ nsHttpNTLMAuth::GenerateCredentials(nsIHttpAuthenticableChannel *authChannel,
|
||||
|
||||
// initial challenge
|
||||
if (PL_strcasecmp(challenge, "NTLM") == 0) {
|
||||
// An empty user or password makes nsAuthSSPI::Init authenticate as the
|
||||
// logged-in user, which only CanUseDefaultCredentials() hosts may do.
|
||||
if (mUseNative && !mAllowDefaultCredentials &&
|
||||
(!*user || !*pass)) {
|
||||
LOG(("Not using default credentials for an untrusted host\n"));
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
// NTLM service name format is 'HTTP@host' for both http and https
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = authChannel->GetURI(getter_AddRefs(uri));
|
||||
|
||||
@@ -22,7 +22,11 @@ private:
|
||||
|
||||
// This flag indicates whether we are using the native NTLM implementation
|
||||
// or the internal one.
|
||||
bool mUseNative;
|
||||
bool mUseNative;
|
||||
|
||||
// Whether the prefs let this host use the logged-in user's identity. Set by
|
||||
// ChallengeReceived, read by GenerateCredentials.
|
||||
bool mAllowDefaultCredentials = false;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "nsIHTMLDocument.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "nsTextNode.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
@@ -690,7 +691,9 @@ nsHtml5TreeOperation::CreateMathMLElement(nsIAtom* aName,
|
||||
void
|
||||
nsHtml5TreeOperation::SetFormElement(nsIContent* aNode, nsIContent* aParent)
|
||||
{
|
||||
if (aNode->SubtreeRoot() != aParent->SubtreeRoot()) {
|
||||
// sFormSubtreeStrict is a pref to temporarily disable this check. See UXP #3197
|
||||
bool sFormSubtreeStrict = mozilla::Preferences::GetBool("html5.forms.standards_compliant", true);
|
||||
if (sFormSubtreeStrict && aNode->SubtreeRoot() != aParent->SubtreeRoot()) {
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIFormControl> formControl(do_QueryInterface(aNode));
|
||||
|
||||
+2772
-3809
File diff suppressed because it is too large.
Load diff
@@ -1776,10 +1776,11 @@ nsComponentManagerImpl::CollectReports(nsIHandleReportCallback* aHandleReport,
|
||||
|
||||
size_t
|
||||
nsComponentManagerImpl::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
|
||||
const
|
||||
{
|
||||
size_t n = aMallocSizeOf(this);
|
||||
|
||||
SafeMutexAutoLock lock(mLock);
|
||||
|
||||
n += mLoaderMap.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
n += mFactories.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
@@ -327,7 +327,7 @@ public:
|
||||
|
||||
nsTArray<PendingServiceInfo> mPendingServices;
|
||||
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
|
||||
|
||||
private:
|
||||
~nsComponentManagerImpl();
|
||||
|
||||
@@ -3009,6 +3009,7 @@ nsLocalFile::IsExecutable(bool* aResult)
|
||||
}
|
||||
|
||||
// Search for any of the set of executable extensions.
|
||||
// Note: always use lower case here since we lowercase the extensions before comparing.
|
||||
static const char* const executableExts[] = {
|
||||
"ad",
|
||||
"ade", // access project extension
|
||||
@@ -3016,6 +3017,7 @@ nsLocalFile::IsExecutable(bool* aResult)
|
||||
"air", // Adobe AIR installer
|
||||
"app", // executable application
|
||||
"application", // from bug 348763
|
||||
"appcontent-ms",
|
||||
"appref-ms", // ClickOnce link
|
||||
"appx",
|
||||
"appxbundle",
|
||||
@@ -3061,11 +3063,12 @@ nsLocalFile::IsExecutable(bool* aResult)
|
||||
"msc",
|
||||
"msh", // Microsoft Shell
|
||||
"mshxml", // Microsoft Shell
|
||||
"msi",
|
||||
"msi", // Standalone microsoft installer package
|
||||
"msix",
|
||||
"msixbundle",
|
||||
"msp",
|
||||
"mst",
|
||||
// "msu", // Windows Update Standalone Installer. Gated by Windows on MS signatures already.
|
||||
"ops", // Office Profile Settings
|
||||
"pcd",
|
||||
"pif",
|
||||
@@ -3077,7 +3080,8 @@ nsLocalFile::IsExecutable(bool* aResult)
|
||||
"scf", // Windows explorer command
|
||||
"scr",
|
||||
"sct",
|
||||
"search-ms", // Windows Saved Search
|
||||
"searchconnector-ms", // Windows Search connector installs an OpenSearch provider
|
||||
"search-ms", // Windows Saved Search
|
||||
"settingcontent-ms",
|
||||
"shb",
|
||||
"shs",
|
||||
|
||||
Reference in new issue
Block a user