267 lines
11 KiB
Diff
267 lines
11 KiB
Diff
changeset: 312063:88bea96c802a
|
|
user: Andrea Marchesini <amarchesini@mozilla.com>
|
|
Date: Tue May 10 10:52:19 2016 +0200
|
|
summary: Bug 1267130 - Improve the URL segment calculation, r=valentin a=ritu
|
|
|
|
diff -r 28dcecced055 -r 88bea96c802a netwerk/base/nsStandardURL.cpp
|
|
--- a/netwerk/base/nsStandardURL.cpp Wed May 18 11:55:29 2016 +1200
|
|
+++ b/netwerk/base/nsStandardURL.cpp Tue May 10 10:52:19 2016 +0200
|
|
@@ -475,19 +475,28 @@
|
|
}
|
|
|
|
uint32_t
|
|
-nsStandardURL::AppendSegmentToBuf(char *buf, uint32_t i, const char *str, URLSegment &seg, const nsCString *escapedStr, bool useEscaped)
|
|
+nsStandardURL::AppendSegmentToBuf(char *buf, uint32_t i, const char *str,
|
|
+ const URLSegment &segInput, URLSegment &segOutput,
|
|
+ const nsCString *escapedStr,
|
|
+ bool useEscaped, int32_t *diff)
|
|
{
|
|
- if (seg.mLen > 0) {
|
|
+ MOZ_ASSERT(segInput.mLen == segOutput.mLen);
|
|
+
|
|
+ if (diff) *diff = 0;
|
|
+
|
|
+ if (segInput.mLen > 0) {
|
|
if (useEscaped) {
|
|
- seg.mLen = escapedStr->Length();
|
|
- memcpy(buf + i, escapedStr->get(), seg.mLen);
|
|
+ MOZ_ASSERT(diff);
|
|
+ segOutput.mLen = escapedStr->Length();
|
|
+ *diff = segOutput.mLen - segInput.mLen;
|
|
+ memcpy(buf + i, escapedStr->get(), segOutput.mLen);
|
|
+ } else {
|
|
+ memcpy(buf + i, str + segInput.mPos, segInput.mLen);
|
|
}
|
|
- else
|
|
- memcpy(buf + i, str + seg.mPos, seg.mLen);
|
|
- seg.mPos = i;
|
|
- i += seg.mLen;
|
|
+ segOutput.mPos = i;
|
|
+ i += segOutput.mLen;
|
|
} else {
|
|
- seg.mPos = i;
|
|
+ segOutput.mPos = i;
|
|
}
|
|
return i;
|
|
}
|
|
@@ -598,6 +607,20 @@
|
|
}
|
|
}
|
|
|
|
+ // We must take a copy of every single segment because they are pointing to
|
|
+ // the |spec| while we are changing their value, in case we must use
|
|
+ // encoded strings.
|
|
+ URLSegment username(mUsername);
|
|
+ URLSegment password(mPassword);
|
|
+ URLSegment host(mHost);
|
|
+ URLSegment path(mPath);
|
|
+ URLSegment filepath(mFilepath);
|
|
+ URLSegment directory(mDirectory);
|
|
+ URLSegment basename(mBasename);
|
|
+ URLSegment extension(mExtension);
|
|
+ URLSegment query(mQuery);
|
|
+ URLSegment ref(mRef);
|
|
+
|
|
//
|
|
// generate the normalized URL string
|
|
//
|
|
@@ -607,9 +630,10 @@
|
|
char *buf;
|
|
mSpec.BeginWriting(buf);
|
|
uint32_t i = 0;
|
|
+ int32_t diff = 0;
|
|
|
|
if (mScheme.mLen > 0) {
|
|
- i = AppendSegmentToBuf(buf, i, spec, mScheme);
|
|
+ i = AppendSegmentToBuf(buf, i, spec, mScheme, mScheme);
|
|
net_ToLowerCase(buf + mScheme.mPos, mScheme.mLen);
|
|
i = AppendToBuf(buf, i, "://", 3);
|
|
}
|
|
@@ -619,15 +643,22 @@
|
|
|
|
// append authority
|
|
if (mUsername.mLen > 0) {
|
|
- i = AppendSegmentToBuf(buf, i, spec, mUsername, &encUsername, useEncUsername);
|
|
- if (mPassword.mLen >= 0) {
|
|
+ i = AppendSegmentToBuf(buf, i, spec, username, mUsername,
|
|
+ &encUsername, useEncUsername, &diff);
|
|
+ ShiftFromPassword(diff);
|
|
+ if (password.mLen >= 0) {
|
|
buf[i++] = ':';
|
|
- i = AppendSegmentToBuf(buf, i, spec, mPassword, &encPassword, useEncPassword);
|
|
+ i = AppendSegmentToBuf(buf, i, spec, password, mPassword,
|
|
+ &encPassword, useEncPassword, &diff);
|
|
+ ShiftFromHost(diff);
|
|
}
|
|
buf[i++] = '@';
|
|
}
|
|
- if (mHost.mLen > 0) {
|
|
- i = AppendSegmentToBuf(buf, i, spec, mHost, &encHost, useEncHost);
|
|
+ if (host.mLen > 0) {
|
|
+ i = AppendSegmentToBuf(buf, i, spec, host, mHost, &encHost, useEncHost,
|
|
+ &diff);
|
|
+ ShiftFromPath(diff);
|
|
+
|
|
net_ToLowerCase(buf + mHost.mPos, mHost.mLen);
|
|
MOZ_ASSERT(mPort >= -1, "Invalid negative mPort");
|
|
if (mPort != -1 && mPort != mDefaultPort) {
|
|
@@ -652,21 +683,23 @@
|
|
}
|
|
else {
|
|
uint32_t leadingSlash = 0;
|
|
- if (spec[mPath.mPos] != '/') {
|
|
+ if (spec[path.mPos] != '/') {
|
|
LOG(("adding leading slash to path\n"));
|
|
leadingSlash = 1;
|
|
buf[i++] = '/';
|
|
// basename must exist, even if empty (bugs 113508, 429347)
|
|
if (mBasename.mLen == -1) {
|
|
- mBasename.mPos = i;
|
|
- mBasename.mLen = 0;
|
|
+ mBasename.mPos = basename.mPos = i;
|
|
+ mBasename.mLen = basename.mLen = 0;
|
|
}
|
|
}
|
|
|
|
// record corrected (file)path starting position
|
|
mPath.mPos = mFilepath.mPos = i - leadingSlash;
|
|
|
|
- i = AppendSegmentToBuf(buf, i, spec, mDirectory, &encDirectory, useEncDirectory);
|
|
+ i = AppendSegmentToBuf(buf, i, spec, directory, mDirectory,
|
|
+ &encDirectory, useEncDirectory, &diff);
|
|
+ ShiftFromBasename(diff);
|
|
|
|
// the directory must end with a '/'
|
|
if (buf[i-1] != '/') {
|
|
@@ -674,7 +707,9 @@
|
|
mDirectory.mLen++;
|
|
}
|
|
|
|
- i = AppendSegmentToBuf(buf, i, spec, mBasename, &encBasename, useEncBasename);
|
|
+ i = AppendSegmentToBuf(buf, i, spec, basename, mBasename,
|
|
+ &encBasename, useEncBasename, &diff);
|
|
+ ShiftFromExtension(diff);
|
|
|
|
// make corrections to directory segment if leadingSlash
|
|
if (leadingSlash) {
|
|
@@ -687,18 +722,24 @@
|
|
|
|
if (mExtension.mLen >= 0) {
|
|
buf[i++] = '.';
|
|
- i = AppendSegmentToBuf(buf, i, spec, mExtension, &encExtension, useEncExtension);
|
|
+ i = AppendSegmentToBuf(buf, i, spec, extension, mExtension,
|
|
+ &encExtension, useEncExtension, &diff);
|
|
+ ShiftFromQuery(diff);
|
|
}
|
|
// calculate corrected filepath length
|
|
mFilepath.mLen = i - mFilepath.mPos;
|
|
|
|
if (mQuery.mLen >= 0) {
|
|
buf[i++] = '?';
|
|
- i = AppendSegmentToBuf(buf, i, spec, mQuery, &encQuery, useEncQuery);
|
|
+ i = AppendSegmentToBuf(buf, i, spec, query, mQuery,
|
|
+ &encQuery, useEncQuery,
|
|
+ &diff);
|
|
+ ShiftFromRef(diff);
|
|
}
|
|
if (mRef.mLen >= 0) {
|
|
buf[i++] = '#';
|
|
- i = AppendSegmentToBuf(buf, i, spec, mRef, &encRef, useEncRef);
|
|
+ i = AppendSegmentToBuf(buf, i, spec, ref, mRef, &encRef, useEncRef,
|
|
+ &diff);
|
|
}
|
|
// calculate corrected path length
|
|
mPath.mLen = i - mPath.mPos;
|
|
@@ -953,6 +994,39 @@
|
|
#undef GOT_PREF
|
|
}
|
|
|
|
+#define SHIFT_FROM(name, what) \
|
|
+void \
|
|
+nsStandardURL::name(int32_t diff) \
|
|
+{ \
|
|
+ if (!diff) return; \
|
|
+ if (what.mLen >= 0) { \
|
|
+ CheckedInt<int32_t> pos = what.mPos; \
|
|
+ pos += diff; \
|
|
+ MOZ_ASSERT(pos.isValid()); \
|
|
+ what.mPos = pos.value(); \
|
|
+ }
|
|
+
|
|
+#define SHIFT_FROM_NEXT(name, what, next) \
|
|
+ SHIFT_FROM(name, what) \
|
|
+ next(diff); \
|
|
+}
|
|
+
|
|
+#define SHIFT_FROM_LAST(name, what) \
|
|
+ SHIFT_FROM(name, what) \
|
|
+}
|
|
+
|
|
+SHIFT_FROM_NEXT(ShiftFromAuthority, mAuthority, ShiftFromUsername)
|
|
+SHIFT_FROM_NEXT(ShiftFromUsername, mUsername, ShiftFromPassword)
|
|
+SHIFT_FROM_NEXT(ShiftFromPassword, mPassword, ShiftFromHost)
|
|
+SHIFT_FROM_NEXT(ShiftFromHost, mHost, ShiftFromPath)
|
|
+SHIFT_FROM_NEXT(ShiftFromPath, mPath, ShiftFromFilepath)
|
|
+SHIFT_FROM_NEXT(ShiftFromFilepath, mFilepath, ShiftFromDirectory)
|
|
+SHIFT_FROM_NEXT(ShiftFromDirectory, mDirectory, ShiftFromBasename)
|
|
+SHIFT_FROM_NEXT(ShiftFromBasename, mBasename, ShiftFromExtension)
|
|
+SHIFT_FROM_NEXT(ShiftFromExtension, mExtension, ShiftFromQuery)
|
|
+SHIFT_FROM_NEXT(ShiftFromQuery, mQuery, ShiftFromRef)
|
|
+SHIFT_FROM_LAST(ShiftFromRef, mRef)
|
|
+
|
|
//----------------------------------------------------------------------------
|
|
// nsStandardURL::nsISupports
|
|
//----------------------------------------------------------------------------
|
|
diff -r 28dcecced055 -r 88bea96c802a netwerk/base/nsStandardURL.h
|
|
--- a/netwerk/base/nsStandardURL.h Wed May 18 11:55:29 2016 +1200
|
|
+++ b/netwerk/base/nsStandardURL.h Tue May 10 10:52:19 2016 +0200
|
|
@@ -77,6 +77,7 @@
|
|
|
|
URLSegment() : mPos(0), mLen(-1) {}
|
|
URLSegment(uint32_t pos, int32_t len) : mPos(pos), mLen(len) {}
|
|
+ URLSegment(const URLSegment& aCopy) : mPos(aCopy.mPos), mLen(aCopy.mLen) {}
|
|
void Reset() { mPos = 0; mLen = -1; }
|
|
// Merge another segment following this one to it if they're contiguous
|
|
// Assumes we have something like "foo;bar" where this object is 'foo' and right
|
|
@@ -177,7 +178,10 @@
|
|
bool NormalizeIDN(const nsCSubstring &host, nsCString &result);
|
|
void CoalescePath(netCoalesceFlags coalesceFlag, char *path);
|
|
|
|
- uint32_t AppendSegmentToBuf(char *, uint32_t, const char *, URLSegment &, const nsCString *esc=nullptr, bool useEsc = false);
|
|
+ uint32_t AppendSegmentToBuf(char *, uint32_t, const char *,
|
|
+ const URLSegment &input, URLSegment &output,
|
|
+ const nsCString *esc=nullptr,
|
|
+ bool useEsc = false, int32_t* diff = nullptr);
|
|
uint32_t AppendToBuf(char *, uint32_t, const char *, uint32_t);
|
|
|
|
nsresult BuildNormalizedSpec(const char *spec);
|
|
@@ -216,17 +220,17 @@
|
|
const nsDependentCSubstring Ref() { return Segment(mRef); }
|
|
|
|
// shift the URLSegments to the right by diff
|
|
- void ShiftFromAuthority(int32_t diff) { mAuthority.mPos += diff; ShiftFromUsername(diff); }
|
|
- void ShiftFromUsername(int32_t diff) { mUsername.mPos += diff; ShiftFromPassword(diff); }
|
|
- void ShiftFromPassword(int32_t diff) { mPassword.mPos += diff; ShiftFromHost(diff); }
|
|
- void ShiftFromHost(int32_t diff) { mHost.mPos += diff; ShiftFromPath(diff); }
|
|
- void ShiftFromPath(int32_t diff) { mPath.mPos += diff; ShiftFromFilepath(diff); }
|
|
- void ShiftFromFilepath(int32_t diff) { mFilepath.mPos += diff; ShiftFromDirectory(diff); }
|
|
- void ShiftFromDirectory(int32_t diff) { mDirectory.mPos += diff; ShiftFromBasename(diff); }
|
|
- void ShiftFromBasename(int32_t diff) { mBasename.mPos += diff; ShiftFromExtension(diff); }
|
|
- void ShiftFromExtension(int32_t diff) { mExtension.mPos += diff; ShiftFromQuery(diff); }
|
|
- void ShiftFromQuery(int32_t diff) { mQuery.mPos += diff; ShiftFromRef(diff); }
|
|
- void ShiftFromRef(int32_t diff) { mRef.mPos += diff; }
|
|
+ void ShiftFromAuthority(int32_t diff);
|
|
+ void ShiftFromUsername(int32_t diff);
|
|
+ void ShiftFromPassword(int32_t diff);
|
|
+ void ShiftFromHost(int32_t diff);
|
|
+ void ShiftFromPath(int32_t diff);
|
|
+ void ShiftFromFilepath(int32_t diff);
|
|
+ void ShiftFromDirectory(int32_t diff);
|
|
+ void ShiftFromBasename(int32_t diff);
|
|
+ void ShiftFromExtension(int32_t diff);
|
|
+ void ShiftFromQuery(int32_t diff);
|
|
+ void ShiftFromRef(int32_t diff);
|
|
|
|
// fastload helper functions
|
|
nsresult ReadSegment(nsIBinaryInputStream *, URLSegment &);
|