2
0

parser.js 31 KB

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