Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/core/annotation.js
Original file line number Diff line number Diff line change
Expand Up @@ -5290,8 +5290,8 @@ class FileAttachmentAnnotation extends MarkupAnnotation {
constructor(params) {
super(params);

const { dict, xref } = params;
const file = new FileSpec(dict.get("FS"), xref);
const { dict } = params;
const file = new FileSpec(dict.get("FS"));

this.data.annotationType = AnnotationType.FILEATTACHMENT;
this.data.hasOwnCanvas = this.data.noRotate;
Expand Down
20 changes: 9 additions & 11 deletions src/core/catalog.js
Original file line number Diff line number Diff line change
Expand Up @@ -1057,7 +1057,7 @@ class Catalog {
if (obj instanceof Dict && obj.has("EmbeddedFiles")) {
const nameTree = new NameTree(obj.getRaw("EmbeddedFiles"), this.xref);
for (const [key, value] of nameTree.getAll()) {
const fs = new FileSpec(value, this.xref);
const fs = new FileSpec(value);
attachments ??= Object.create(null);
attachments[stringToPDFString(key, /* keepEscapeSequence = */ true)] =
fs.serializable;
Expand Down Expand Up @@ -1623,23 +1623,21 @@ class Catalog {
case "GoToR":
const urlDict = action.get("F");
if (urlDict instanceof Dict) {
const fs = new FileSpec(
urlDict,
/* xref = */ null,
/* skipContent = */ true
);
const { rawFilename } = fs.serializable;
url = rawFilename;
const fs = new FileSpec(urlDict, /* skipContent = */ true);
({ rawFilename: url } = fs.serializable);
} else if (typeof urlDict === "string") {
url = urlDict;
} else {
break;
}

// NOTE: the destination is relative to the *remote* document.
const remoteDest = fetchRemoteDest(action);
if (remoteDest && typeof url === "string") {
if (remoteDest) {
// NOTE: We don't use the `updateUrlHash` function here, since
// the `createValidAbsoluteUrl` function (see below) already
// handles parsing and validation of the final URL.
// the `createValidAbsoluteUrl` function (see below) already handles
// 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;
}
// The 'NewWindow' property, equal to `LinkTarget.BLANK`.
Expand Down
5 changes: 2 additions & 3 deletions src/core/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import {
stringToBytes,
stringToPDFString,
stringToUTF8String,
toHexUtil,
unreachable,
Util,
warn,
Expand Down Expand Up @@ -1605,8 +1604,8 @@ class PDFDocument {
}

return shadow(this, "fingerprints", [
toHexUtil(hashOriginal),
hashModified ? toHexUtil(hashModified) : null,
hashOriginal.toHex(),
hashModified?.toHex() ?? null,
]);
}

Expand Down
67 changes: 23 additions & 44 deletions src/core/file_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,18 @@
* 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 { Dict } from "./primitives.js";

function pickPlatformItem(dict) {
if (!(dict instanceof Dict)) {
return null;
}
// 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");
if (dict instanceof Dict) {
// 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);
}
}
}
return null;
}
Expand All @@ -51,11 +43,10 @@
class FileSpec {
#contentAvailable = false;

constructor(root, xref, skipContent = false) {
constructor(root, skipContent = false) {
if (!(root instanceof Dict)) {
return;
}
this.xref = xref;
this.root = root;
if (root.has("FS")) {
this.fs = root.get("FS");
Expand All @@ -73,56 +64,44 @@
}

get filename() {
let filename = "";

const item = pickPlatformItem(this.root);
if (item && typeof item === "string") {
filename = stringToPDFString(item, /* keepEscapeSequence = */ true)
return stringToPDFString(item, /* keepEscapeSequence = */ true)
.replaceAll("\\\\", "\\")

Check failure

Code scanning / CodeQL

Double escaping or unescaping High

This replacement may produce '' characters that are double-unescaped
here
.
.replaceAll("\\/", "/")
.replaceAll("\\", "/");
}
return shadow(this, "filename", filename || "unnamed");
return "";
}

get content() {
if (!this.#contentAvailable) {
return null;
}
this._contentRef ||= pickPlatformItem(this.root?.get("EF"));
const ef = pickPlatformItem(this.root?.get("EF"));

let content = null;
if (this._contentRef) {
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 does not have any content");
if (ef instanceof BaseStream) {
return ef.getBytes();
}
return content;
warn("Embedded file specification points to non-existing/invalid content");
return null;
}

get description() {
let description = "";

const desc = this.root?.get("Desc");
if (desc && typeof desc === "string") {
description = stringToPDFString(desc);
return stringToPDFString(desc);
}
return shadow(this, "description", description);
return "";
}

get serializable() {
const { filename, content, description } = this;
return {
rawFilename: this.filename,
filename: stripPath(this.filename),
content: this.content,
description: this.description,
rawFilename: filename,
filename: stripPath(filename) || "unnamed",
content,
description,
};
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/core/xfa/template.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ import {
XFAObject,
XFAObjectArray,
} from "./xfa_object.js";
import { fromBase64Util, Util, warn } from "../../shared/util.js";
import {
getBBox,
getColor,
Expand All @@ -103,6 +102,7 @@ import {
getStringOption,
HTMLResult,
} from "./utils.js";
import { Util, warn } from "../../shared/util.js";
import { getMetrics } from "./fonts.js";
import { recoverJsURL } from "../core_utils.js";
import { searchNode } from "./som.js";
Expand Down Expand Up @@ -3420,7 +3420,7 @@ class Image extends StringObject {
}

if (!buffer && this.transferEncoding === "base64") {
buffer = fromBase64Util(this[$content]);
buffer = Uint8Array.fromBase64(this[$content]);
}

if (!buffer) {
Expand Down
6 changes: 3 additions & 3 deletions src/display/editor/drawers/signaturedraw.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
* limitations under the License.
*/

import { fromBase64Util, toBase64Util, warn } from "../../../shared/util.js";
import { ContourDrawOutline } from "./contour.js";
import { InkDrawOutline } from "./inkdraw.js";
import { Outline } from "./outline.js";
import { warn } from "../../../shared/util.js";

const BASE_HEADER_LENGTH = 8;
const POINTS_PROPERTIES_NUMBER = 3;
Expand Down Expand Up @@ -749,12 +749,12 @@ class SignatureExtractor {
const buf = await new Response(cs.readable).arrayBuffer();
const bytes = new Uint8Array(buf);

return toBase64Util(bytes);
return bytes.toBase64();
}

static async decompressSignature(signatureData) {
try {
const bytes = fromBase64Util(signatureData);
const bytes = Uint8Array.fromBase64(signatureData);
const { readable, writable } = new DecompressionStream("deflate-raw");
const writer = writable.getWriter();
await writer.ready;
Expand Down
3 changes: 1 addition & 2 deletions src/display/font_loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import {
isNodeJS,
shadow,
string32,
toBase64Util,
unreachable,
warn,
} from "../shared/util.js";
Expand Down Expand Up @@ -408,7 +407,7 @@ class FontFaceObject {
return null;
}
// 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;
if (!this.cssFontInfo) {
rule = `@font-face {font-family:"${this.loadedName}";src:${url}}`;
Expand Down
41 changes: 0 additions & 41 deletions src/shared/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -1235,44 +1235,6 @@ function MathClamp(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`
// preference is removed from Firefox.
if (typeof Math.sumPrecise !== "function") {
Expand Down Expand Up @@ -1338,7 +1300,6 @@ export {
FeatureTest,
FONT_IDENTITY_MATRIX,
FormatError,
fromBase64Util,
getModificationDate,
getUuid,
getVerbosityLevel,
Expand Down Expand Up @@ -1368,8 +1329,6 @@ export {
stringToPDFString,
stringToUTF8String,
TextRenderingMode,
toBase64Util,
toHexUtil,
UnknownErrorException,
unreachable,
updateUrlHash,
Expand Down
6 changes: 2 additions & 4 deletions test/unit/display_utils_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
PDFDateString,
renderRichText,
} 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("getFilenameFromUrl", function () {
Expand Down Expand Up @@ -183,9 +183,7 @@ describe("display_utils", function () {

it('gets fallback filename from query string appended to "data:" URL', function () {
const typedArray = new Uint8Array([1, 2, 3, 4, 5]);
const dataUrl = `data:application/pdf;base64,${toBase64Util(typedArray)}`;
// Sanity check to ensure that a "data:" URL was returned.
expect(dataUrl.startsWith("data:")).toEqual(true);
const dataUrl = `data:application/pdf;base64,${typedArray.toBase64()}`;

expect(getPdfFilenameFromUrl(dataUrl + "?file1.pdf")).toEqual(
"document.pdf"
Expand Down