2
0

parser.js 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990
  1. /**
  2. * @licstart The following is the entire license notice for the
  3. * Javascript code in this page
  4. *
  5. * Copyright 2017 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.Parser = exports.Linearization = exports.Lexer = undefined;
  27. var _stream = require('./stream');
  28. var _util = require('../shared/util');
  29. var _primitives = require('./primitives');
  30. var _ccitt_stream = require('./ccitt_stream');
  31. var _jbig2_stream = require('./jbig2_stream');
  32. var _jpeg_stream = require('./jpeg_stream');
  33. var _jpx_stream = require('./jpx_stream');
  34. var MAX_LENGTH_TO_CACHE = 1000;
  35. var Parser = function ParserClosure() {
  36. function Parser(lexer, allowStreams, xref, recoveryMode) {
  37. this.lexer = lexer;
  38. this.allowStreams = allowStreams;
  39. this.xref = xref;
  40. this.recoveryMode = recoveryMode || false;
  41. this.imageCache = Object.create(null);
  42. this.refill();
  43. }
  44. Parser.prototype = {
  45. refill: function Parser_refill() {
  46. this.buf1 = this.lexer.getObj();
  47. this.buf2 = this.lexer.getObj();
  48. },
  49. shift: function Parser_shift() {
  50. if ((0, _primitives.isCmd)(this.buf2, 'ID')) {
  51. this.buf1 = this.buf2;
  52. this.buf2 = null;
  53. } else {
  54. this.buf1 = this.buf2;
  55. this.buf2 = this.lexer.getObj();
  56. }
  57. },
  58. tryShift: function Parser_tryShift() {
  59. try {
  60. this.shift();
  61. return true;
  62. } catch (e) {
  63. if (e instanceof _util.MissingDataException) {
  64. throw e;
  65. }
  66. return false;
  67. }
  68. },
  69. getObj: function Parser_getObj(cipherTransform) {
  70. var buf1 = this.buf1;
  71. this.shift();
  72. if (buf1 instanceof _primitives.Cmd) {
  73. switch (buf1.cmd) {
  74. case 'BI':
  75. return this.makeInlineImage(cipherTransform);
  76. case '[':
  77. var array = [];
  78. while (!(0, _primitives.isCmd)(this.buf1, ']') && !(0, _primitives.isEOF)(this.buf1)) {
  79. array.push(this.getObj(cipherTransform));
  80. }
  81. if ((0, _primitives.isEOF)(this.buf1)) {
  82. if (!this.recoveryMode) {
  83. throw new _util.FormatError('End of file inside array');
  84. }
  85. return array;
  86. }
  87. this.shift();
  88. return array;
  89. case '<<':
  90. var dict = new _primitives.Dict(this.xref);
  91. while (!(0, _primitives.isCmd)(this.buf1, '>>') && !(0, _primitives.isEOF)(this.buf1)) {
  92. if (!(0, _primitives.isName)(this.buf1)) {
  93. (0, _util.info)('Malformed dictionary: key must be a name object');
  94. this.shift();
  95. continue;
  96. }
  97. var key = this.buf1.name;
  98. this.shift();
  99. if ((0, _primitives.isEOF)(this.buf1)) {
  100. break;
  101. }
  102. dict.set(key, this.getObj(cipherTransform));
  103. }
  104. if ((0, _primitives.isEOF)(this.buf1)) {
  105. if (!this.recoveryMode) {
  106. throw new _util.FormatError('End of file inside dictionary');
  107. }
  108. return dict;
  109. }
  110. if ((0, _primitives.isCmd)(this.buf2, 'stream')) {
  111. return this.allowStreams ? this.makeStream(dict, cipherTransform) : dict;
  112. }
  113. this.shift();
  114. return dict;
  115. default:
  116. return buf1;
  117. }
  118. }
  119. if (Number.isInteger(buf1)) {
  120. var num = buf1;
  121. if (Number.isInteger(this.buf1) && (0, _primitives.isCmd)(this.buf2, 'R')) {
  122. var ref = new _primitives.Ref(num, this.buf1);
  123. this.shift();
  124. this.shift();
  125. return ref;
  126. }
  127. return num;
  128. }
  129. if ((0, _util.isString)(buf1)) {
  130. var str = buf1;
  131. if (cipherTransform) {
  132. str = cipherTransform.decryptString(str);
  133. }
  134. return str;
  135. }
  136. return buf1;
  137. },
  138. findDefaultInlineStreamEnd: function findDefaultInlineStreamEnd(stream) {
  139. var E = 0x45,
  140. I = 0x49,
  141. SPACE = 0x20,
  142. LF = 0xA,
  143. CR = 0xD;
  144. var n = 10,
  145. NUL = 0x0;
  146. var startPos = stream.pos,
  147. state = 0,
  148. ch = void 0,
  149. maybeEIPos = void 0;
  150. while ((ch = stream.getByte()) !== -1) {
  151. if (state === 0) {
  152. state = ch === E ? 1 : 0;
  153. } else if (state === 1) {
  154. state = ch === I ? 2 : 0;
  155. } else {
  156. (0, _util.assert)(state === 2);
  157. if (ch === SPACE || ch === LF || ch === CR) {
  158. maybeEIPos = stream.pos;
  159. var followingBytes = stream.peekBytes(n);
  160. for (var i = 0, ii = followingBytes.length; i < ii; i++) {
  161. ch = followingBytes[i];
  162. if (ch === NUL && followingBytes[i + 1] !== NUL) {
  163. continue;
  164. }
  165. if (ch !== LF && ch !== CR && (ch < SPACE || ch > 0x7F)) {
  166. state = 0;
  167. break;
  168. }
  169. }
  170. if (state === 2) {
  171. break;
  172. }
  173. } else {
  174. state = 0;
  175. }
  176. }
  177. }
  178. if (ch === -1) {
  179. (0, _util.warn)('findDefaultInlineStreamEnd: ' + 'Reached the end of the stream without finding a valid EI marker');
  180. if (maybeEIPos) {
  181. (0, _util.warn)('... trying to recover by using the last "EI" occurrence.');
  182. stream.skip(-(stream.pos - maybeEIPos));
  183. }
  184. }
  185. return stream.pos - 4 - startPos;
  186. },
  187. findDCTDecodeInlineStreamEnd: function Parser_findDCTDecodeInlineStreamEnd(stream) {
  188. var startPos = stream.pos,
  189. foundEOI = false,
  190. b,
  191. markerLength,
  192. length;
  193. while ((b = stream.getByte()) !== -1) {
  194. if (b !== 0xFF) {
  195. continue;
  196. }
  197. switch (stream.getByte()) {
  198. case 0x00:
  199. break;
  200. case 0xFF:
  201. stream.skip(-1);
  202. break;
  203. case 0xD9:
  204. foundEOI = true;
  205. break;
  206. case 0xC0:
  207. case 0xC1:
  208. case 0xC2:
  209. case 0xC3:
  210. case 0xC5:
  211. case 0xC6:
  212. case 0xC7:
  213. case 0xC9:
  214. case 0xCA:
  215. case 0xCB:
  216. case 0xCD:
  217. case 0xCE:
  218. case 0xCF:
  219. case 0xC4:
  220. case 0xCC:
  221. case 0xDA:
  222. case 0xDB:
  223. case 0xDC:
  224. case 0xDD:
  225. case 0xDE:
  226. case 0xDF:
  227. case 0xE0:
  228. case 0xE1:
  229. case 0xE2:
  230. case 0xE3:
  231. case 0xE4:
  232. case 0xE5:
  233. case 0xE6:
  234. case 0xE7:
  235. case 0xE8:
  236. case 0xE9:
  237. case 0xEA:
  238. case 0xEB:
  239. case 0xEC:
  240. case 0xED:
  241. case 0xEE:
  242. case 0xEF:
  243. case 0xFE:
  244. markerLength = stream.getUint16();
  245. if (markerLength > 2) {
  246. stream.skip(markerLength - 2);
  247. } else {
  248. stream.skip(-2);
  249. }
  250. break;
  251. }
  252. if (foundEOI) {
  253. break;
  254. }
  255. }
  256. length = stream.pos - startPos;
  257. if (b === -1) {
  258. (0, _util.warn)('Inline DCTDecode image stream: ' + 'EOI marker not found, searching for /EI/ instead.');
  259. stream.skip(-length);
  260. return this.findDefaultInlineStreamEnd(stream);
  261. }
  262. this.inlineStreamSkipEI(stream);
  263. return length;
  264. },
  265. findASCII85DecodeInlineStreamEnd: function Parser_findASCII85DecodeInlineStreamEnd(stream) {
  266. var TILDE = 0x7E,
  267. GT = 0x3E;
  268. var startPos = stream.pos,
  269. ch,
  270. length;
  271. while ((ch = stream.getByte()) !== -1) {
  272. if (ch === TILDE && stream.peekByte() === GT) {
  273. stream.skip();
  274. break;
  275. }
  276. }
  277. length = stream.pos - startPos;
  278. if (ch === -1) {
  279. (0, _util.warn)('Inline ASCII85Decode image stream: ' + 'EOD marker not found, searching for /EI/ instead.');
  280. stream.skip(-length);
  281. return this.findDefaultInlineStreamEnd(stream);
  282. }
  283. this.inlineStreamSkipEI(stream);
  284. return length;
  285. },
  286. findASCIIHexDecodeInlineStreamEnd: function Parser_findASCIIHexDecodeInlineStreamEnd(stream) {
  287. var GT = 0x3E;
  288. var startPos = stream.pos,
  289. ch,
  290. length;
  291. while ((ch = stream.getByte()) !== -1) {
  292. if (ch === GT) {
  293. break;
  294. }
  295. }
  296. length = stream.pos - startPos;
  297. if (ch === -1) {
  298. (0, _util.warn)('Inline ASCIIHexDecode image stream: ' + 'EOD marker not found, searching for /EI/ instead.');
  299. stream.skip(-length);
  300. return this.findDefaultInlineStreamEnd(stream);
  301. }
  302. this.inlineStreamSkipEI(stream);
  303. return length;
  304. },
  305. inlineStreamSkipEI: function Parser_inlineStreamSkipEI(stream) {
  306. var E = 0x45,
  307. I = 0x49;
  308. var state = 0,
  309. ch;
  310. while ((ch = stream.getByte()) !== -1) {
  311. if (state === 0) {
  312. state = ch === E ? 1 : 0;
  313. } else if (state === 1) {
  314. state = ch === I ? 2 : 0;
  315. } else if (state === 2) {
  316. break;
  317. }
  318. }
  319. },
  320. makeInlineImage: function Parser_makeInlineImage(cipherTransform) {
  321. var lexer = this.lexer;
  322. var stream = lexer.stream;
  323. var dict = new _primitives.Dict(this.xref);
  324. while (!(0, _primitives.isCmd)(this.buf1, 'ID') && !(0, _primitives.isEOF)(this.buf1)) {
  325. if (!(0, _primitives.isName)(this.buf1)) {
  326. throw new _util.FormatError('Dictionary key must be a name object');
  327. }
  328. var key = this.buf1.name;
  329. this.shift();
  330. if ((0, _primitives.isEOF)(this.buf1)) {
  331. break;
  332. }
  333. dict.set(key, this.getObj(cipherTransform));
  334. }
  335. var filter = dict.get('Filter', 'F'),
  336. filterName;
  337. if ((0, _primitives.isName)(filter)) {
  338. filterName = filter.name;
  339. } else if (Array.isArray(filter)) {
  340. var filterZero = this.xref.fetchIfRef(filter[0]);
  341. if ((0, _primitives.isName)(filterZero)) {
  342. filterName = filterZero.name;
  343. }
  344. }
  345. var startPos = stream.pos,
  346. length,
  347. i,
  348. ii;
  349. if (filterName === 'DCTDecode' || filterName === 'DCT') {
  350. length = this.findDCTDecodeInlineStreamEnd(stream);
  351. } else if (filterName === 'ASCII85Decode' || filterName === 'A85') {
  352. length = this.findASCII85DecodeInlineStreamEnd(stream);
  353. } else if (filterName === 'ASCIIHexDecode' || filterName === 'AHx') {
  354. length = this.findASCIIHexDecodeInlineStreamEnd(stream);
  355. } else {
  356. length = this.findDefaultInlineStreamEnd(stream);
  357. }
  358. var imageStream = stream.makeSubStream(startPos, length, dict);
  359. var adler32;
  360. if (length < MAX_LENGTH_TO_CACHE) {
  361. var imageBytes = imageStream.getBytes();
  362. imageStream.reset();
  363. var a = 1;
  364. var b = 0;
  365. for (i = 0, ii = imageBytes.length; i < ii; ++i) {
  366. a += imageBytes[i] & 0xff;
  367. b += a;
  368. }
  369. adler32 = b % 65521 << 16 | a % 65521;
  370. var cacheEntry = this.imageCache[adler32];
  371. if (cacheEntry !== undefined) {
  372. this.buf2 = _primitives.Cmd.get('EI');
  373. this.shift();
  374. cacheEntry.reset();
  375. return cacheEntry;
  376. }
  377. }
  378. if (cipherTransform) {
  379. imageStream = cipherTransform.createStream(imageStream, length);
  380. }
  381. imageStream = this.filter(imageStream, dict, length);
  382. imageStream.dict = dict;
  383. if (adler32 !== undefined) {
  384. imageStream.cacheKey = 'inline_' + length + '_' + adler32;
  385. this.imageCache[adler32] = imageStream;
  386. }
  387. this.buf2 = _primitives.Cmd.get('EI');
  388. this.shift();
  389. return imageStream;
  390. },
  391. makeStream: function Parser_makeStream(dict, cipherTransform) {
  392. var lexer = this.lexer;
  393. var stream = lexer.stream;
  394. lexer.skipToNextLine();
  395. var pos = stream.pos - 1;
  396. var length = dict.get('Length');
  397. if (!Number.isInteger(length)) {
  398. (0, _util.info)('Bad ' + length + ' attribute in stream');
  399. length = 0;
  400. }
  401. stream.pos = pos + length;
  402. lexer.nextChar();
  403. if (this.tryShift() && (0, _primitives.isCmd)(this.buf2, 'endstream')) {
  404. this.shift();
  405. } else {
  406. stream.pos = pos;
  407. var SCAN_BLOCK_SIZE = 2048;
  408. var ENDSTREAM_SIGNATURE_LENGTH = 9;
  409. var ENDSTREAM_SIGNATURE = [0x65, 0x6E, 0x64, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6D];
  410. var skipped = 0,
  411. found = false,
  412. i,
  413. j;
  414. while (stream.pos < stream.end) {
  415. var scanBytes = stream.peekBytes(SCAN_BLOCK_SIZE);
  416. var scanLength = scanBytes.length - ENDSTREAM_SIGNATURE_LENGTH;
  417. if (scanLength <= 0) {
  418. break;
  419. }
  420. found = false;
  421. i = 0;
  422. while (i < scanLength) {
  423. j = 0;
  424. while (j < ENDSTREAM_SIGNATURE_LENGTH && scanBytes[i + j] === ENDSTREAM_SIGNATURE[j]) {
  425. j++;
  426. }
  427. if (j >= ENDSTREAM_SIGNATURE_LENGTH) {
  428. found = true;
  429. break;
  430. }
  431. i++;
  432. }
  433. if (found) {
  434. skipped += i;
  435. stream.pos += i;
  436. break;
  437. }
  438. skipped += scanLength;
  439. stream.pos += scanLength;
  440. }
  441. if (!found) {
  442. throw new _util.FormatError('Missing endstream');
  443. }
  444. length = skipped;
  445. lexer.nextChar();
  446. this.shift();
  447. this.shift();
  448. }
  449. this.shift();
  450. stream = stream.makeSubStream(pos, length, dict);
  451. if (cipherTransform) {
  452. stream = cipherTransform.createStream(stream, length);
  453. }
  454. stream = this.filter(stream, dict, length);
  455. stream.dict = dict;
  456. return stream;
  457. },
  458. filter: function Parser_filter(stream, dict, length) {
  459. var filter = dict.get('Filter', 'F');
  460. var params = dict.get('DecodeParms', 'DP');
  461. if ((0, _primitives.isName)(filter)) {
  462. if (Array.isArray(params)) {
  463. (0, _util.warn)('/DecodeParms should not contain an Array, ' + 'when /Filter contains a Name.');
  464. }
  465. return this.makeFilter(stream, filter.name, length, params);
  466. }
  467. var maybeLength = length;
  468. if (Array.isArray(filter)) {
  469. var filterArray = filter;
  470. var paramsArray = params;
  471. for (var i = 0, ii = filterArray.length; i < ii; ++i) {
  472. filter = this.xref.fetchIfRef(filterArray[i]);
  473. if (!(0, _primitives.isName)(filter)) {
  474. throw new _util.FormatError('Bad filter name: ' + filter);
  475. }
  476. params = null;
  477. if (Array.isArray(paramsArray) && i in paramsArray) {
  478. params = this.xref.fetchIfRef(paramsArray[i]);
  479. }
  480. stream = this.makeFilter(stream, filter.name, maybeLength, params);
  481. maybeLength = null;
  482. }
  483. }
  484. return stream;
  485. },
  486. makeFilter: function Parser_makeFilter(stream, name, maybeLength, params) {
  487. if (maybeLength === 0) {
  488. (0, _util.warn)('Empty "' + name + '" stream.');
  489. return new _stream.NullStream();
  490. }
  491. try {
  492. var xrefStreamStats = this.xref.stats.streamTypes;
  493. if (name === 'FlateDecode' || name === 'Fl') {
  494. xrefStreamStats[_util.StreamType.FLATE] = true;
  495. if (params) {
  496. return new _stream.PredictorStream(new _stream.FlateStream(stream, maybeLength), maybeLength, params);
  497. }
  498. return new _stream.FlateStream(stream, maybeLength);
  499. }
  500. if (name === 'LZWDecode' || name === 'LZW') {
  501. xrefStreamStats[_util.StreamType.LZW] = true;
  502. var earlyChange = 1;
  503. if (params) {
  504. if (params.has('EarlyChange')) {
  505. earlyChange = params.get('EarlyChange');
  506. }
  507. return new _stream.PredictorStream(new _stream.LZWStream(stream, maybeLength, earlyChange), maybeLength, params);
  508. }
  509. return new _stream.LZWStream(stream, maybeLength, earlyChange);
  510. }
  511. if (name === 'DCTDecode' || name === 'DCT') {
  512. xrefStreamStats[_util.StreamType.DCT] = true;
  513. return new _jpeg_stream.JpegStream(stream, maybeLength, stream.dict, params);
  514. }
  515. if (name === 'JPXDecode' || name === 'JPX') {
  516. xrefStreamStats[_util.StreamType.JPX] = true;
  517. return new _jpx_stream.JpxStream(stream, maybeLength, stream.dict, params);
  518. }
  519. if (name === 'ASCII85Decode' || name === 'A85') {
  520. xrefStreamStats[_util.StreamType.A85] = true;
  521. return new _stream.Ascii85Stream(stream, maybeLength);
  522. }
  523. if (name === 'ASCIIHexDecode' || name === 'AHx') {
  524. xrefStreamStats[_util.StreamType.AHX] = true;
  525. return new _stream.AsciiHexStream(stream, maybeLength);
  526. }
  527. if (name === 'CCITTFaxDecode' || name === 'CCF') {
  528. xrefStreamStats[_util.StreamType.CCF] = true;
  529. return new _ccitt_stream.CCITTFaxStream(stream, maybeLength, params);
  530. }
  531. if (name === 'RunLengthDecode' || name === 'RL') {
  532. xrefStreamStats[_util.StreamType.RL] = true;
  533. return new _stream.RunLengthStream(stream, maybeLength);
  534. }
  535. if (name === 'JBIG2Decode') {
  536. xrefStreamStats[_util.StreamType.JBIG] = true;
  537. return new _jbig2_stream.Jbig2Stream(stream, maybeLength, stream.dict, params);
  538. }
  539. (0, _util.warn)('filter "' + name + '" not supported yet');
  540. return stream;
  541. } catch (ex) {
  542. if (ex instanceof _util.MissingDataException) {
  543. throw ex;
  544. }
  545. (0, _util.warn)('Invalid stream: \"' + ex + '\"');
  546. return new _stream.NullStream();
  547. }
  548. }
  549. };
  550. return Parser;
  551. }();
  552. var Lexer = function LexerClosure() {
  553. function Lexer(stream, knownCommands) {
  554. this.stream = stream;
  555. this.nextChar();
  556. this.strBuf = [];
  557. this.knownCommands = knownCommands;
  558. }
  559. var specialChars = [1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
  560. function toHexDigit(ch) {
  561. if (ch >= 0x30 && ch <= 0x39) {
  562. return ch & 0x0F;
  563. }
  564. if (ch >= 0x41 && ch <= 0x46 || ch >= 0x61 && ch <= 0x66) {
  565. return (ch & 0x0F) + 9;
  566. }
  567. return -1;
  568. }
  569. Lexer.prototype = {
  570. nextChar: function Lexer_nextChar() {
  571. return this.currentChar = this.stream.getByte();
  572. },
  573. peekChar: function Lexer_peekChar() {
  574. return this.stream.peekByte();
  575. },
  576. getNumber: function Lexer_getNumber() {
  577. var ch = this.currentChar;
  578. var eNotation = false;
  579. var divideBy = 0;
  580. var sign = 1;
  581. if (ch === 0x2D) {
  582. sign = -1;
  583. ch = this.nextChar();
  584. if (ch === 0x2D) {
  585. ch = this.nextChar();
  586. }
  587. } else if (ch === 0x2B) {
  588. ch = this.nextChar();
  589. }
  590. if (ch === 0x2E) {
  591. divideBy = 10;
  592. ch = this.nextChar();
  593. }
  594. if (ch === 0x0A || ch === 0x0D) {
  595. do {
  596. ch = this.nextChar();
  597. } while (ch === 0x0A || ch === 0x0D);
  598. }
  599. if (ch < 0x30 || ch > 0x39) {
  600. throw new _util.FormatError('Invalid number: ' + String.fromCharCode(ch) + ' (charCode ' + ch + ')');
  601. }
  602. var baseValue = ch - 0x30;
  603. var powerValue = 0;
  604. var powerValueSign = 1;
  605. while ((ch = this.nextChar()) >= 0) {
  606. if (0x30 <= ch && ch <= 0x39) {
  607. var currentDigit = ch - 0x30;
  608. if (eNotation) {
  609. powerValue = powerValue * 10 + currentDigit;
  610. } else {
  611. if (divideBy !== 0) {
  612. divideBy *= 10;
  613. }
  614. baseValue = baseValue * 10 + currentDigit;
  615. }
  616. } else if (ch === 0x2E) {
  617. if (divideBy === 0) {
  618. divideBy = 1;
  619. } else {
  620. break;
  621. }
  622. } else if (ch === 0x2D) {
  623. (0, _util.warn)('Badly formatted number');
  624. } else if (ch === 0x45 || ch === 0x65) {
  625. ch = this.peekChar();
  626. if (ch === 0x2B || ch === 0x2D) {
  627. powerValueSign = ch === 0x2D ? -1 : 1;
  628. this.nextChar();
  629. } else if (ch < 0x30 || ch > 0x39) {
  630. break;
  631. }
  632. eNotation = true;
  633. } else {
  634. break;
  635. }
  636. }
  637. if (divideBy !== 0) {
  638. baseValue /= divideBy;
  639. }
  640. if (eNotation) {
  641. baseValue *= Math.pow(10, powerValueSign * powerValue);
  642. }
  643. return sign * baseValue;
  644. },
  645. getString: function Lexer_getString() {
  646. var numParen = 1;
  647. var done = false;
  648. var strBuf = this.strBuf;
  649. strBuf.length = 0;
  650. var ch = this.nextChar();
  651. while (true) {
  652. var charBuffered = false;
  653. switch (ch | 0) {
  654. case -1:
  655. (0, _util.warn)('Unterminated string');
  656. done = true;
  657. break;
  658. case 0x28:
  659. ++numParen;
  660. strBuf.push('(');
  661. break;
  662. case 0x29:
  663. if (--numParen === 0) {
  664. this.nextChar();
  665. done = true;
  666. } else {
  667. strBuf.push(')');
  668. }
  669. break;
  670. case 0x5C:
  671. ch = this.nextChar();
  672. switch (ch) {
  673. case -1:
  674. (0, _util.warn)('Unterminated string');
  675. done = true;
  676. break;
  677. case 0x6E:
  678. strBuf.push('\n');
  679. break;
  680. case 0x72:
  681. strBuf.push('\r');
  682. break;
  683. case 0x74:
  684. strBuf.push('\t');
  685. break;
  686. case 0x62:
  687. strBuf.push('\b');
  688. break;
  689. case 0x66:
  690. strBuf.push('\f');
  691. break;
  692. case 0x5C:
  693. case 0x28:
  694. case 0x29:
  695. strBuf.push(String.fromCharCode(ch));
  696. break;
  697. case 0x30:
  698. case 0x31:
  699. case 0x32:
  700. case 0x33:
  701. case 0x34:
  702. case 0x35:
  703. case 0x36:
  704. case 0x37:
  705. var x = ch & 0x0F;
  706. ch = this.nextChar();
  707. charBuffered = true;
  708. if (ch >= 0x30 && ch <= 0x37) {
  709. x = (x << 3) + (ch & 0x0F);
  710. ch = this.nextChar();
  711. if (ch >= 0x30 && ch <= 0x37) {
  712. charBuffered = false;
  713. x = (x << 3) + (ch & 0x0F);
  714. }
  715. }
  716. strBuf.push(String.fromCharCode(x));
  717. break;
  718. case 0x0D:
  719. if (this.peekChar() === 0x0A) {
  720. this.nextChar();
  721. }
  722. break;
  723. case 0x0A:
  724. break;
  725. default:
  726. strBuf.push(String.fromCharCode(ch));
  727. break;
  728. }
  729. break;
  730. default:
  731. strBuf.push(String.fromCharCode(ch));
  732. break;
  733. }
  734. if (done) {
  735. break;
  736. }
  737. if (!charBuffered) {
  738. ch = this.nextChar();
  739. }
  740. }
  741. return strBuf.join('');
  742. },
  743. getName: function Lexer_getName() {
  744. var ch, previousCh;
  745. var strBuf = this.strBuf;
  746. strBuf.length = 0;
  747. while ((ch = this.nextChar()) >= 0 && !specialChars[ch]) {
  748. if (ch === 0x23) {
  749. ch = this.nextChar();
  750. if (specialChars[ch]) {
  751. (0, _util.warn)('Lexer_getName: ' + 'NUMBER SIGN (#) should be followed by a hexadecimal number.');
  752. strBuf.push('#');
  753. break;
  754. }
  755. var x = toHexDigit(ch);
  756. if (x !== -1) {
  757. previousCh = ch;
  758. ch = this.nextChar();
  759. var x2 = toHexDigit(ch);
  760. if (x2 === -1) {
  761. (0, _util.warn)('Lexer_getName: Illegal digit (' + String.fromCharCode(ch) + ') in hexadecimal number.');
  762. strBuf.push('#', String.fromCharCode(previousCh));
  763. if (specialChars[ch]) {
  764. break;
  765. }
  766. strBuf.push(String.fromCharCode(ch));
  767. continue;
  768. }
  769. strBuf.push(String.fromCharCode(x << 4 | x2));
  770. } else {
  771. strBuf.push('#', String.fromCharCode(ch));
  772. }
  773. } else {
  774. strBuf.push(String.fromCharCode(ch));
  775. }
  776. }
  777. if (strBuf.length > 127) {
  778. (0, _util.warn)('name token is longer than allowed by the spec: ' + strBuf.length);
  779. }
  780. return _primitives.Name.get(strBuf.join(''));
  781. },
  782. getHexString: function Lexer_getHexString() {
  783. var strBuf = this.strBuf;
  784. strBuf.length = 0;
  785. var ch = this.currentChar;
  786. var isFirstHex = true;
  787. var firstDigit;
  788. var secondDigit;
  789. while (true) {
  790. if (ch < 0) {
  791. (0, _util.warn)('Unterminated hex string');
  792. break;
  793. } else if (ch === 0x3E) {
  794. this.nextChar();
  795. break;
  796. } else if (specialChars[ch] === 1) {
  797. ch = this.nextChar();
  798. continue;
  799. } else {
  800. if (isFirstHex) {
  801. firstDigit = toHexDigit(ch);
  802. if (firstDigit === -1) {
  803. (0, _util.warn)('Ignoring invalid character "' + ch + '" in hex string');
  804. ch = this.nextChar();
  805. continue;
  806. }
  807. } else {
  808. secondDigit = toHexDigit(ch);
  809. if (secondDigit === -1) {
  810. (0, _util.warn)('Ignoring invalid character "' + ch + '" in hex string');
  811. ch = this.nextChar();
  812. continue;
  813. }
  814. strBuf.push(String.fromCharCode(firstDigit << 4 | secondDigit));
  815. }
  816. isFirstHex = !isFirstHex;
  817. ch = this.nextChar();
  818. }
  819. }
  820. return strBuf.join('');
  821. },
  822. getObj: function Lexer_getObj() {
  823. var comment = false;
  824. var ch = this.currentChar;
  825. while (true) {
  826. if (ch < 0) {
  827. return _primitives.EOF;
  828. }
  829. if (comment) {
  830. if (ch === 0x0A || ch === 0x0D) {
  831. comment = false;
  832. }
  833. } else if (ch === 0x25) {
  834. comment = true;
  835. } else if (specialChars[ch] !== 1) {
  836. break;
  837. }
  838. ch = this.nextChar();
  839. }
  840. switch (ch | 0) {
  841. case 0x30:
  842. case 0x31:
  843. case 0x32:
  844. case 0x33:
  845. case 0x34:
  846. case 0x35:
  847. case 0x36:
  848. case 0x37:
  849. case 0x38:
  850. case 0x39:
  851. case 0x2B:
  852. case 0x2D:
  853. case 0x2E:
  854. return this.getNumber();
  855. case 0x28:
  856. return this.getString();
  857. case 0x2F:
  858. return this.getName();
  859. case 0x5B:
  860. this.nextChar();
  861. return _primitives.Cmd.get('[');
  862. case 0x5D:
  863. this.nextChar();
  864. return _primitives.Cmd.get(']');
  865. case 0x3C:
  866. ch = this.nextChar();
  867. if (ch === 0x3C) {
  868. this.nextChar();
  869. return _primitives.Cmd.get('<<');
  870. }
  871. return this.getHexString();
  872. case 0x3E:
  873. ch = this.nextChar();
  874. if (ch === 0x3E) {
  875. this.nextChar();
  876. return _primitives.Cmd.get('>>');
  877. }
  878. return _primitives.Cmd.get('>');
  879. case 0x7B:
  880. this.nextChar();
  881. return _primitives.Cmd.get('{');
  882. case 0x7D:
  883. this.nextChar();
  884. return _primitives.Cmd.get('}');
  885. case 0x29:
  886. this.nextChar();
  887. throw new _util.FormatError('Illegal character: ' + ch);
  888. }
  889. var str = String.fromCharCode(ch);
  890. var knownCommands = this.knownCommands;
  891. var knownCommandFound = knownCommands && knownCommands[str] !== undefined;
  892. while ((ch = this.nextChar()) >= 0 && !specialChars[ch]) {
  893. var possibleCommand = str + String.fromCharCode(ch);
  894. if (knownCommandFound && knownCommands[possibleCommand] === undefined) {
  895. break;
  896. }
  897. if (str.length === 128) {
  898. throw new _util.FormatError('Command token too long: ' + str.length);
  899. }
  900. str = possibleCommand;
  901. knownCommandFound = knownCommands && knownCommands[str] !== undefined;
  902. }
  903. if (str === 'true') {
  904. return true;
  905. }
  906. if (str === 'false') {
  907. return false;
  908. }
  909. if (str === 'null') {
  910. return null;
  911. }
  912. return _primitives.Cmd.get(str);
  913. },
  914. skipToNextLine: function Lexer_skipToNextLine() {
  915. var ch = this.currentChar;
  916. while (ch >= 0) {
  917. if (ch === 0x0D) {
  918. ch = this.nextChar();
  919. if (ch === 0x0A) {
  920. this.nextChar();
  921. }
  922. break;
  923. } else if (ch === 0x0A) {
  924. this.nextChar();
  925. break;
  926. }
  927. ch = this.nextChar();
  928. }
  929. }
  930. };
  931. return Lexer;
  932. }();
  933. var Linearization = {
  934. create: function LinearizationCreate(stream) {
  935. function getInt(name, allowZeroValue) {
  936. var obj = linDict.get(name);
  937. if (Number.isInteger(obj) && (allowZeroValue ? obj >= 0 : obj > 0)) {
  938. return obj;
  939. }
  940. throw new Error('The "' + name + '" parameter in the linearization ' + 'dictionary is invalid.');
  941. }
  942. function getHints() {
  943. var hints = linDict.get('H'),
  944. hintsLength,
  945. item;
  946. if (Array.isArray(hints) && ((hintsLength = hints.length) === 2 || hintsLength === 4)) {
  947. for (var index = 0; index < hintsLength; index++) {
  948. if (!(Number.isInteger(item = hints[index]) && item > 0)) {
  949. throw new Error('Hint (' + index + ') in the linearization dictionary is invalid.');
  950. }
  951. }
  952. return hints;
  953. }
  954. throw new Error('Hint array in the linearization dictionary is invalid.');
  955. }
  956. var parser = new Parser(new Lexer(stream), false, null);
  957. var obj1 = parser.getObj();
  958. var obj2 = parser.getObj();
  959. var obj3 = parser.getObj();
  960. var linDict = parser.getObj();
  961. var obj, length;
  962. if (!(Number.isInteger(obj1) && Number.isInteger(obj2) && (0, _primitives.isCmd)(obj3, 'obj') && (0, _primitives.isDict)(linDict) && (0, _util.isNum)(obj = linDict.get('Linearized')) && obj > 0)) {
  963. return null;
  964. } else if ((length = getInt('L')) !== stream.length) {
  965. throw new Error('The "L" parameter in the linearization dictionary ' + 'does not equal the stream length.');
  966. }
  967. return {
  968. length: length,
  969. hints: getHints(),
  970. objectNumberFirst: getInt('O'),
  971. endFirst: getInt('E'),
  972. numPages: getInt('N'),
  973. mainXRefEntriesOffset: getInt('T'),
  974. pageFirst: linDict.has('P') ? getInt('P', true) : 0
  975. };
  976. }
  977. };
  978. exports.Lexer = Lexer;
  979. exports.Linearization = Linearization;
  980. exports.Parser = Parser;