diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /netwerk/base/nsMediaFragmentURIParser.cpp | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'netwerk/base/nsMediaFragmentURIParser.cpp')
-rw-r--r-- | netwerk/base/nsMediaFragmentURIParser.cpp | 390 |
1 files changed, 390 insertions, 0 deletions
diff --git a/netwerk/base/nsMediaFragmentURIParser.cpp b/netwerk/base/nsMediaFragmentURIParser.cpp new file mode 100644 index 000000000..af73fe52c --- /dev/null +++ b/netwerk/base/nsMediaFragmentURIParser.cpp @@ -0,0 +1,390 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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 "nsTArray.h" +#include "nsCharSeparatedTokenizer.h" +#include "nsEscape.h" +#include "nsIURI.h" +#include <utility> + +#include "nsMediaFragmentURIParser.h" + +using std::pair; +using std::make_pair; + +namespace mozilla { namespace net { + +nsMediaFragmentURIParser::nsMediaFragmentURIParser(nsIURI* aURI) + : mClipUnit(eClipUnit_Pixel) +{ + nsAutoCString ref; + aURI->GetRef(ref); + Parse(ref); +} + +nsMediaFragmentURIParser::nsMediaFragmentURIParser(nsCString& aRef) + : mClipUnit(eClipUnit_Pixel) +{ + Parse(aRef); +} + +bool nsMediaFragmentURIParser::ParseNPT(nsDependentSubstring aString) +{ + nsDependentSubstring original(aString); + if (aString.Length() > 4 && + aString[0] == 'n' && aString[1] == 'p' && + aString[2] == 't' && aString[3] == ':') { + aString.Rebind(aString, 4); + } + + if (aString.Length() == 0) { + return false; + } + + double start = -1.0; + double end = -1.0; + + ParseNPTTime(aString, start); + + if (aString.Length() == 0) { + mStart.emplace(start); + return true; + } + + if (aString[0] != ',') { + aString.Rebind(original, 0); + return false; + } + + aString.Rebind(aString, 1); + + if (aString.Length() == 0) { + aString.Rebind(original, 0); + return false; + } + + ParseNPTTime(aString, end); + + if (end <= start || aString.Length() != 0) { + aString.Rebind(original, 0); + return false; + } + + mStart.emplace(start); + mEnd.emplace(end); + return true; +} + +bool nsMediaFragmentURIParser::ParseNPTTime(nsDependentSubstring& aString, double& aTime) +{ + if (aString.Length() == 0) { + return false; + } + + return + ParseNPTHHMMSS(aString, aTime) || + ParseNPTMMSS(aString, aTime) || + ParseNPTSec(aString, aTime); +} + +// Return true if the given character is a numeric character +static bool IsDigit(nsDependentSubstring::char_type aChar) +{ + return (aChar >= '0' && aChar <= '9'); +} + +// Return the index of the first character in the string that is not +// a numerical digit, starting from 'aStart'. +static uint32_t FirstNonDigit(nsDependentSubstring& aString, uint32_t aStart) +{ + while (aStart < aString.Length() && IsDigit(aString[aStart])) { + ++aStart; + } + return aStart; +} + +bool nsMediaFragmentURIParser::ParseNPTSec(nsDependentSubstring& aString, double& aSec) +{ + nsDependentSubstring original(aString); + if (aString.Length() == 0) { + return false; + } + + uint32_t index = FirstNonDigit(aString, 0); + if (index == 0) { + return false; + } + + nsDependentSubstring n(aString, 0, index); + nsresult ec; + int32_t s = PromiseFlatString(n).ToInteger(&ec); + if (NS_FAILED(ec)) { + return false; + } + + aString.Rebind(aString, index); + double fraction = 0.0; + if (!ParseNPTFraction(aString, fraction)) { + aString.Rebind(original, 0); + return false; + } + + aSec = s + fraction; + return true; +} + +bool nsMediaFragmentURIParser::ParseNPTMMSS(nsDependentSubstring& aString, double& aTime) +{ + nsDependentSubstring original(aString); + uint32_t mm = 0; + uint32_t ss = 0; + double fraction = 0.0; + if (!ParseNPTMM(aString, mm)) { + aString.Rebind(original, 0); + return false; + } + + if (aString.Length() < 2 || aString[0] != ':') { + aString.Rebind(original, 0); + return false; + } + + aString.Rebind(aString, 1); + if (!ParseNPTSS(aString, ss)) { + aString.Rebind(original, 0); + return false; + } + + if (!ParseNPTFraction(aString, fraction)) { + aString.Rebind(original, 0); + return false; + } + aTime = mm * 60 + ss + fraction; + return true; +} + +bool nsMediaFragmentURIParser::ParseNPTFraction(nsDependentSubstring& aString, double& aFraction) +{ + double fraction = 0.0; + + if (aString.Length() > 0 && aString[0] == '.') { + uint32_t index = FirstNonDigit(aString, 1); + + if (index > 1) { + nsDependentSubstring number(aString, 0, index); + nsresult ec; + fraction = PromiseFlatString(number).ToDouble(&ec); + if (NS_FAILED(ec)) { + return false; + } + } + aString.Rebind(aString, index); + } + + aFraction = fraction; + return true; +} + +bool nsMediaFragmentURIParser::ParseNPTHHMMSS(nsDependentSubstring& aString, double& aTime) +{ + nsDependentSubstring original(aString); + uint32_t hh = 0; + double seconds = 0.0; + if (!ParseNPTHH(aString, hh)) { + return false; + } + + if (aString.Length() < 2 || aString[0] != ':') { + aString.Rebind(original, 0); + return false; + } + + aString.Rebind(aString, 1); + if (!ParseNPTMMSS(aString, seconds)) { + aString.Rebind(original, 0); + return false; + } + + aTime = hh * 3600 + seconds; + return true; +} + +bool nsMediaFragmentURIParser::ParseNPTHH(nsDependentSubstring& aString, uint32_t& aHour) +{ + if (aString.Length() == 0) { + return false; + } + + uint32_t index = FirstNonDigit(aString, 0); + if (index == 0) { + return false; + } + + nsDependentSubstring n(aString, 0, index); + nsresult ec; + int32_t u = PromiseFlatString(n).ToInteger(&ec); + if (NS_FAILED(ec)) { + return false; + } + + aString.Rebind(aString, index); + aHour = u; + return true; +} + +bool nsMediaFragmentURIParser::ParseNPTMM(nsDependentSubstring& aString, uint32_t& aMinute) +{ + return ParseNPTSS(aString, aMinute); +} + +bool nsMediaFragmentURIParser::ParseNPTSS(nsDependentSubstring& aString, uint32_t& aSecond) +{ + if (aString.Length() < 2) { + return false; + } + + if (IsDigit(aString[0]) && IsDigit(aString[1])) { + nsDependentSubstring n(aString, 0, 2); + nsresult ec; + int32_t u = PromiseFlatString(n).ToInteger(&ec); + if (NS_FAILED(ec)) { + return false; + } + + aString.Rebind(aString, 2); + if (u >= 60) + return false; + + aSecond = u; + return true; + } + + return false; +} + +static bool ParseInteger(nsDependentSubstring& aString, + int32_t& aResult) +{ + uint32_t index = FirstNonDigit(aString, 0); + if (index == 0) { + return false; + } + + nsDependentSubstring n(aString, 0, index); + nsresult ec; + int32_t s = PromiseFlatString(n).ToInteger(&ec); + if (NS_FAILED(ec)) { + return false; + } + + aString.Rebind(aString, index); + aResult = s; + return true; +} + +static bool ParseCommaSeparator(nsDependentSubstring& aString) +{ + if (aString.Length() > 1 && aString[0] == ',') { + aString.Rebind(aString, 1); + return true; + } + + return false; +} + +bool nsMediaFragmentURIParser::ParseXYWH(nsDependentSubstring aString) +{ + int32_t x, y, w, h; + ClipUnit clipUnit; + + // Determine units. + if (StringBeginsWith(aString, NS_LITERAL_STRING("pixel:"))) { + clipUnit = eClipUnit_Pixel; + aString.Rebind(aString, 6); + } else if (StringBeginsWith(aString, NS_LITERAL_STRING("percent:"))) { + clipUnit = eClipUnit_Percent; + aString.Rebind(aString, 8); + } else { + clipUnit = eClipUnit_Pixel; + } + + // Read and validate coordinates. + if (ParseInteger(aString, x) && x >= 0 && + ParseCommaSeparator(aString) && + ParseInteger(aString, y) && y >= 0 && + ParseCommaSeparator(aString) && + ParseInteger(aString, w) && w > 0 && + ParseCommaSeparator(aString) && + ParseInteger(aString, h) && h > 0 && + aString.Length() == 0) { + + // Reject invalid percentage coordinates. + if (clipUnit == eClipUnit_Percent && + (x + w > 100 || y + h > 100)) { + return false; + } + + mClip.emplace(x, y, w, h); + mClipUnit = clipUnit; + return true; + } + + return false; +} + +bool nsMediaFragmentURIParser::ParseMozSampleSize(nsDependentSubstring aString) +{ + int32_t sampleSize; + + // Read and validate coordinates. + if (ParseInteger(aString, sampleSize) && sampleSize > 0) { + mSampleSize.emplace(sampleSize); + return true; + } + + return false; +} + +void nsMediaFragmentURIParser::Parse(nsACString& aRef) +{ + // Create an array of possibly-invalid media fragments. + nsTArray< std::pair<nsCString, nsCString> > fragments; + nsCCharSeparatedTokenizer tokenizer(aRef, '&'); + + while (tokenizer.hasMoreTokens()) { + const nsCSubstring& nv = tokenizer.nextToken(); + int32_t index = nv.FindChar('='); + if (index >= 0) { + nsAutoCString name; + nsAutoCString value; + NS_UnescapeURL(StringHead(nv, index), esc_Ref | esc_AlwaysCopy, name); + NS_UnescapeURL(Substring(nv, index + 1, nv.Length()), + esc_Ref | esc_AlwaysCopy, value); + fragments.AppendElement(make_pair(name, value)); + } + } + + // Parse the media fragment values. + bool gotTemporal = false, gotSpatial = false, gotSampleSize = false; + for (int i = fragments.Length() - 1 ; i >= 0 ; --i) { + if (gotTemporal && gotSpatial && gotSampleSize) { + // We've got one of each possible type. No need to look at the rest. + break; + } else if (!gotTemporal && fragments[i].first.EqualsLiteral("t")) { + nsAutoString value = NS_ConvertUTF8toUTF16(fragments[i].second); + gotTemporal = ParseNPT(nsDependentSubstring(value, 0)); + } else if (!gotSpatial && fragments[i].first.EqualsLiteral("xywh")) { + nsAutoString value = NS_ConvertUTF8toUTF16(fragments[i].second); + gotSpatial = ParseXYWH(nsDependentSubstring(value, 0)); + } else if (!gotSampleSize && fragments[i].first.EqualsLiteral("-moz-samplesize")) { + nsAutoString value = NS_ConvertUTF8toUTF16(fragments[i].second); + gotSampleSize = ParseMozSampleSize(nsDependentSubstring(value, 0)); + } + } +} + +} // namespace net +} // namespace mozilla |