catalog.js 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682
  1. /**
  2. * @licstart The following is the entire license notice for the
  3. * Javascript code in this page
  4. *
  5. * Copyright 2021 Mozilla Foundation
  6. *
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. *
  19. * @licend The above is the entire license notice for the
  20. * Javascript code in this page
  21. */
  22. "use strict";
  23. Object.defineProperty(exports, "__esModule", {
  24. value: true
  25. });
  26. exports.Catalog = void 0;
  27. var _primitives = require("./primitives.js");
  28. var _core_utils = require("./core_utils.js");
  29. var _util = require("../shared/util.js");
  30. var _name_number_tree = require("./name_number_tree.js");
  31. var _base_stream = require("./base_stream.js");
  32. var _colorspace = require("./colorspace.js");
  33. var _file_spec = require("./file_spec.js");
  34. var _image_utils = require("./image_utils.js");
  35. var _metadata_parser = require("./metadata_parser.js");
  36. var _struct_tree = require("./struct_tree.js");
  37. function fetchDestination(dest) {
  38. if (dest instanceof _primitives.Dict) {
  39. dest = dest.get("D");
  40. }
  41. return Array.isArray(dest) ? dest : null;
  42. }
  43. class Catalog {
  44. constructor(pdfManager, xref) {
  45. this.pdfManager = pdfManager;
  46. this.xref = xref;
  47. this._catDict = xref.getCatalogObj();
  48. if (!(this._catDict instanceof _primitives.Dict)) {
  49. throw new _util.FormatError("Catalog object is not a dictionary.");
  50. }
  51. this.toplevelPagesDict;
  52. this._actualNumPages = null;
  53. this.fontCache = new _primitives.RefSetCache();
  54. this.builtInCMapCache = new Map();
  55. this.standardFontDataCache = new Map();
  56. this.globalImageCache = new _image_utils.GlobalImageCache();
  57. this.pageKidsCountCache = new _primitives.RefSetCache();
  58. this.pageIndexCache = new _primitives.RefSetCache();
  59. this.nonBlendModesSet = new _primitives.RefSet();
  60. }
  61. get version() {
  62. const version = this._catDict.get("Version");
  63. return (0, _util.shadow)(this, "version", version instanceof _primitives.Name ? version.name : null);
  64. }
  65. get lang() {
  66. const lang = this._catDict.get("Lang");
  67. return (0, _util.shadow)(this, "lang", typeof lang === "string" ? (0, _util.stringToPDFString)(lang) : null);
  68. }
  69. get needsRendering() {
  70. const needsRendering = this._catDict.get("NeedsRendering");
  71. return (0, _util.shadow)(this, "needsRendering", typeof needsRendering === "boolean" ? needsRendering : false);
  72. }
  73. get collection() {
  74. let collection = null;
  75. try {
  76. const obj = this._catDict.get("Collection");
  77. if ((0, _primitives.isDict)(obj) && obj.size > 0) {
  78. collection = obj;
  79. }
  80. } catch (ex) {
  81. if (ex instanceof _core_utils.MissingDataException) {
  82. throw ex;
  83. }
  84. (0, _util.info)("Cannot fetch Collection entry; assuming no collection is present.");
  85. }
  86. return (0, _util.shadow)(this, "collection", collection);
  87. }
  88. get acroForm() {
  89. let acroForm = null;
  90. try {
  91. const obj = this._catDict.get("AcroForm");
  92. if ((0, _primitives.isDict)(obj) && obj.size > 0) {
  93. acroForm = obj;
  94. }
  95. } catch (ex) {
  96. if (ex instanceof _core_utils.MissingDataException) {
  97. throw ex;
  98. }
  99. (0, _util.info)("Cannot fetch AcroForm entry; assuming no forms are present.");
  100. }
  101. return (0, _util.shadow)(this, "acroForm", acroForm);
  102. }
  103. get acroFormRef() {
  104. const value = this._catDict.getRaw("AcroForm");
  105. return (0, _util.shadow)(this, "acroFormRef", (0, _primitives.isRef)(value) ? value : null);
  106. }
  107. get metadata() {
  108. const streamRef = this._catDict.getRaw("Metadata");
  109. if (!(streamRef instanceof _primitives.Ref)) {
  110. return (0, _util.shadow)(this, "metadata", null);
  111. }
  112. let metadata = null;
  113. try {
  114. const suppressEncryption = !(this.xref.encrypt && this.xref.encrypt.encryptMetadata);
  115. const stream = this.xref.fetch(streamRef, suppressEncryption);
  116. if (stream instanceof _base_stream.BaseStream && stream.dict instanceof _primitives.Dict) {
  117. const type = stream.dict.get("Type");
  118. const subtype = stream.dict.get("Subtype");
  119. if ((0, _primitives.isName)(type, "Metadata") && (0, _primitives.isName)(subtype, "XML")) {
  120. const data = (0, _util.stringToUTF8String)(stream.getString());
  121. if (data) {
  122. metadata = new _metadata_parser.MetadataParser(data).serializable;
  123. }
  124. }
  125. }
  126. } catch (ex) {
  127. if (ex instanceof _core_utils.MissingDataException) {
  128. throw ex;
  129. }
  130. (0, _util.info)(`Skipping invalid Metadata: "${ex}".`);
  131. }
  132. return (0, _util.shadow)(this, "metadata", metadata);
  133. }
  134. get markInfo() {
  135. let markInfo = null;
  136. try {
  137. markInfo = this._readMarkInfo();
  138. } catch (ex) {
  139. if (ex instanceof _core_utils.MissingDataException) {
  140. throw ex;
  141. }
  142. (0, _util.warn)("Unable to read mark info.");
  143. }
  144. return (0, _util.shadow)(this, "markInfo", markInfo);
  145. }
  146. _readMarkInfo() {
  147. const obj = this._catDict.get("MarkInfo");
  148. if (!(0, _primitives.isDict)(obj)) {
  149. return null;
  150. }
  151. const markInfo = Object.assign(Object.create(null), {
  152. Marked: false,
  153. UserProperties: false,
  154. Suspects: false
  155. });
  156. for (const key in markInfo) {
  157. if (!obj.has(key)) {
  158. continue;
  159. }
  160. const value = obj.get(key);
  161. if (!(0, _util.isBool)(value)) {
  162. continue;
  163. }
  164. markInfo[key] = value;
  165. }
  166. return markInfo;
  167. }
  168. get structTreeRoot() {
  169. let structTree = null;
  170. try {
  171. structTree = this._readStructTreeRoot();
  172. } catch (ex) {
  173. if (ex instanceof _core_utils.MissingDataException) {
  174. throw ex;
  175. }
  176. (0, _util.warn)("Unable read to structTreeRoot info.");
  177. }
  178. return (0, _util.shadow)(this, "structTreeRoot", structTree);
  179. }
  180. _readStructTreeRoot() {
  181. const obj = this._catDict.get("StructTreeRoot");
  182. if (!(0, _primitives.isDict)(obj)) {
  183. return null;
  184. }
  185. const root = new _struct_tree.StructTreeRoot(obj);
  186. root.init();
  187. return root;
  188. }
  189. get toplevelPagesDict() {
  190. const pagesObj = this._catDict.get("Pages");
  191. if (!(0, _primitives.isDict)(pagesObj)) {
  192. throw new _util.FormatError("Invalid top-level pages dictionary.");
  193. }
  194. return (0, _util.shadow)(this, "toplevelPagesDict", pagesObj);
  195. }
  196. get documentOutline() {
  197. let obj = null;
  198. try {
  199. obj = this._readDocumentOutline();
  200. } catch (ex) {
  201. if (ex instanceof _core_utils.MissingDataException) {
  202. throw ex;
  203. }
  204. (0, _util.warn)("Unable to read document outline.");
  205. }
  206. return (0, _util.shadow)(this, "documentOutline", obj);
  207. }
  208. _readDocumentOutline() {
  209. let obj = this._catDict.get("Outlines");
  210. if (!(0, _primitives.isDict)(obj)) {
  211. return null;
  212. }
  213. obj = obj.getRaw("First");
  214. if (!(0, _primitives.isRef)(obj)) {
  215. return null;
  216. }
  217. const root = {
  218. items: []
  219. };
  220. const queue = [{
  221. obj,
  222. parent: root
  223. }];
  224. const processed = new _primitives.RefSet();
  225. processed.put(obj);
  226. const xref = this.xref,
  227. blackColor = new Uint8ClampedArray(3);
  228. while (queue.length > 0) {
  229. const i = queue.shift();
  230. const outlineDict = xref.fetchIfRef(i.obj);
  231. if (outlineDict === null) {
  232. continue;
  233. }
  234. if (!outlineDict.has("Title")) {
  235. throw new _util.FormatError("Invalid outline item encountered.");
  236. }
  237. const data = {
  238. url: null,
  239. dest: null
  240. };
  241. Catalog.parseDestDictionary({
  242. destDict: outlineDict,
  243. resultObj: data,
  244. docBaseUrl: this.pdfManager.docBaseUrl
  245. });
  246. const title = outlineDict.get("Title");
  247. const flags = outlineDict.get("F") || 0;
  248. const color = outlineDict.getArray("C");
  249. const count = outlineDict.get("Count");
  250. let rgbColor = blackColor;
  251. if (Array.isArray(color) && color.length === 3 && (color[0] !== 0 || color[1] !== 0 || color[2] !== 0)) {
  252. rgbColor = _colorspace.ColorSpace.singletons.rgb.getRgb(color, 0);
  253. }
  254. const outlineItem = {
  255. dest: data.dest,
  256. url: data.url,
  257. unsafeUrl: data.unsafeUrl,
  258. newWindow: data.newWindow,
  259. title: (0, _util.stringToPDFString)(title),
  260. color: rgbColor,
  261. count: Number.isInteger(count) ? count : undefined,
  262. bold: !!(flags & 2),
  263. italic: !!(flags & 1),
  264. items: []
  265. };
  266. i.parent.items.push(outlineItem);
  267. obj = outlineDict.getRaw("First");
  268. if ((0, _primitives.isRef)(obj) && !processed.has(obj)) {
  269. queue.push({
  270. obj,
  271. parent: outlineItem
  272. });
  273. processed.put(obj);
  274. }
  275. obj = outlineDict.getRaw("Next");
  276. if ((0, _primitives.isRef)(obj) && !processed.has(obj)) {
  277. queue.push({
  278. obj,
  279. parent: i.parent
  280. });
  281. processed.put(obj);
  282. }
  283. }
  284. return root.items.length > 0 ? root.items : null;
  285. }
  286. get permissions() {
  287. let permissions = null;
  288. try {
  289. permissions = this._readPermissions();
  290. } catch (ex) {
  291. if (ex instanceof _core_utils.MissingDataException) {
  292. throw ex;
  293. }
  294. (0, _util.warn)("Unable to read permissions.");
  295. }
  296. return (0, _util.shadow)(this, "permissions", permissions);
  297. }
  298. _readPermissions() {
  299. const encrypt = this.xref.trailer.get("Encrypt");
  300. if (!(0, _primitives.isDict)(encrypt)) {
  301. return null;
  302. }
  303. let flags = encrypt.get("P");
  304. if (!(0, _util.isNum)(flags)) {
  305. return null;
  306. }
  307. flags += 2 ** 32;
  308. const permissions = [];
  309. for (const key in _util.PermissionFlag) {
  310. const value = _util.PermissionFlag[key];
  311. if (flags & value) {
  312. permissions.push(value);
  313. }
  314. }
  315. return permissions;
  316. }
  317. get optionalContentConfig() {
  318. let config = null;
  319. try {
  320. const properties = this._catDict.get("OCProperties");
  321. if (!properties) {
  322. return (0, _util.shadow)(this, "optionalContentConfig", null);
  323. }
  324. const defaultConfig = properties.get("D");
  325. if (!defaultConfig) {
  326. return (0, _util.shadow)(this, "optionalContentConfig", null);
  327. }
  328. const groupsData = properties.get("OCGs");
  329. if (!Array.isArray(groupsData)) {
  330. return (0, _util.shadow)(this, "optionalContentConfig", null);
  331. }
  332. const groups = [];
  333. const groupRefs = [];
  334. for (const groupRef of groupsData) {
  335. if (!(0, _primitives.isRef)(groupRef)) {
  336. continue;
  337. }
  338. groupRefs.push(groupRef);
  339. const group = this.xref.fetchIfRef(groupRef);
  340. groups.push({
  341. id: groupRef.toString(),
  342. name: (0, _util.isString)(group.get("Name")) ? (0, _util.stringToPDFString)(group.get("Name")) : null,
  343. intent: (0, _util.isString)(group.get("Intent")) ? (0, _util.stringToPDFString)(group.get("Intent")) : null
  344. });
  345. }
  346. config = this._readOptionalContentConfig(defaultConfig, groupRefs);
  347. config.groups = groups;
  348. } catch (ex) {
  349. if (ex instanceof _core_utils.MissingDataException) {
  350. throw ex;
  351. }
  352. (0, _util.warn)(`Unable to read optional content config: ${ex}`);
  353. }
  354. return (0, _util.shadow)(this, "optionalContentConfig", config);
  355. }
  356. _readOptionalContentConfig(config, contentGroupRefs) {
  357. function parseOnOff(refs) {
  358. const onParsed = [];
  359. if (Array.isArray(refs)) {
  360. for (const value of refs) {
  361. if (!(0, _primitives.isRef)(value)) {
  362. continue;
  363. }
  364. if (contentGroupRefs.includes(value)) {
  365. onParsed.push(value.toString());
  366. }
  367. }
  368. }
  369. return onParsed;
  370. }
  371. function parseOrder(refs, nestedLevels = 0) {
  372. if (!Array.isArray(refs)) {
  373. return null;
  374. }
  375. const order = [];
  376. for (const value of refs) {
  377. if ((0, _primitives.isRef)(value) && contentGroupRefs.includes(value)) {
  378. parsedOrderRefs.put(value);
  379. order.push(value.toString());
  380. continue;
  381. }
  382. const nestedOrder = parseNestedOrder(value, nestedLevels);
  383. if (nestedOrder) {
  384. order.push(nestedOrder);
  385. }
  386. }
  387. if (nestedLevels > 0) {
  388. return order;
  389. }
  390. const hiddenGroups = [];
  391. for (const groupRef of contentGroupRefs) {
  392. if (parsedOrderRefs.has(groupRef)) {
  393. continue;
  394. }
  395. hiddenGroups.push(groupRef.toString());
  396. }
  397. if (hiddenGroups.length) {
  398. order.push({
  399. name: null,
  400. order: hiddenGroups
  401. });
  402. }
  403. return order;
  404. }
  405. function parseNestedOrder(ref, nestedLevels) {
  406. if (++nestedLevels > MAX_NESTED_LEVELS) {
  407. (0, _util.warn)("parseNestedOrder - reached MAX_NESTED_LEVELS.");
  408. return null;
  409. }
  410. const value = xref.fetchIfRef(ref);
  411. if (!Array.isArray(value)) {
  412. return null;
  413. }
  414. const nestedName = xref.fetchIfRef(value[0]);
  415. if (typeof nestedName !== "string") {
  416. return null;
  417. }
  418. const nestedOrder = parseOrder(value.slice(1), nestedLevels);
  419. if (!nestedOrder || !nestedOrder.length) {
  420. return null;
  421. }
  422. return {
  423. name: (0, _util.stringToPDFString)(nestedName),
  424. order: nestedOrder
  425. };
  426. }
  427. const xref = this.xref,
  428. parsedOrderRefs = new _primitives.RefSet(),
  429. MAX_NESTED_LEVELS = 10;
  430. return {
  431. name: (0, _util.isString)(config.get("Name")) ? (0, _util.stringToPDFString)(config.get("Name")) : null,
  432. creator: (0, _util.isString)(config.get("Creator")) ? (0, _util.stringToPDFString)(config.get("Creator")) : null,
  433. baseState: (0, _primitives.isName)(config.get("BaseState")) ? config.get("BaseState").name : null,
  434. on: parseOnOff(config.get("ON")),
  435. off: parseOnOff(config.get("OFF")),
  436. order: parseOrder(config.get("Order")),
  437. groups: null
  438. };
  439. }
  440. setActualNumPages(num = null) {
  441. this._actualNumPages = num;
  442. }
  443. get hasActualNumPages() {
  444. return this._actualNumPages !== null;
  445. }
  446. get _pagesCount() {
  447. const obj = this.toplevelPagesDict.get("Count");
  448. if (!Number.isInteger(obj)) {
  449. throw new _util.FormatError("Page count in top-level pages dictionary is not an integer.");
  450. }
  451. return (0, _util.shadow)(this, "_pagesCount", obj);
  452. }
  453. get numPages() {
  454. return this.hasActualNumPages ? this._actualNumPages : this._pagesCount;
  455. }
  456. get destinations() {
  457. const obj = this._readDests(),
  458. dests = Object.create(null);
  459. if (obj instanceof _name_number_tree.NameTree) {
  460. for (const [key, value] of obj.getAll()) {
  461. const dest = fetchDestination(value);
  462. if (dest) {
  463. dests[key] = dest;
  464. }
  465. }
  466. } else if (obj instanceof _primitives.Dict) {
  467. obj.forEach(function (key, value) {
  468. const dest = fetchDestination(value);
  469. if (dest) {
  470. dests[key] = dest;
  471. }
  472. });
  473. }
  474. return (0, _util.shadow)(this, "destinations", dests);
  475. }
  476. getDestination(id) {
  477. const obj = this._readDests();
  478. if (obj instanceof _name_number_tree.NameTree) {
  479. const dest = fetchDestination(obj.get(id));
  480. if (dest) {
  481. return dest;
  482. }
  483. const allDest = this.destinations[id];
  484. if (allDest) {
  485. (0, _util.warn)(`Found "${id}" at an incorrect position in the NameTree.`);
  486. return allDest;
  487. }
  488. } else if (obj instanceof _primitives.Dict) {
  489. const dest = fetchDestination(obj.get(id));
  490. if (dest) {
  491. return dest;
  492. }
  493. }
  494. return null;
  495. }
  496. _readDests() {
  497. const obj = this._catDict.get("Names");
  498. if (obj && obj.has("Dests")) {
  499. return new _name_number_tree.NameTree(obj.getRaw("Dests"), this.xref);
  500. } else if (this._catDict.has("Dests")) {
  501. return this._catDict.get("Dests");
  502. }
  503. return undefined;
  504. }
  505. get pageLabels() {
  506. let obj = null;
  507. try {
  508. obj = this._readPageLabels();
  509. } catch (ex) {
  510. if (ex instanceof _core_utils.MissingDataException) {
  511. throw ex;
  512. }
  513. (0, _util.warn)("Unable to read page labels.");
  514. }
  515. return (0, _util.shadow)(this, "pageLabels", obj);
  516. }
  517. _readPageLabels() {
  518. const obj = this._catDict.getRaw("PageLabels");
  519. if (!obj) {
  520. return null;
  521. }
  522. const pageLabels = new Array(this.numPages);
  523. let style = null,
  524. prefix = "";
  525. const numberTree = new _name_number_tree.NumberTree(obj, this.xref);
  526. const nums = numberTree.getAll();
  527. let currentLabel = "",
  528. currentIndex = 1;
  529. for (let i = 0, ii = this.numPages; i < ii; i++) {
  530. const labelDict = nums.get(i);
  531. if (labelDict !== undefined) {
  532. if (!(0, _primitives.isDict)(labelDict)) {
  533. throw new _util.FormatError("PageLabel is not a dictionary.");
  534. }
  535. if (labelDict.has("Type") && !(0, _primitives.isName)(labelDict.get("Type"), "PageLabel")) {
  536. throw new _util.FormatError("Invalid type in PageLabel dictionary.");
  537. }
  538. if (labelDict.has("S")) {
  539. const s = labelDict.get("S");
  540. if (!(0, _primitives.isName)(s)) {
  541. throw new _util.FormatError("Invalid style in PageLabel dictionary.");
  542. }
  543. style = s.name;
  544. } else {
  545. style = null;
  546. }
  547. if (labelDict.has("P")) {
  548. const p = labelDict.get("P");
  549. if (!(0, _util.isString)(p)) {
  550. throw new _util.FormatError("Invalid prefix in PageLabel dictionary.");
  551. }
  552. prefix = (0, _util.stringToPDFString)(p);
  553. } else {
  554. prefix = "";
  555. }
  556. if (labelDict.has("St")) {
  557. const st = labelDict.get("St");
  558. if (!(Number.isInteger(st) && st >= 1)) {
  559. throw new _util.FormatError("Invalid start in PageLabel dictionary.");
  560. }
  561. currentIndex = st;
  562. } else {
  563. currentIndex = 1;
  564. }
  565. }
  566. switch (style) {
  567. case "D":
  568. currentLabel = currentIndex;
  569. break;
  570. case "R":
  571. case "r":
  572. currentLabel = (0, _core_utils.toRomanNumerals)(currentIndex, style === "r");
  573. break;
  574. case "A":
  575. case "a":
  576. const LIMIT = 26;
  577. const A_UPPER_CASE = 0x41,
  578. A_LOWER_CASE = 0x61;
  579. const baseCharCode = style === "a" ? A_LOWER_CASE : A_UPPER_CASE;
  580. const letterIndex = currentIndex - 1;
  581. const character = String.fromCharCode(baseCharCode + letterIndex % LIMIT);
  582. const charBuf = [];
  583. for (let j = 0, jj = letterIndex / LIMIT | 0; j <= jj; j++) {
  584. charBuf.push(character);
  585. }
  586. currentLabel = charBuf.join("");
  587. break;
  588. default:
  589. if (style) {
  590. throw new _util.FormatError(`Invalid style "${style}" in PageLabel dictionary.`);
  591. }
  592. currentLabel = "";
  593. }
  594. pageLabels[i] = prefix + currentLabel;
  595. currentIndex++;
  596. }
  597. return pageLabels;
  598. }
  599. get pageLayout() {
  600. const obj = this._catDict.get("PageLayout");
  601. let pageLayout = "";
  602. if ((0, _primitives.isName)(obj)) {
  603. switch (obj.name) {
  604. case "SinglePage":
  605. case "OneColumn":
  606. case "TwoColumnLeft":
  607. case "TwoColumnRight":
  608. case "TwoPageLeft":
  609. case "TwoPageRight":
  610. pageLayout = obj.name;
  611. }
  612. }
  613. return (0, _util.shadow)(this, "pageLayout", pageLayout);
  614. }
  615. get pageMode() {
  616. const obj = this._catDict.get("PageMode");
  617. let pageMode = "UseNone";
  618. if ((0, _primitives.isName)(obj)) {
  619. switch (obj.name) {
  620. case "UseNone":
  621. case "UseOutlines":
  622. case "UseThumbs":
  623. case "FullScreen":
  624. case "UseOC":
  625. case "UseAttachments":
  626. pageMode = obj.name;
  627. }
  628. }
  629. return (0, _util.shadow)(this, "pageMode", pageMode);
  630. }
  631. get viewerPreferences() {
  632. const ViewerPreferencesValidators = {
  633. HideToolbar: _util.isBool,
  634. HideMenubar: _util.isBool,
  635. HideWindowUI: _util.isBool,
  636. FitWindow: _util.isBool,
  637. CenterWindow: _util.isBool,
  638. DisplayDocTitle: _util.isBool,
  639. NonFullScreenPageMode: _primitives.isName,
  640. Direction: _primitives.isName,
  641. ViewArea: _primitives.isName,
  642. ViewClip: _primitives.isName,
  643. PrintArea: _primitives.isName,
  644. PrintClip: _primitives.isName,
  645. PrintScaling: _primitives.isName,
  646. Duplex: _primitives.isName,
  647. PickTrayByPDFSize: _util.isBool,
  648. PrintPageRange: Array.isArray,
  649. NumCopies: Number.isInteger
  650. };
  651. const obj = this._catDict.get("ViewerPreferences");
  652. let prefs = null;
  653. if ((0, _primitives.isDict)(obj)) {
  654. for (const key in ViewerPreferencesValidators) {
  655. if (!obj.has(key)) {
  656. continue;
  657. }
  658. const value = obj.get(key);
  659. if (!ViewerPreferencesValidators[key](value)) {
  660. (0, _util.info)(`Bad value in ViewerPreferences for "${key}".`);
  661. continue;
  662. }
  663. let prefValue;
  664. switch (key) {
  665. case "NonFullScreenPageMode":
  666. switch (value.name) {
  667. case "UseNone":
  668. case "UseOutlines":
  669. case "UseThumbs":
  670. case "UseOC":
  671. prefValue = value.name;
  672. break;
  673. default:
  674. prefValue = "UseNone";
  675. }
  676. break;
  677. case "Direction":
  678. switch (value.name) {
  679. case "L2R":
  680. case "R2L":
  681. prefValue = value.name;
  682. break;
  683. default:
  684. prefValue = "L2R";
  685. }
  686. break;
  687. case "ViewArea":
  688. case "ViewClip":
  689. case "PrintArea":
  690. case "PrintClip":
  691. switch (value.name) {
  692. case "MediaBox":
  693. case "CropBox":
  694. case "BleedBox":
  695. case "TrimBox":
  696. case "ArtBox":
  697. prefValue = value.name;
  698. break;
  699. default:
  700. prefValue = "CropBox";
  701. }
  702. break;
  703. case "PrintScaling":
  704. switch (value.name) {
  705. case "None":
  706. case "AppDefault":
  707. prefValue = value.name;
  708. break;
  709. default:
  710. prefValue = "AppDefault";
  711. }
  712. break;
  713. case "Duplex":
  714. switch (value.name) {
  715. case "Simplex":
  716. case "DuplexFlipShortEdge":
  717. case "DuplexFlipLongEdge":
  718. prefValue = value.name;
  719. break;
  720. default:
  721. prefValue = "None";
  722. }
  723. break;
  724. case "PrintPageRange":
  725. const length = value.length;
  726. if (length % 2 !== 0) {
  727. break;
  728. }
  729. const isValid = value.every((page, i, arr) => {
  730. return Number.isInteger(page) && page > 0 && (i === 0 || page >= arr[i - 1]) && page <= this.numPages;
  731. });
  732. if (isValid) {
  733. prefValue = value;
  734. }
  735. break;
  736. case "NumCopies":
  737. if (value > 0) {
  738. prefValue = value;
  739. }
  740. break;
  741. default:
  742. if (typeof value !== "boolean") {
  743. throw new _util.FormatError(`viewerPreferences - expected a boolean value for: ${key}`);
  744. }
  745. prefValue = value;
  746. }
  747. if (prefValue !== undefined) {
  748. if (!prefs) {
  749. prefs = Object.create(null);
  750. }
  751. prefs[key] = prefValue;
  752. } else {
  753. (0, _util.info)(`Bad value in ViewerPreferences for "${key}".`);
  754. }
  755. }
  756. }
  757. return (0, _util.shadow)(this, "viewerPreferences", prefs);
  758. }
  759. get openAction() {
  760. const obj = this._catDict.get("OpenAction");
  761. const openAction = Object.create(null);
  762. if ((0, _primitives.isDict)(obj)) {
  763. const destDict = new _primitives.Dict(this.xref);
  764. destDict.set("A", obj);
  765. const resultObj = {
  766. url: null,
  767. dest: null,
  768. action: null
  769. };
  770. Catalog.parseDestDictionary({
  771. destDict,
  772. resultObj
  773. });
  774. if (Array.isArray(resultObj.dest)) {
  775. openAction.dest = resultObj.dest;
  776. } else if (resultObj.action) {
  777. openAction.action = resultObj.action;
  778. }
  779. } else if (Array.isArray(obj)) {
  780. openAction.dest = obj;
  781. }
  782. return (0, _util.shadow)(this, "openAction", (0, _util.objectSize)(openAction) > 0 ? openAction : null);
  783. }
  784. get attachments() {
  785. const obj = this._catDict.get("Names");
  786. let attachments = null;
  787. if (obj instanceof _primitives.Dict && obj.has("EmbeddedFiles")) {
  788. const nameTree = new _name_number_tree.NameTree(obj.getRaw("EmbeddedFiles"), this.xref);
  789. for (const [key, value] of nameTree.getAll()) {
  790. const fs = new _file_spec.FileSpec(value, this.xref);
  791. if (!attachments) {
  792. attachments = Object.create(null);
  793. }
  794. attachments[(0, _util.stringToPDFString)(key)] = fs.serializable;
  795. }
  796. }
  797. return (0, _util.shadow)(this, "attachments", attachments);
  798. }
  799. get xfaImages() {
  800. const obj = this._catDict.get("Names");
  801. let xfaImages = null;
  802. if (obj instanceof _primitives.Dict && obj.has("XFAImages")) {
  803. const nameTree = new _name_number_tree.NameTree(obj.getRaw("XFAImages"), this.xref);
  804. for (const [key, value] of nameTree.getAll()) {
  805. if (!xfaImages) {
  806. xfaImages = new _primitives.Dict(this.xref);
  807. }
  808. xfaImages.set(key, value);
  809. }
  810. }
  811. return (0, _util.shadow)(this, "xfaImages", xfaImages);
  812. }
  813. _collectJavaScript() {
  814. const obj = this._catDict.get("Names");
  815. let javaScript = null;
  816. function appendIfJavaScriptDict(name, jsDict) {
  817. if (!(jsDict instanceof _primitives.Dict)) {
  818. return;
  819. }
  820. if (!(0, _primitives.isName)(jsDict.get("S"), "JavaScript")) {
  821. return;
  822. }
  823. let js = jsDict.get("JS");
  824. if ((0, _primitives.isStream)(js)) {
  825. js = js.getString();
  826. } else if (typeof js !== "string") {
  827. return;
  828. }
  829. if (javaScript === null) {
  830. javaScript = new Map();
  831. }
  832. javaScript.set(name, (0, _util.stringToPDFString)(js));
  833. }
  834. if (obj instanceof _primitives.Dict && obj.has("JavaScript")) {
  835. const nameTree = new _name_number_tree.NameTree(obj.getRaw("JavaScript"), this.xref);
  836. for (const [key, value] of nameTree.getAll()) {
  837. appendIfJavaScriptDict(key, value);
  838. }
  839. }
  840. const openAction = this._catDict.get("OpenAction");
  841. if (openAction) {
  842. appendIfJavaScriptDict("OpenAction", openAction);
  843. }
  844. return javaScript;
  845. }
  846. get javaScript() {
  847. const javaScript = this._collectJavaScript();
  848. return (0, _util.shadow)(this, "javaScript", javaScript ? [...javaScript.values()] : null);
  849. }
  850. get jsActions() {
  851. const javaScript = this._collectJavaScript();
  852. let actions = (0, _core_utils.collectActions)(this.xref, this._catDict, _util.DocumentActionEventType);
  853. if (javaScript) {
  854. if (!actions) {
  855. actions = Object.create(null);
  856. }
  857. for (const [key, val] of javaScript) {
  858. if (key in actions) {
  859. actions[key].push(val);
  860. } else {
  861. actions[key] = [val];
  862. }
  863. }
  864. }
  865. return (0, _util.shadow)(this, "jsActions", actions);
  866. }
  867. fontFallback(id, handler) {
  868. const promises = [];
  869. this.fontCache.forEach(function (promise) {
  870. promises.push(promise);
  871. });
  872. return Promise.all(promises).then(translatedFonts => {
  873. for (const translatedFont of translatedFonts) {
  874. if (translatedFont.loadedName === id) {
  875. translatedFont.fallback(handler);
  876. return;
  877. }
  878. }
  879. });
  880. }
  881. cleanup(manuallyTriggered = false) {
  882. (0, _primitives.clearPrimitiveCaches)();
  883. this.globalImageCache.clear(manuallyTriggered);
  884. this.pageKidsCountCache.clear();
  885. this.pageIndexCache.clear();
  886. this.nonBlendModesSet.clear();
  887. const promises = [];
  888. this.fontCache.forEach(function (promise) {
  889. promises.push(promise);
  890. });
  891. return Promise.all(promises).then(translatedFonts => {
  892. for (const {
  893. dict
  894. } of translatedFonts) {
  895. delete dict.cacheKey;
  896. }
  897. this.fontCache.clear();
  898. this.builtInCMapCache.clear();
  899. this.standardFontDataCache.clear();
  900. });
  901. }
  902. getPageDict(pageIndex) {
  903. const capability = (0, _util.createPromiseCapability)();
  904. const nodesToVisit = [this.toplevelPagesDict];
  905. const visitedNodes = new _primitives.RefSet();
  906. const pagesRef = this._catDict.getRaw("Pages");
  907. if (pagesRef instanceof _primitives.Ref) {
  908. visitedNodes.put(pagesRef);
  909. }
  910. const xref = this.xref,
  911. pageKidsCountCache = this.pageKidsCountCache;
  912. let currentPageIndex = 0;
  913. function next() {
  914. while (nodesToVisit.length) {
  915. const currentNode = nodesToVisit.pop();
  916. if (currentNode instanceof _primitives.Ref) {
  917. const count = pageKidsCountCache.get(currentNode);
  918. if (count >= 0 && currentPageIndex + count <= pageIndex) {
  919. currentPageIndex += count;
  920. continue;
  921. }
  922. if (visitedNodes.has(currentNode)) {
  923. capability.reject(new _util.FormatError("Pages tree contains circular reference."));
  924. return;
  925. }
  926. visitedNodes.put(currentNode);
  927. xref.fetchAsync(currentNode).then(function (obj) {
  928. if ((0, _primitives.isDict)(obj, "Page") || (0, _primitives.isDict)(obj) && !obj.has("Kids")) {
  929. if (currentNode && !pageKidsCountCache.has(currentNode)) {
  930. pageKidsCountCache.put(currentNode, 1);
  931. }
  932. if (pageIndex === currentPageIndex) {
  933. capability.resolve([obj, currentNode]);
  934. } else {
  935. currentPageIndex++;
  936. next();
  937. }
  938. return;
  939. }
  940. nodesToVisit.push(obj);
  941. next();
  942. }, capability.reject);
  943. return;
  944. }
  945. if (!(currentNode instanceof _primitives.Dict)) {
  946. capability.reject(new _util.FormatError("Page dictionary kid reference points to wrong type of object."));
  947. return;
  948. }
  949. let count;
  950. try {
  951. count = currentNode.get("Count");
  952. } catch (ex) {
  953. if (ex instanceof _core_utils.MissingDataException) {
  954. throw ex;
  955. }
  956. }
  957. if (Number.isInteger(count) && count >= 0) {
  958. const objId = currentNode.objId;
  959. if (objId && !pageKidsCountCache.has(objId)) {
  960. pageKidsCountCache.put(objId, count);
  961. }
  962. if (currentPageIndex + count <= pageIndex) {
  963. currentPageIndex += count;
  964. continue;
  965. }
  966. }
  967. let kids;
  968. try {
  969. kids = currentNode.get("Kids");
  970. } catch (ex) {
  971. if (ex instanceof _core_utils.MissingDataException) {
  972. throw ex;
  973. }
  974. }
  975. if (!Array.isArray(kids)) {
  976. let type;
  977. try {
  978. type = currentNode.get("Type");
  979. } catch (ex) {
  980. if (ex instanceof _core_utils.MissingDataException) {
  981. throw ex;
  982. }
  983. }
  984. if ((0, _primitives.isName)(type, "Page") || !currentNode.has("Type") && currentNode.has("Contents")) {
  985. if (currentPageIndex === pageIndex) {
  986. capability.resolve([currentNode, null]);
  987. return;
  988. }
  989. currentPageIndex++;
  990. continue;
  991. }
  992. capability.reject(new _util.FormatError("Page dictionary kids object is not an array."));
  993. return;
  994. }
  995. for (let last = kids.length - 1; last >= 0; last--) {
  996. nodesToVisit.push(kids[last]);
  997. }
  998. }
  999. capability.reject(new Error(`Page index ${pageIndex} not found.`));
  1000. }
  1001. next();
  1002. return capability.promise;
  1003. }
  1004. getAllPageDicts(recoveryMode = false) {
  1005. const queue = [{
  1006. currentNode: this.toplevelPagesDict,
  1007. posInKids: 0
  1008. }];
  1009. const visitedNodes = new _primitives.RefSet();
  1010. const pagesRef = this._catDict.getRaw("Pages");
  1011. if (pagesRef instanceof _primitives.Ref) {
  1012. visitedNodes.put(pagesRef);
  1013. }
  1014. const map = new Map();
  1015. let pageIndex = 0;
  1016. function addPageDict(pageDict, pageRef) {
  1017. map.set(pageIndex++, [pageDict, pageRef]);
  1018. }
  1019. function addPageError(error) {
  1020. map.set(pageIndex++, [error, null]);
  1021. }
  1022. while (queue.length > 0) {
  1023. const queueItem = queue[queue.length - 1];
  1024. const {
  1025. currentNode,
  1026. posInKids
  1027. } = queueItem;
  1028. let kids;
  1029. try {
  1030. kids = currentNode.get("Kids");
  1031. } catch (ex) {
  1032. if (ex instanceof _core_utils.MissingDataException) {
  1033. throw ex;
  1034. }
  1035. if (ex instanceof _core_utils.XRefEntryException && !recoveryMode) {
  1036. throw ex;
  1037. }
  1038. addPageError(ex);
  1039. break;
  1040. }
  1041. if (!Array.isArray(kids)) {
  1042. addPageError(new _util.FormatError("Page dictionary kids object is not an array."));
  1043. break;
  1044. }
  1045. if (posInKids >= kids.length) {
  1046. queue.pop();
  1047. continue;
  1048. }
  1049. const kidObj = kids[posInKids];
  1050. let obj;
  1051. if (kidObj instanceof _primitives.Ref) {
  1052. try {
  1053. obj = this.xref.fetch(kidObj);
  1054. } catch (ex) {
  1055. if (ex instanceof _core_utils.MissingDataException) {
  1056. throw ex;
  1057. }
  1058. if (ex instanceof _core_utils.XRefEntryException && !recoveryMode) {
  1059. throw ex;
  1060. }
  1061. addPageError(ex);
  1062. break;
  1063. }
  1064. if (visitedNodes.has(kidObj)) {
  1065. addPageError(new _util.FormatError("Pages tree contains circular reference."));
  1066. break;
  1067. }
  1068. visitedNodes.put(kidObj);
  1069. } else {
  1070. obj = kidObj;
  1071. }
  1072. if (!(obj instanceof _primitives.Dict)) {
  1073. addPageError(new _util.FormatError("Page dictionary kid reference points to wrong type of object."));
  1074. break;
  1075. }
  1076. if ((0, _primitives.isDict)(obj, "Page") || !obj.has("Kids")) {
  1077. addPageDict(obj, kidObj instanceof _primitives.Ref ? kidObj : null);
  1078. } else {
  1079. queue.push({
  1080. currentNode: obj,
  1081. posInKids: 0
  1082. });
  1083. }
  1084. queueItem.posInKids++;
  1085. }
  1086. return map;
  1087. }
  1088. getPageIndex(pageRef) {
  1089. const cachedPageIndex = this.pageIndexCache.get(pageRef);
  1090. if (cachedPageIndex !== undefined) {
  1091. return Promise.resolve(cachedPageIndex);
  1092. }
  1093. const xref = this.xref;
  1094. function pagesBeforeRef(kidRef) {
  1095. let total = 0,
  1096. parentRef;
  1097. return xref.fetchAsync(kidRef).then(function (node) {
  1098. if ((0, _primitives.isRefsEqual)(kidRef, pageRef) && !(0, _primitives.isDict)(node, "Page") && !((0, _primitives.isDict)(node) && !node.has("Type") && node.has("Contents"))) {
  1099. throw new _util.FormatError("The reference does not point to a /Page dictionary.");
  1100. }
  1101. if (!node) {
  1102. return null;
  1103. }
  1104. if (!(0, _primitives.isDict)(node)) {
  1105. throw new _util.FormatError("Node must be a dictionary.");
  1106. }
  1107. parentRef = node.getRaw("Parent");
  1108. return node.getAsync("Parent");
  1109. }).then(function (parent) {
  1110. if (!parent) {
  1111. return null;
  1112. }
  1113. if (!(0, _primitives.isDict)(parent)) {
  1114. throw new _util.FormatError("Parent must be a dictionary.");
  1115. }
  1116. return parent.getAsync("Kids");
  1117. }).then(function (kids) {
  1118. if (!kids) {
  1119. return null;
  1120. }
  1121. const kidPromises = [];
  1122. let found = false;
  1123. for (let i = 0, ii = kids.length; i < ii; i++) {
  1124. const kid = kids[i];
  1125. if (!(0, _primitives.isRef)(kid)) {
  1126. throw new _util.FormatError("Kid must be a reference.");
  1127. }
  1128. if ((0, _primitives.isRefsEqual)(kid, kidRef)) {
  1129. found = true;
  1130. break;
  1131. }
  1132. kidPromises.push(xref.fetchAsync(kid).then(function (obj) {
  1133. if (!(0, _primitives.isDict)(obj)) {
  1134. throw new _util.FormatError("Kid node must be a dictionary.");
  1135. }
  1136. if (obj.has("Count")) {
  1137. total += obj.get("Count");
  1138. } else {
  1139. total++;
  1140. }
  1141. }));
  1142. }
  1143. if (!found) {
  1144. throw new _util.FormatError("Kid reference not found in parent's kids.");
  1145. }
  1146. return Promise.all(kidPromises).then(function () {
  1147. return [total, parentRef];
  1148. });
  1149. });
  1150. }
  1151. let total = 0;
  1152. const next = ref => pagesBeforeRef(ref).then(args => {
  1153. if (!args) {
  1154. this.pageIndexCache.put(pageRef, total);
  1155. return total;
  1156. }
  1157. const [count, parentRef] = args;
  1158. total += count;
  1159. return next(parentRef);
  1160. });
  1161. return next(pageRef);
  1162. }
  1163. static parseDestDictionary(params) {
  1164. const destDict = params.destDict;
  1165. if (!(0, _primitives.isDict)(destDict)) {
  1166. (0, _util.warn)("parseDestDictionary: `destDict` must be a dictionary.");
  1167. return;
  1168. }
  1169. const resultObj = params.resultObj;
  1170. if (typeof resultObj !== "object") {
  1171. (0, _util.warn)("parseDestDictionary: `resultObj` must be an object.");
  1172. return;
  1173. }
  1174. const docBaseUrl = params.docBaseUrl || null;
  1175. let action = destDict.get("A"),
  1176. url,
  1177. dest;
  1178. if (!(0, _primitives.isDict)(action)) {
  1179. if (destDict.has("Dest")) {
  1180. action = destDict.get("Dest");
  1181. } else {
  1182. action = destDict.get("AA");
  1183. if ((0, _primitives.isDict)(action)) {
  1184. if (action.has("D")) {
  1185. action = action.get("D");
  1186. } else if (action.has("U")) {
  1187. action = action.get("U");
  1188. }
  1189. }
  1190. }
  1191. }
  1192. if ((0, _primitives.isDict)(action)) {
  1193. const actionType = action.get("S");
  1194. if (!(0, _primitives.isName)(actionType)) {
  1195. (0, _util.warn)("parseDestDictionary: Invalid type in Action dictionary.");
  1196. return;
  1197. }
  1198. const actionName = actionType.name;
  1199. switch (actionName) {
  1200. case "ResetForm":
  1201. const flags = action.get("Flags");
  1202. const include = (((0, _util.isNum)(flags) ? flags : 0) & 1) === 0;
  1203. const fields = [];
  1204. const refs = [];
  1205. for (const obj of action.get("Fields") || []) {
  1206. if ((0, _primitives.isRef)(obj)) {
  1207. refs.push(obj.toString());
  1208. } else if ((0, _util.isString)(obj)) {
  1209. fields.push((0, _util.stringToPDFString)(obj));
  1210. }
  1211. }
  1212. resultObj.resetForm = {
  1213. fields,
  1214. refs,
  1215. include
  1216. };
  1217. break;
  1218. case "URI":
  1219. url = action.get("URI");
  1220. if (url instanceof _primitives.Name) {
  1221. url = "/" + url.name;
  1222. }
  1223. break;
  1224. case "GoTo":
  1225. dest = action.get("D");
  1226. break;
  1227. case "Launch":
  1228. case "GoToR":
  1229. const urlDict = action.get("F");
  1230. if ((0, _primitives.isDict)(urlDict)) {
  1231. url = urlDict.get("F") || null;
  1232. } else if ((0, _util.isString)(urlDict)) {
  1233. url = urlDict;
  1234. }
  1235. let remoteDest = action.get("D");
  1236. if (remoteDest) {
  1237. if ((0, _primitives.isName)(remoteDest)) {
  1238. remoteDest = remoteDest.name;
  1239. }
  1240. if ((0, _util.isString)(url)) {
  1241. const baseUrl = url.split("#")[0];
  1242. if ((0, _util.isString)(remoteDest)) {
  1243. url = baseUrl + "#" + remoteDest;
  1244. } else if (Array.isArray(remoteDest)) {
  1245. url = baseUrl + "#" + JSON.stringify(remoteDest);
  1246. }
  1247. }
  1248. }
  1249. const newWindow = action.get("NewWindow");
  1250. if ((0, _util.isBool)(newWindow)) {
  1251. resultObj.newWindow = newWindow;
  1252. }
  1253. break;
  1254. case "Named":
  1255. const namedAction = action.get("N");
  1256. if ((0, _primitives.isName)(namedAction)) {
  1257. resultObj.action = namedAction.name;
  1258. }
  1259. break;
  1260. case "JavaScript":
  1261. const jsAction = action.get("JS");
  1262. let js;
  1263. if ((0, _primitives.isStream)(jsAction)) {
  1264. js = jsAction.getString();
  1265. } else if ((0, _util.isString)(jsAction)) {
  1266. js = jsAction;
  1267. }
  1268. const jsURL = js && (0, _core_utils.recoverJsURL)((0, _util.stringToPDFString)(js));
  1269. if (jsURL) {
  1270. url = jsURL.url;
  1271. resultObj.newWindow = jsURL.newWindow;
  1272. break;
  1273. }
  1274. default:
  1275. if (actionName === "JavaScript" || actionName === "SubmitForm") {
  1276. break;
  1277. }
  1278. (0, _util.warn)(`parseDestDictionary - unsupported action: "${actionName}".`);
  1279. break;
  1280. }
  1281. } else if (destDict.has("Dest")) {
  1282. dest = destDict.get("Dest");
  1283. }
  1284. if ((0, _util.isString)(url)) {
  1285. const absoluteUrl = (0, _util.createValidAbsoluteUrl)(url, docBaseUrl, {
  1286. addDefaultProtocol: true,
  1287. tryConvertEncoding: true
  1288. });
  1289. if (absoluteUrl) {
  1290. resultObj.url = absoluteUrl.href;
  1291. }
  1292. resultObj.unsafeUrl = url;
  1293. }
  1294. if (dest) {
  1295. if ((0, _primitives.isName)(dest)) {
  1296. dest = dest.name;
  1297. }
  1298. if ((0, _util.isString)(dest) || Array.isArray(dest)) {
  1299. resultObj.dest = dest;
  1300. }
  1301. }
  1302. }
  1303. }
  1304. exports.Catalog = Catalog;