mirror of
https://github.com/mozilla/pdf.js.git
synced 2026-08-03 04:47:21 +02:00
Merge pull request #20596 from Snuffleupagus/FileSpec-fixes
Simplify the `FileSpec` class, and remove no longer needed polyfills
This commit is contained in:
commit
471adfd023
@ -5290,8 +5290,8 @@ class FileAttachmentAnnotation extends MarkupAnnotation {
|
|||||||
constructor(params) {
|
constructor(params) {
|
||||||
super(params);
|
super(params);
|
||||||
|
|
||||||
const { dict, xref } = params;
|
const { dict } = params;
|
||||||
const file = new FileSpec(dict.get("FS"), xref);
|
const file = new FileSpec(dict.get("FS"));
|
||||||
|
|
||||||
this.data.annotationType = AnnotationType.FILEATTACHMENT;
|
this.data.annotationType = AnnotationType.FILEATTACHMENT;
|
||||||
this.data.hasOwnCanvas = this.data.noRotate;
|
this.data.hasOwnCanvas = this.data.noRotate;
|
||||||
|
|||||||
@ -1057,7 +1057,7 @@ class Catalog {
|
|||||||
if (obj instanceof Dict && obj.has("EmbeddedFiles")) {
|
if (obj instanceof Dict && obj.has("EmbeddedFiles")) {
|
||||||
const nameTree = new NameTree(obj.getRaw("EmbeddedFiles"), this.xref);
|
const nameTree = new NameTree(obj.getRaw("EmbeddedFiles"), this.xref);
|
||||||
for (const [key, value] of nameTree.getAll()) {
|
for (const [key, value] of nameTree.getAll()) {
|
||||||
const fs = new FileSpec(value, this.xref);
|
const fs = new FileSpec(value);
|
||||||
attachments ??= Object.create(null);
|
attachments ??= Object.create(null);
|
||||||
attachments[stringToPDFString(key, /* keepEscapeSequence = */ true)] =
|
attachments[stringToPDFString(key, /* keepEscapeSequence = */ true)] =
|
||||||
fs.serializable;
|
fs.serializable;
|
||||||
@ -1623,23 +1623,21 @@ class Catalog {
|
|||||||
case "GoToR":
|
case "GoToR":
|
||||||
const urlDict = action.get("F");
|
const urlDict = action.get("F");
|
||||||
if (urlDict instanceof Dict) {
|
if (urlDict instanceof Dict) {
|
||||||
const fs = new FileSpec(
|
const fs = new FileSpec(urlDict, /* skipContent = */ true);
|
||||||
urlDict,
|
({ rawFilename: url } = fs.serializable);
|
||||||
/* xref = */ null,
|
|
||||||
/* skipContent = */ true
|
|
||||||
);
|
|
||||||
const { rawFilename } = fs.serializable;
|
|
||||||
url = rawFilename;
|
|
||||||
} else if (typeof urlDict === "string") {
|
} else if (typeof urlDict === "string") {
|
||||||
url = urlDict;
|
url = urlDict;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: the destination is relative to the *remote* document.
|
// NOTE: the destination is relative to the *remote* document.
|
||||||
const remoteDest = fetchRemoteDest(action);
|
const remoteDest = fetchRemoteDest(action);
|
||||||
if (remoteDest && typeof url === "string") {
|
if (remoteDest) {
|
||||||
// NOTE: We don't use the `updateUrlHash` function here, since
|
// NOTE: We don't use the `updateUrlHash` function here, since
|
||||||
// the `createValidAbsoluteUrl` function (see below) already
|
// the `createValidAbsoluteUrl` function (see below) already handles
|
||||||
// handles parsing and validation of the final URL.
|
// parsing/validation of the final URL and manual splitting also
|
||||||
|
// ensures that the `unsafeUrl` property will be available/correct.
|
||||||
url = /* baseUrl = */ url.split("#", 1)[0] + "#" + remoteDest;
|
url = /* baseUrl = */ url.split("#", 1)[0] + "#" + remoteDest;
|
||||||
}
|
}
|
||||||
// The 'NewWindow' property, equal to `LinkTarget.BLANK`.
|
// The 'NewWindow' property, equal to `LinkTarget.BLANK`.
|
||||||
|
|||||||
@ -27,7 +27,6 @@ import {
|
|||||||
stringToBytes,
|
stringToBytes,
|
||||||
stringToPDFString,
|
stringToPDFString,
|
||||||
stringToUTF8String,
|
stringToUTF8String,
|
||||||
toHexUtil,
|
|
||||||
unreachable,
|
unreachable,
|
||||||
Util,
|
Util,
|
||||||
warn,
|
warn,
|
||||||
@ -1628,8 +1627,8 @@ class PDFDocument {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return shadow(this, "fingerprints", [
|
return shadow(this, "fingerprints", [
|
||||||
toHexUtil(hashOriginal),
|
hashOriginal.toHex(),
|
||||||
hashModified ? toHexUtil(hashModified) : null,
|
hashModified?.toHex() ?? null,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,26 +13,18 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { shadow, stringToPDFString, warn } from "../shared/util.js";
|
import { stringToPDFString, warn } from "../shared/util.js";
|
||||||
import { BaseStream } from "./base_stream.js";
|
import { BaseStream } from "./base_stream.js";
|
||||||
import { Dict } from "./primitives.js";
|
import { Dict } from "./primitives.js";
|
||||||
|
|
||||||
function pickPlatformItem(dict) {
|
function pickPlatformItem(dict) {
|
||||||
if (!(dict instanceof Dict)) {
|
if (dict instanceof Dict) {
|
||||||
return null;
|
// Look for the filename in this order: UF, F, Unix, Mac, DOS
|
||||||
|
for (const key of ["UF", "F", "Unix", "Mac", "DOS"]) {
|
||||||
|
if (dict.has(key)) {
|
||||||
|
return dict.get(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Look for the filename in this order:
|
|
||||||
// UF, F, Unix, Mac, DOS
|
|
||||||
if (dict.has("UF")) {
|
|
||||||
return dict.get("UF");
|
|
||||||
} else if (dict.has("F")) {
|
|
||||||
return dict.get("F");
|
|
||||||
} else if (dict.has("Unix")) {
|
|
||||||
return dict.get("Unix");
|
|
||||||
} else if (dict.has("Mac")) {
|
|
||||||
return dict.get("Mac");
|
|
||||||
} else if (dict.has("DOS")) {
|
|
||||||
return dict.get("DOS");
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -51,11 +43,10 @@ function stripPath(str) {
|
|||||||
class FileSpec {
|
class FileSpec {
|
||||||
#contentAvailable = false;
|
#contentAvailable = false;
|
||||||
|
|
||||||
constructor(root, xref, skipContent = false) {
|
constructor(root, skipContent = false) {
|
||||||
if (!(root instanceof Dict)) {
|
if (!(root instanceof Dict)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.xref = xref;
|
|
||||||
this.root = root;
|
this.root = root;
|
||||||
if (root.has("FS")) {
|
if (root.has("FS")) {
|
||||||
this.fs = root.get("FS");
|
this.fs = root.get("FS");
|
||||||
@ -73,56 +64,46 @@ class FileSpec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get filename() {
|
get filename() {
|
||||||
let filename = "";
|
|
||||||
|
|
||||||
const item = pickPlatformItem(this.root);
|
const item = pickPlatformItem(this.root);
|
||||||
if (item && typeof item === "string") {
|
if (item && typeof item === "string") {
|
||||||
filename = stringToPDFString(item, /* keepEscapeSequence = */ true)
|
// NOTE: The following replacement order is INTENTIONAL, regardless of
|
||||||
|
// what some static code analysers (e.g. CodeQL) may claim.
|
||||||
|
return stringToPDFString(item, /* keepEscapeSequence = */ true)
|
||||||
.replaceAll("\\\\", "\\")
|
.replaceAll("\\\\", "\\")
|
||||||
.replaceAll("\\/", "/")
|
.replaceAll("\\/", "/")
|
||||||
.replaceAll("\\", "/");
|
.replaceAll("\\", "/");
|
||||||
}
|
}
|
||||||
return shadow(this, "filename", filename || "unnamed");
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
get content() {
|
get content() {
|
||||||
if (!this.#contentAvailable) {
|
if (!this.#contentAvailable) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
this._contentRef ||= pickPlatformItem(this.root?.get("EF"));
|
const ef = pickPlatformItem(this.root?.get("EF"));
|
||||||
|
|
||||||
let content = null;
|
if (ef instanceof BaseStream) {
|
||||||
if (this._contentRef) {
|
return ef.getBytes();
|
||||||
const fileObj = this.xref.fetchIfRef(this._contentRef);
|
|
||||||
if (fileObj instanceof BaseStream) {
|
|
||||||
content = fileObj.getBytes();
|
|
||||||
} else {
|
|
||||||
warn(
|
|
||||||
"Embedded file specification points to non-existing/invalid content"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else {
|
warn("Embedded file specification points to non-existing/invalid content");
|
||||||
warn("Embedded file specification does not have any content");
|
return null;
|
||||||
}
|
|
||||||
return content;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get description() {
|
get description() {
|
||||||
let description = "";
|
|
||||||
|
|
||||||
const desc = this.root?.get("Desc");
|
const desc = this.root?.get("Desc");
|
||||||
if (desc && typeof desc === "string") {
|
if (desc && typeof desc === "string") {
|
||||||
description = stringToPDFString(desc);
|
return stringToPDFString(desc);
|
||||||
}
|
}
|
||||||
return shadow(this, "description", description);
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
get serializable() {
|
get serializable() {
|
||||||
|
const { filename, content, description } = this;
|
||||||
return {
|
return {
|
||||||
rawFilename: this.filename,
|
rawFilename: filename,
|
||||||
filename: stripPath(this.filename),
|
filename: stripPath(filename) || "unnamed",
|
||||||
content: this.content,
|
content,
|
||||||
description: this.description,
|
description,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -90,7 +90,6 @@ import {
|
|||||||
XFAObject,
|
XFAObject,
|
||||||
XFAObjectArray,
|
XFAObjectArray,
|
||||||
} from "./xfa_object.js";
|
} from "./xfa_object.js";
|
||||||
import { fromBase64Util, Util, warn } from "../../shared/util.js";
|
|
||||||
import {
|
import {
|
||||||
getBBox,
|
getBBox,
|
||||||
getColor,
|
getColor,
|
||||||
@ -103,6 +102,7 @@ import {
|
|||||||
getStringOption,
|
getStringOption,
|
||||||
HTMLResult,
|
HTMLResult,
|
||||||
} from "./utils.js";
|
} from "./utils.js";
|
||||||
|
import { Util, warn } from "../../shared/util.js";
|
||||||
import { getMetrics } from "./fonts.js";
|
import { getMetrics } from "./fonts.js";
|
||||||
import { recoverJsURL } from "../core_utils.js";
|
import { recoverJsURL } from "../core_utils.js";
|
||||||
import { searchNode } from "./som.js";
|
import { searchNode } from "./som.js";
|
||||||
@ -3420,7 +3420,7 @@ class Image extends StringObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!buffer && this.transferEncoding === "base64") {
|
if (!buffer && this.transferEncoding === "base64") {
|
||||||
buffer = fromBase64Util(this[$content]);
|
buffer = Uint8Array.fromBase64(this[$content]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
|
|||||||
@ -13,10 +13,10 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { fromBase64Util, toBase64Util, warn } from "../../../shared/util.js";
|
|
||||||
import { ContourDrawOutline } from "./contour.js";
|
import { ContourDrawOutline } from "./contour.js";
|
||||||
import { InkDrawOutline } from "./inkdraw.js";
|
import { InkDrawOutline } from "./inkdraw.js";
|
||||||
import { Outline } from "./outline.js";
|
import { Outline } from "./outline.js";
|
||||||
|
import { warn } from "../../../shared/util.js";
|
||||||
|
|
||||||
const BASE_HEADER_LENGTH = 8;
|
const BASE_HEADER_LENGTH = 8;
|
||||||
const POINTS_PROPERTIES_NUMBER = 3;
|
const POINTS_PROPERTIES_NUMBER = 3;
|
||||||
@ -749,12 +749,12 @@ class SignatureExtractor {
|
|||||||
const buf = await new Response(cs.readable).arrayBuffer();
|
const buf = await new Response(cs.readable).arrayBuffer();
|
||||||
const bytes = new Uint8Array(buf);
|
const bytes = new Uint8Array(buf);
|
||||||
|
|
||||||
return toBase64Util(bytes);
|
return bytes.toBase64();
|
||||||
}
|
}
|
||||||
|
|
||||||
static async decompressSignature(signatureData) {
|
static async decompressSignature(signatureData) {
|
||||||
try {
|
try {
|
||||||
const bytes = fromBase64Util(signatureData);
|
const bytes = Uint8Array.fromBase64(signatureData);
|
||||||
const { readable, writable } = new DecompressionStream("deflate-raw");
|
const { readable, writable } = new DecompressionStream("deflate-raw");
|
||||||
const writer = writable.getWriter();
|
const writer = writable.getWriter();
|
||||||
await writer.ready;
|
await writer.ready;
|
||||||
|
|||||||
@ -19,7 +19,6 @@ import {
|
|||||||
isNodeJS,
|
isNodeJS,
|
||||||
shadow,
|
shadow,
|
||||||
string32,
|
string32,
|
||||||
toBase64Util,
|
|
||||||
unreachable,
|
unreachable,
|
||||||
warn,
|
warn,
|
||||||
} from "../shared/util.js";
|
} from "../shared/util.js";
|
||||||
@ -408,7 +407,7 @@ class FontFaceObject {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// Add the @font-face rule to the document.
|
// Add the @font-face rule to the document.
|
||||||
const url = `url(data:${this.mimetype};base64,${toBase64Util(this.data)});`;
|
const url = `url(data:${this.mimetype};base64,${this.data.toBase64()});`;
|
||||||
let rule;
|
let rule;
|
||||||
if (!this.cssFontInfo) {
|
if (!this.cssFontInfo) {
|
||||||
rule = `@font-face {font-family:"${this.loadedName}";src:${url}}`;
|
rule = `@font-face {font-family:"${this.loadedName}";src:${url}}`;
|
||||||
|
|||||||
@ -1235,44 +1235,6 @@ function MathClamp(v, min, max) {
|
|||||||
return Math.min(Math.max(v, min), max);
|
return Math.min(Math.max(v, min), max);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Remove this once `Uint8Array.prototype.toHex` is generally available.
|
|
||||||
function toHexUtil(arr) {
|
|
||||||
if (Uint8Array.prototype.toHex) {
|
|
||||||
return arr.toHex();
|
|
||||||
}
|
|
||||||
return Array.from(arr, num => hexNumbers[num]).join("");
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Remove this once `Uint8Array.prototype.toBase64` is generally
|
|
||||||
// available.
|
|
||||||
function toBase64Util(arr) {
|
|
||||||
if (Uint8Array.prototype.toBase64) {
|
|
||||||
return arr.toBase64();
|
|
||||||
}
|
|
||||||
return btoa(bytesToString(arr));
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Remove this once `Uint8Array.fromBase64` is generally available.
|
|
||||||
function fromBase64Util(str) {
|
|
||||||
if (Uint8Array.fromBase64) {
|
|
||||||
return Uint8Array.fromBase64(str);
|
|
||||||
}
|
|
||||||
return stringToBytes(atob(str));
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Remove this once https://bugzilla.mozilla.org/show_bug.cgi?id=1928493
|
|
||||||
// is fixed.
|
|
||||||
if (
|
|
||||||
(typeof PDFJSDev === "undefined" || PDFJSDev.test("SKIP_BABEL")) &&
|
|
||||||
typeof Promise.try !== "function"
|
|
||||||
) {
|
|
||||||
Promise.try = function (fn, ...args) {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
resolve(fn(...args));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Remove this once the `javascript.options.experimental.math_sumprecise`
|
// TODO: Remove this once the `javascript.options.experimental.math_sumprecise`
|
||||||
// preference is removed from Firefox.
|
// preference is removed from Firefox.
|
||||||
if (typeof Math.sumPrecise !== "function") {
|
if (typeof Math.sumPrecise !== "function") {
|
||||||
@ -1338,7 +1300,6 @@ export {
|
|||||||
FeatureTest,
|
FeatureTest,
|
||||||
FONT_IDENTITY_MATRIX,
|
FONT_IDENTITY_MATRIX,
|
||||||
FormatError,
|
FormatError,
|
||||||
fromBase64Util,
|
|
||||||
getModificationDate,
|
getModificationDate,
|
||||||
getUuid,
|
getUuid,
|
||||||
getVerbosityLevel,
|
getVerbosityLevel,
|
||||||
@ -1368,8 +1329,6 @@ export {
|
|||||||
stringToPDFString,
|
stringToPDFString,
|
||||||
stringToUTF8String,
|
stringToUTF8String,
|
||||||
TextRenderingMode,
|
TextRenderingMode,
|
||||||
toBase64Util,
|
|
||||||
toHexUtil,
|
|
||||||
UnknownErrorException,
|
UnknownErrorException,
|
||||||
unreachable,
|
unreachable,
|
||||||
updateUrlHash,
|
updateUrlHash,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { decodeFontData, ttx, verifyTtxOutput } from "./fontutils.js";
|
import { ttx, verifyTtxOutput } from "./fontutils.js";
|
||||||
|
|
||||||
describe("font1", function () {
|
describe("font1", function () {
|
||||||
const font1_1 = decodeFontData(
|
const font1_1 = Uint8Array.fromBase64(
|
||||||
// eslint-disable-next-line max-len
|
// eslint-disable-next-line max-len
|
||||||
"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"
|
||||||
);
|
);
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -14,22 +14,10 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { bytesToString, stringToBytes } from "../../src/shared/util.js";
|
|
||||||
|
|
||||||
function decodeFontData(base64) {
|
|
||||||
const str = atob(base64);
|
|
||||||
return stringToBytes(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
function encodeFontData(data) {
|
|
||||||
const str = bytesToString(data);
|
|
||||||
return btoa(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function ttx(data) {
|
async function ttx(data) {
|
||||||
const response = await fetch("/ttx", {
|
const response = await fetch("/ttx", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: encodeFontData(data),
|
body: data.toBase64(),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
@ -45,4 +33,4 @@ function verifyTtxOutput(output) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { decodeFontData, encodeFontData, ttx, verifyTtxOutput };
|
export { ttx, verifyTtxOutput };
|
||||||
|
|||||||
@ -22,7 +22,7 @@ import {
|
|||||||
PDFDateString,
|
PDFDateString,
|
||||||
renderRichText,
|
renderRichText,
|
||||||
} from "../../src/display/display_utils.js";
|
} from "../../src/display/display_utils.js";
|
||||||
import { isNodeJS, toBase64Util } from "../../src/shared/util.js";
|
import { isNodeJS } from "../../src/shared/util.js";
|
||||||
|
|
||||||
describe("display_utils", function () {
|
describe("display_utils", function () {
|
||||||
describe("getFilenameFromUrl", function () {
|
describe("getFilenameFromUrl", function () {
|
||||||
@ -183,9 +183,7 @@ describe("display_utils", function () {
|
|||||||
|
|
||||||
it('gets fallback filename from query string appended to "data:" URL', function () {
|
it('gets fallback filename from query string appended to "data:" URL', function () {
|
||||||
const typedArray = new Uint8Array([1, 2, 3, 4, 5]);
|
const typedArray = new Uint8Array([1, 2, 3, 4, 5]);
|
||||||
const dataUrl = `data:application/pdf;base64,${toBase64Util(typedArray)}`;
|
const dataUrl = `data:application/pdf;base64,${typedArray.toBase64()}`;
|
||||||
// Sanity check to ensure that a "data:" URL was returned.
|
|
||||||
expect(dataUrl.startsWith("data:")).toEqual(true);
|
|
||||||
|
|
||||||
expect(getPdfFilenameFromUrl(dataUrl + "?file1.pdf")).toEqual(
|
expect(getPdfFilenameFromUrl(dataUrl + "?file1.pdf")).toEqual(
|
||||||
"document.pdf"
|
"document.pdf"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user