Merge pull request #14056 from Snuffleupagus/bug-1731240
Correctly validate URLs in XFA documents (bug 1731240)
This commit is contained in:
commit
6381158855
@ -13,6 +13,13 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
addDefaultProtocolToUrl,
|
||||||
|
collectActions,
|
||||||
|
MissingDataException,
|
||||||
|
toRomanNumerals,
|
||||||
|
tryConvertUrlEncoding,
|
||||||
|
} from "./core_utils.js";
|
||||||
import {
|
import {
|
||||||
clearPrimitiveCaches,
|
clearPrimitiveCaches,
|
||||||
Dict,
|
Dict,
|
||||||
@ -24,11 +31,6 @@ import {
|
|||||||
RefSet,
|
RefSet,
|
||||||
RefSetCache,
|
RefSetCache,
|
||||||
} from "./primitives.js";
|
} from "./primitives.js";
|
||||||
import {
|
|
||||||
collectActions,
|
|
||||||
MissingDataException,
|
|
||||||
toRomanNumerals,
|
|
||||||
} from "./core_utils.js";
|
|
||||||
import {
|
import {
|
||||||
createPromiseCapability,
|
createPromiseCapability,
|
||||||
createValidAbsoluteUrl,
|
createValidAbsoluteUrl,
|
||||||
@ -1283,21 +1285,6 @@ class Catalog {
|
|||||||
* @param {ParseDestDictionaryParameters} params
|
* @param {ParseDestDictionaryParameters} params
|
||||||
*/
|
*/
|
||||||
static parseDestDictionary(params) {
|
static parseDestDictionary(params) {
|
||||||
// Lets URLs beginning with 'www.' default to using the 'http://' protocol.
|
|
||||||
function addDefaultProtocolToUrl(url) {
|
|
||||||
return url.startsWith("www.") ? `http://${url}` : url;
|
|
||||||
}
|
|
||||||
|
|
||||||
// According to ISO 32000-1:2008, section 12.6.4.7, URIs should be encoded
|
|
||||||
// in 7-bit ASCII. Some bad PDFs use UTF-8 encoding; see Bugzilla 1122280.
|
|
||||||
function tryConvertUrlEncoding(url) {
|
|
||||||
try {
|
|
||||||
return stringToUTF8String(url);
|
|
||||||
} catch (e) {
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const destDict = params.destDict;
|
const destDict = params.destDict;
|
||||||
if (!isDict(destDict)) {
|
if (!isDict(destDict)) {
|
||||||
warn("parseDestDictionary: `destDict` must be a dictionary.");
|
warn("parseDestDictionary: `destDict` must be a dictionary.");
|
||||||
|
@ -18,6 +18,7 @@ import {
|
|||||||
BaseException,
|
BaseException,
|
||||||
objectSize,
|
objectSize,
|
||||||
stringToPDFString,
|
stringToPDFString,
|
||||||
|
stringToUTF8String,
|
||||||
warn,
|
warn,
|
||||||
} from "../shared/util.js";
|
} from "../shared/util.js";
|
||||||
import { Dict, isName, isRef, isStream, RefSet } from "./primitives.js";
|
import { Dict, isName, isRef, isStream, RefSet } from "./primitives.js";
|
||||||
@ -451,7 +452,23 @@ function validateCSSFont(cssFontInfo) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Let URLs beginning with 'www.' default to using the 'http://' protocol.
|
||||||
|
function addDefaultProtocolToUrl(url) {
|
||||||
|
return url.startsWith("www.") ? `http://${url}` : url;
|
||||||
|
}
|
||||||
|
|
||||||
|
// According to ISO 32000-1:2008, section 12.6.4.7, URIs should be encoded
|
||||||
|
// in 7-bit ASCII. Some bad PDFs use UTF-8 encoding; see Bugzilla 1122280.
|
||||||
|
function tryConvertUrlEncoding(url) {
|
||||||
|
try {
|
||||||
|
return stringToUTF8String(url);
|
||||||
|
} catch (e) {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
addDefaultProtocolToUrl,
|
||||||
collectActions,
|
collectActions,
|
||||||
encodeToXmlString,
|
encodeToXmlString,
|
||||||
escapePDFName,
|
escapePDFName,
|
||||||
@ -467,6 +484,7 @@ export {
|
|||||||
readUint16,
|
readUint16,
|
||||||
readUint32,
|
readUint32,
|
||||||
toRomanNumerals,
|
toRomanNumerals,
|
||||||
|
tryConvertUrlEncoding,
|
||||||
validateCSSFont,
|
validateCSSFont,
|
||||||
XRefEntryException,
|
XRefEntryException,
|
||||||
XRefParseException,
|
XRefParseException,
|
||||||
|
@ -29,8 +29,13 @@ import {
|
|||||||
XmlObject,
|
XmlObject,
|
||||||
} from "./xfa_object.js";
|
} from "./xfa_object.js";
|
||||||
import { $buildXFAObject, NamespaceIds } from "./namespaces.js";
|
import { $buildXFAObject, NamespaceIds } from "./namespaces.js";
|
||||||
|
import {
|
||||||
|
addDefaultProtocolToUrl,
|
||||||
|
tryConvertUrlEncoding,
|
||||||
|
} from "../core_utils.js";
|
||||||
import { fixTextIndent, measureToString, setFontFamily } from "./html_utils.js";
|
import { fixTextIndent, measureToString, setFontFamily } from "./html_utils.js";
|
||||||
import { getMeasurement, HTMLResult, stripQuotes } from "./utils.js";
|
import { getMeasurement, HTMLResult, stripQuotes } from "./utils.js";
|
||||||
|
import { createValidAbsoluteUrl } from "../../shared/util.js";
|
||||||
|
|
||||||
const XHTML_NS_ID = NamespaceIds.xhtml.id;
|
const XHTML_NS_ID = NamespaceIds.xhtml.id;
|
||||||
|
|
||||||
@ -321,7 +326,16 @@ class XhtmlObject extends XmlObject {
|
|||||||
class A extends XhtmlObject {
|
class A extends XhtmlObject {
|
||||||
constructor(attributes) {
|
constructor(attributes) {
|
||||||
super(attributes, "a");
|
super(attributes, "a");
|
||||||
this.href = attributes.href || "";
|
let href = "";
|
||||||
|
if (typeof attributes.href === "string") {
|
||||||
|
let url = addDefaultProtocolToUrl(attributes.href);
|
||||||
|
url = tryConvertUrlEncoding(url);
|
||||||
|
const absoluteUrl = createValidAbsoluteUrl(url);
|
||||||
|
if (absoluteUrl) {
|
||||||
|
href = absoluteUrl.href;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.href = href;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -522,4 +522,70 @@ describe("XFAFactory", function () {
|
|||||||
expect(field1).not.toEqual(null);
|
expect(field1).not.toEqual(null);
|
||||||
expect(field1.attributes.value).toEqual("123");
|
expect(field1.attributes.value).toEqual("123");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should parse URLs correctly", function () {
|
||||||
|
function getXml(href) {
|
||||||
|
return `
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/">
|
||||||
|
<template xmlns="http://www.xfa.org/schema/xfa-template/3.3">
|
||||||
|
<subform name="root" mergeMode="matchTemplate">
|
||||||
|
<pageSet>
|
||||||
|
<pageArea>
|
||||||
|
<contentArea x="0pt" w="456pt" h="789pt"/>
|
||||||
|
<medium stock="default" short="456pt" long="789pt"/>
|
||||||
|
<draw name="url" y="5.928mm" x="128.388mm" w="71.237mm" h="9.528mm">
|
||||||
|
<value>
|
||||||
|
<exData contentType="text/html">
|
||||||
|
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<a href="${href}">${href}</a>
|
||||||
|
</body>
|
||||||
|
</exData>
|
||||||
|
</value>
|
||||||
|
</draw>
|
||||||
|
</pageArea>
|
||||||
|
</pageSet>
|
||||||
|
</subform>
|
||||||
|
</template>
|
||||||
|
<xfa:datasets xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/">
|
||||||
|
<xfa:data>
|
||||||
|
</xfa:data>
|
||||||
|
</xfa:datasets>
|
||||||
|
</xdp:xdp>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
let factory, pages, a;
|
||||||
|
|
||||||
|
// A valid, and complete, URL.
|
||||||
|
factory = new XFAFactory({ "xdp:xdp": getXml("https://www.example.com/") });
|
||||||
|
expect(factory.numberPages).toEqual(1);
|
||||||
|
pages = factory.getPages();
|
||||||
|
a = searchHtmlNode(pages, "name", "a");
|
||||||
|
expect(a.value).toEqual("https://www.example.com/");
|
||||||
|
expect(a.attributes.href).toEqual("https://www.example.com/");
|
||||||
|
|
||||||
|
// A valid, but incomplete, URL.
|
||||||
|
factory = new XFAFactory({ "xdp:xdp": getXml("www.example.com/") });
|
||||||
|
expect(factory.numberPages).toEqual(1);
|
||||||
|
pages = factory.getPages();
|
||||||
|
a = searchHtmlNode(pages, "name", "a");
|
||||||
|
expect(a.value).toEqual("www.example.com/");
|
||||||
|
expect(a.attributes.href).toEqual("http://www.example.com/");
|
||||||
|
|
||||||
|
// A valid email-address.
|
||||||
|
factory = new XFAFactory({ "xdp:xdp": getXml("mailto:test@example.com") });
|
||||||
|
expect(factory.numberPages).toEqual(1);
|
||||||
|
pages = factory.getPages();
|
||||||
|
a = searchHtmlNode(pages, "name", "a");
|
||||||
|
expect(a.value).toEqual("mailto:test@example.com");
|
||||||
|
expect(a.attributes.href).toEqual("mailto:test@example.com");
|
||||||
|
|
||||||
|
// Not a valid URL.
|
||||||
|
factory = new XFAFactory({ "xdp:xdp": getXml("qwerty/") });
|
||||||
|
expect(factory.numberPages).toEqual(1);
|
||||||
|
pages = factory.getPages();
|
||||||
|
a = searchHtmlNode(pages, "name", "a");
|
||||||
|
expect(a.value).toEqual("qwerty/");
|
||||||
|
expect(a.attributes.href).toEqual("");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user