From e02d17da935fb83c404721059ecf2557f93e3daa Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Tue, 13 Apr 2021 18:25:48 +0200 Subject: [PATCH] Move the `FileSpec` from `src/core/obj.js` and into its own file The size of the `src/core/obj.js` file has increased slowly over the years, and it also contains a fair amount of *distinct* functionality. In order to improve readability and make it easier to navigate through the code, this patch moves the `FileSpec` into its own file. --- src/core/annotation.js | 3 +- src/core/file_spec.js | 113 +++++++++++++++++++++++++++++++++++++++++ src/core/obj.js | 96 +--------------------------------- 3 files changed, 117 insertions(+), 95 deletions(-) create mode 100644 src/core/file_spec.js diff --git a/src/core/annotation.js b/src/core/annotation.js index 3d6afebfb..c30fdaeba 100644 --- a/src/core/annotation.js +++ b/src/core/annotation.js @@ -34,7 +34,6 @@ import { Util, warn, } from "../shared/util.js"; -import { Catalog, FileSpec } from "./obj.js"; import { collectActions, getInheritableProperty } from "./core_utils.js"; import { createDefaultAppearance, @@ -49,7 +48,9 @@ import { Name, RefSet, } from "./primitives.js"; +import { Catalog } from "./obj.js"; import { ColorSpace } from "./colorspace.js"; +import { FileSpec } from "./file_spec.js"; import { ObjectLoader } from "./object_loader.js"; import { OperatorList } from "./operator_list.js"; import { StringStream } from "./stream.js"; diff --git a/src/core/file_spec.js b/src/core/file_spec.js new file mode 100644 index 000000000..9beee0a6d --- /dev/null +++ b/src/core/file_spec.js @@ -0,0 +1,113 @@ +/* Copyright 2021 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* eslint-disable no-var */ + +import { isDict, isStream } from "./primitives.js"; +import { stringToPDFString, warn } from "../shared/util.js"; + +/** + * "A PDF file can refer to the contents of another file by using a File + * Specification (PDF 1.1)", see the spec (7.11) for more details. + * NOTE: Only embedded files are supported (as part of the attachments support) + * TODO: support the 'URL' file system (with caching if !/V), portable + * collections attributes and related files (/RF) + */ +var FileSpec = (function FileSpecClosure() { + // eslint-disable-next-line no-shadow + function FileSpec(root, xref) { + if (!root || !isDict(root)) { + return; + } + this.xref = xref; + this.root = root; + if (root.has("FS")) { + this.fs = root.get("FS"); + } + this.description = root.has("Desc") + ? stringToPDFString(root.get("Desc")) + : ""; + if (root.has("RF")) { + warn("Related file specifications are not supported"); + } + this.contentAvailable = true; + if (!root.has("EF")) { + this.contentAvailable = false; + warn("Non-embedded file specifications are not supported"); + } + } + + function pickPlatformItem(dict) { + // 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; + } + + FileSpec.prototype = { + get filename() { + if (!this._filename && this.root) { + var filename = pickPlatformItem(this.root) || "unnamed"; + this._filename = stringToPDFString(filename) + .replace(/\\\\/g, "\\") + .replace(/\\\//g, "/") + .replace(/\\/g, "/"); + } + return this._filename; + }, + get content() { + if (!this.contentAvailable) { + return null; + } + if (!this.contentRef && this.root) { + this.contentRef = pickPlatformItem(this.root.get("EF")); + } + var content = null; + if (this.contentRef) { + var xref = this.xref; + var fileObj = xref.fetchIfRef(this.contentRef); + if (fileObj && isStream(fileObj)) { + content = fileObj.getBytes(); + } else { + warn( + "Embedded file specification points to non-existing/invalid " + + "content" + ); + } + } else { + warn("Embedded file specification does not have a content"); + } + return content; + }, + get serializable() { + return { + filename: this.filename, + content: this.content, + }; + }, + }; + return FileSpec; +})(); + +export { FileSpec }; diff --git a/src/core/obj.js b/src/core/obj.js index 49e2bb353..ea9e7d0e3 100644 --- a/src/core/obj.js +++ b/src/core/obj.js @@ -58,6 +58,7 @@ import { import { Lexer, Parser } from "./parser.js"; import { CipherTransformFactory } from "./crypto.js"; import { ColorSpace } from "./colorspace.js"; +import { FileSpec } from "./file_spec.js"; import { GlobalImageCache } from "./image_utils.js"; import { MetadataParser } from "./metadata_parser.js"; import { StructTreeRoot } from "./struct_tree.js"; @@ -2419,97 +2420,4 @@ class NumberTree extends NameOrNumberTree { } } -/** - * "A PDF file can refer to the contents of another file by using a File - * Specification (PDF 1.1)", see the spec (7.11) for more details. - * NOTE: Only embedded files are supported (as part of the attachments support) - * TODO: support the 'URL' file system (with caching if !/V), portable - * collections attributes and related files (/RF) - */ -var FileSpec = (function FileSpecClosure() { - // eslint-disable-next-line no-shadow - function FileSpec(root, xref) { - if (!root || !isDict(root)) { - return; - } - this.xref = xref; - this.root = root; - if (root.has("FS")) { - this.fs = root.get("FS"); - } - this.description = root.has("Desc") - ? stringToPDFString(root.get("Desc")) - : ""; - if (root.has("RF")) { - warn("Related file specifications are not supported"); - } - this.contentAvailable = true; - if (!root.has("EF")) { - this.contentAvailable = false; - warn("Non-embedded file specifications are not supported"); - } - } - - function pickPlatformItem(dict) { - // 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; - } - - FileSpec.prototype = { - get filename() { - if (!this._filename && this.root) { - var filename = pickPlatformItem(this.root) || "unnamed"; - this._filename = stringToPDFString(filename) - .replace(/\\\\/g, "\\") - .replace(/\\\//g, "/") - .replace(/\\/g, "/"); - } - return this._filename; - }, - get content() { - if (!this.contentAvailable) { - return null; - } - if (!this.contentRef && this.root) { - this.contentRef = pickPlatformItem(this.root.get("EF")); - } - var content = null; - if (this.contentRef) { - var xref = this.xref; - var fileObj = xref.fetchIfRef(this.contentRef); - if (fileObj && isStream(fileObj)) { - content = fileObj.getBytes(); - } else { - warn( - "Embedded file specification points to non-existing/invalid " + - "content" - ); - } - } else { - warn("Embedded file specification does not have a content"); - } - return content; - }, - get serializable() { - return { - filename: this.filename, - content: this.content, - }; - }, - }; - return FileSpec; -})(); - -export { Catalog, FileSpec, NumberTree, XRef }; +export { Catalog, NumberTree, XRef };