cairo-script-file.c 22 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109
  1. /*
  2. * Copyright © 2008 Chris Wilson <chris@chris-wilson.co.uk>
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it either under the terms of the GNU Lesser General Public
  6. * License version 2.1 as published by the Free Software Foundation
  7. * (the "LGPL") or, at your option, under the terms of the Mozilla
  8. * Public License Version 1.1 (the "MPL"). If you do not alter this
  9. * notice, a recipient may use your version of this file under either
  10. * the MPL or the LGPL.
  11. *
  12. * You should have received a copy of the LGPL along with this library
  13. * in the file COPYING-LGPL-2.1; if not, write to the Free Software
  14. * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
  15. * You should have received a copy of the MPL along with this library
  16. * in the file COPYING-MPL-1.1
  17. *
  18. * The contents of this file are subject to the Mozilla Public License
  19. * Version 1.1 (the "License"); you may not use this file except in
  20. * compliance with the License. You may obtain a copy of the License at
  21. * http://www.mozilla.org/MPL/
  22. *
  23. * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
  24. * OF ANY KIND, either express or implied. See the LGPL or the MPL for
  25. * the specific language governing rights and limitations.
  26. *
  27. * The Original Code is the cairo graphics library.
  28. *
  29. * The Initial Developer of the Original Code is Chris Wilson.
  30. *
  31. * Contributor(s):
  32. * Chris Wilson <chris@chris-wilson.co.uk>
  33. */
  34. #include "config.h"
  35. #include "cairo-script-private.h"
  36. #include <stdio.h>
  37. #include <limits.h> /* INT_MAX */
  38. #include <string.h>
  39. #include <zlib.h>
  40. #if HAVE_LZO
  41. #include <lzo/lzo2a.h>
  42. #endif
  43. #define CHUNK_SIZE 32768
  44. #define OWN_STREAM 0x1
  45. csi_status_t
  46. csi_file_new (csi_t *ctx,
  47. csi_object_t *obj,
  48. const char *path, const char *mode)
  49. {
  50. csi_file_t *file;
  51. file = _csi_slab_alloc (ctx, sizeof (csi_file_t));
  52. if (file == NULL)
  53. return _csi_error (CAIRO_STATUS_NO_MEMORY);
  54. file->base.type = CSI_OBJECT_TYPE_FILE;
  55. file->base.ref = 1;
  56. file->data = NULL;
  57. file->type = STDIO;
  58. file->flags = OWN_STREAM;
  59. file->src = fopen (path, mode);
  60. if (file->src == NULL) {
  61. _csi_slab_free (ctx, file, sizeof (csi_file_t));
  62. return _csi_error (CAIRO_STATUS_FILE_NOT_FOUND);
  63. }
  64. file->data = _csi_alloc (ctx, CHUNK_SIZE);
  65. if (file->data == NULL) {
  66. _csi_slab_free (ctx, file, sizeof (csi_file_t));
  67. return _csi_error (CAIRO_STATUS_NO_MEMORY);
  68. }
  69. file->bp = file->data;
  70. file->rem = 0;
  71. obj->type = CSI_OBJECT_TYPE_FILE;
  72. obj->datum.file = file;
  73. return CAIRO_STATUS_SUCCESS;
  74. }
  75. csi_status_t
  76. csi_file_new_for_stream (csi_t *ctx,
  77. csi_object_t *obj,
  78. FILE *stream)
  79. {
  80. csi_file_t *file;
  81. file = _csi_slab_alloc (ctx, sizeof (csi_file_t));
  82. if (file == NULL)
  83. return _csi_error (CAIRO_STATUS_NO_MEMORY);
  84. file->base.type = CSI_OBJECT_TYPE_FILE;
  85. file->base.ref = 1;
  86. file->data = NULL;
  87. file->type = STDIO;
  88. file->flags = 0;
  89. file->src = stream;
  90. if (file->src == NULL) {
  91. _csi_slab_free (ctx, file, sizeof (csi_file_t));
  92. return _csi_error (CAIRO_STATUS_FILE_NOT_FOUND);
  93. }
  94. file->data = _csi_alloc (ctx, CHUNK_SIZE);
  95. if (file->data == NULL) {
  96. _csi_slab_free (ctx, file, sizeof (csi_file_t));
  97. return _csi_error (CAIRO_STATUS_NO_MEMORY);
  98. }
  99. file->bp = file->data;
  100. file->rem = 0;
  101. obj->type = CSI_OBJECT_TYPE_FILE;
  102. obj->datum.file = file;
  103. return CAIRO_STATUS_SUCCESS;
  104. }
  105. csi_status_t
  106. csi_file_new_for_bytes (csi_t *ctx,
  107. csi_object_t *obj,
  108. const char *bytes,
  109. unsigned int length)
  110. {
  111. csi_file_t *file;
  112. file = _csi_slab_alloc (ctx, sizeof (csi_file_t));
  113. if (file == NULL)
  114. return _csi_error (CAIRO_STATUS_NO_MEMORY);
  115. file->base.type = CSI_OBJECT_TYPE_FILE;
  116. file->base.ref = 1;
  117. file->type = BYTES;
  118. file->src = (uint8_t *) bytes;
  119. file->data = (uint8_t *) bytes;
  120. file->bp = (uint8_t *) bytes;
  121. file->rem = length;
  122. obj->type = CSI_OBJECT_TYPE_FILE;
  123. obj->datum.file = file;
  124. return CAIRO_STATUS_SUCCESS;
  125. }
  126. csi_status_t
  127. csi_file_new_from_string (csi_t *ctx,
  128. csi_object_t *obj,
  129. csi_string_t *src)
  130. {
  131. csi_file_t *file;
  132. file = _csi_slab_alloc (ctx, sizeof (csi_file_t));
  133. if (_csi_unlikely (file == NULL))
  134. return _csi_error (CAIRO_STATUS_NO_MEMORY);
  135. file->base.type = CSI_OBJECT_TYPE_FILE;
  136. file->base.ref = 1;
  137. if (src->deflate) {
  138. uLongf len = src->deflate;
  139. csi_object_t tmp_obj;
  140. csi_string_t *tmp_str;
  141. csi_status_t status;
  142. status = csi_string_new (ctx, &tmp_obj, NULL, src->deflate);
  143. if (_csi_unlikely (status))
  144. return status;
  145. tmp_str = tmp_obj.datum.string;
  146. switch (src->method) {
  147. case NONE:
  148. default:
  149. status = _csi_error (CAIRO_STATUS_NO_MEMORY);
  150. break;
  151. case ZLIB:
  152. #if HAVE_ZLIB
  153. if (uncompress ((Bytef *) tmp_str->string, &len,
  154. (Bytef *) src->string, src->len) != Z_OK)
  155. #endif
  156. status = _csi_error (CAIRO_STATUS_NO_MEMORY);
  157. break;
  158. case LZO:
  159. #if HAVE_LZO
  160. if (lzo2a_decompress ((lzo_bytep) src->string, src->len,
  161. (lzo_bytep) tmp_str->string, &len,
  162. NULL))
  163. #endif
  164. status = _csi_error (CAIRO_STATUS_NO_MEMORY);
  165. break;
  166. }
  167. if (_csi_unlikely (status)) {
  168. csi_string_free (ctx, tmp_str);
  169. _csi_slab_free (ctx, file, sizeof (csi_file_t));
  170. return status;
  171. }
  172. file->src = tmp_str;
  173. file->data = tmp_str->string;
  174. file->rem = tmp_str->len;
  175. } else {
  176. file->src = src; src->base.ref++;
  177. file->data = src->string;
  178. file->rem = src->len;
  179. }
  180. file->type = BYTES;
  181. file->bp = file->data;
  182. obj->type = CSI_OBJECT_TYPE_FILE;
  183. obj->datum.file = file;
  184. return CAIRO_STATUS_SUCCESS;
  185. }
  186. static csi_status_t
  187. _csi_file_new_filter (csi_t *ctx,
  188. csi_object_t *obj,
  189. csi_object_t *src,
  190. const csi_filter_funcs_t *funcs,
  191. void *data)
  192. {
  193. csi_file_t *file;
  194. csi_object_t src_file;
  195. csi_status_t status;
  196. file = _csi_slab_alloc (ctx, sizeof (csi_file_t));
  197. if (file == NULL)
  198. return _csi_error (CAIRO_STATUS_NO_MEMORY);
  199. obj->type = CSI_OBJECT_TYPE_FILE;
  200. obj->datum.file = file;
  201. file->base.type = CSI_OBJECT_TYPE_FILE;
  202. file->base.ref = 1;
  203. file->type = FILTER;
  204. file->data = data;
  205. file->filter = funcs;
  206. status = csi_object_as_file (ctx, src, &src_file);
  207. if (status) {
  208. csi_object_free (ctx, obj);
  209. return status;
  210. }
  211. file->src = src_file.datum.file;
  212. return CAIRO_STATUS_SUCCESS;
  213. }
  214. #if 0
  215. csi_status_t
  216. csi_file_new_from_stream (csi_t *ctx,
  217. FILE *file,
  218. csi_object_t **out)
  219. {
  220. csi_file_t *obj;
  221. obj = (csi_file_t *) _csi_object_new (ctx, CSI_OBJECT_TYPE_FILE);
  222. if (obj == NULL)
  223. return _csi_error (CAIRO_STATUS_NO_MEMORY);
  224. obj->type = STDIO;
  225. obj->src = file;
  226. obj->data = _csi_alloc (ctx, CHUNK_SIZE);
  227. if (obj->data == NULL) {
  228. csi_object_free (&obj->base);
  229. return _csi_error (CAIRO_STATUS_UNDEFINED_FILENAME_ERROR);
  230. }
  231. obj->bp = obj->data;
  232. obj->rem = 0;
  233. *out = &obj->base;
  234. return CAIRO_STATUS_SUCCESS;
  235. }
  236. static csi_object_t *
  237. _csi_file_new_from_procedure (csi_t *ctx, csi_object_t *src)
  238. {
  239. csi_file_t *obj;
  240. obj = (csi_file_t *) _csi_object_new (ctx, CSI_OBJECT_TYPE_FILE);
  241. if (obj == NULL)
  242. return NULL;
  243. obj->type = PROCEDURE;
  244. obj->src = csi_object_reference (src);
  245. obj->data = NULL;
  246. return &obj->base;
  247. }
  248. #endif
  249. typedef struct _ascii85_decode_data {
  250. uint8_t buf[CHUNK_SIZE];
  251. uint8_t *bp;
  252. short bytes_available;
  253. short eod;
  254. } _ascii85_decode_data_t;
  255. static int
  256. _getc_skip_whitespace (csi_file_t *src)
  257. {
  258. int c;
  259. do switch ((c = csi_file_getc (src))) {
  260. case 0x0:
  261. case 0x9:
  262. case 0xa:
  263. case 0xc:
  264. case 0xd:
  265. case 0x20:
  266. continue;
  267. default:
  268. return c;
  269. } while (TRUE);
  270. return c;
  271. }
  272. static void
  273. _ascii85_decode (csi_file_t *file)
  274. {
  275. _ascii85_decode_data_t *data = file->data;
  276. unsigned int n;
  277. if (data->eod)
  278. return;
  279. data->bp = data->buf;
  280. n = 0;
  281. do {
  282. unsigned int v = _getc_skip_whitespace (file->src);
  283. if (v == 'z') {
  284. data->buf[n+0] = 0;
  285. data->buf[n+1] = 0;
  286. data->buf[n+2] = 0;
  287. data->buf[n+3] = 0;
  288. } else if (v == '~') {
  289. _getc_skip_whitespace (file->src); /* == '>' || IO_ERROR */
  290. data->eod = TRUE;
  291. break;
  292. } else if (v < '!' || v > 'u') {
  293. /* IO_ERROR */
  294. data->eod = TRUE;
  295. break;
  296. } else {
  297. unsigned int i;
  298. v -= '!';
  299. for (i = 1; i < 5; i++) {
  300. int c = _getc_skip_whitespace (file->src);
  301. if (c == '~') { /* short tuple */
  302. _getc_skip_whitespace (file->src); /* == '>' || IO_ERROR */
  303. data->eod = TRUE;
  304. switch (i) {
  305. case 0:
  306. case 1:
  307. /* IO_ERROR */
  308. break;
  309. case 2:
  310. v = v * (85*85*85) + 85*85*85 -1;
  311. goto odd1;
  312. case 3:
  313. v = v * (85*85) + 85*85 -1;
  314. goto odd2;
  315. case 4:
  316. v = v * 85 + 84;
  317. data->buf[n+2] = v >> 8 & 0xff;
  318. odd2:
  319. data->buf[n+1] = v >> 16 & 0xff;
  320. odd1:
  321. data->buf[n+0] = v >> 24 & 0xff;
  322. data->bytes_available = n + i - 1;
  323. return;
  324. }
  325. break;
  326. }
  327. v = 85*v + c-'!';
  328. }
  329. data->buf[n+0] = v >> 24 & 0xff;
  330. data->buf[n+1] = v >> 16 & 0xff;
  331. data->buf[n+2] = v >> 8 & 0xff;
  332. data->buf[n+3] = v >> 0 & 0xff;
  333. }
  334. n += 4;
  335. } while (n < sizeof (data->buf) && data->eod == FALSE);
  336. data->bytes_available = n;
  337. }
  338. static int
  339. _ascii85_decode_getc (csi_file_t *file)
  340. {
  341. _ascii85_decode_data_t *data = file->data;
  342. if (data->bytes_available == 0) {
  343. _ascii85_decode (file);
  344. if (data->bytes_available == 0)
  345. return EOF;
  346. }
  347. data->bytes_available--;
  348. return *data->bp++;
  349. }
  350. static void
  351. _ascii85_decode_putc (csi_file_t *file, int c)
  352. {
  353. _ascii85_decode_data_t *data = file->data;
  354. data->bytes_available++;
  355. data->bp--;
  356. }
  357. static int
  358. _ascii85_decode_read (csi_file_t *file, uint8_t *buf, int len)
  359. {
  360. _ascii85_decode_data_t *data = file->data;
  361. if (data->bytes_available == 0) {
  362. _ascii85_decode (file);
  363. if (data->bytes_available == 0)
  364. return 0;
  365. }
  366. if (len > data->bytes_available)
  367. len = data->bytes_available;
  368. memcpy (buf, data->bp, len);
  369. data->bp += len;
  370. data->bytes_available -= len;
  371. return len;
  372. }
  373. csi_status_t
  374. csi_file_new_ascii85_decode (csi_t *ctx,
  375. csi_object_t *obj,
  376. csi_dictionary_t *dict,
  377. csi_object_t *src)
  378. {
  379. static const csi_filter_funcs_t funcs = {
  380. _ascii85_decode_getc,
  381. _ascii85_decode_putc,
  382. _ascii85_decode_read,
  383. _csi_free,
  384. };
  385. _ascii85_decode_data_t *data;
  386. data = _csi_alloc0 (ctx, sizeof (_ascii85_decode_data_t));
  387. if (data == NULL)
  388. return _csi_error (CAIRO_STATUS_NO_MEMORY);
  389. return _csi_file_new_filter (ctx, obj, src, &funcs, data);
  390. }
  391. #if HAVE_ZLIB
  392. #include <zlib.h>
  393. typedef struct _deflate_decode_data {
  394. z_stream zlib_stream;
  395. uint8_t in[CHUNK_SIZE];
  396. uint8_t out[CHUNK_SIZE];
  397. int bytes_available;
  398. uint8_t *bp;
  399. } _deflate_decode_data_t;
  400. static void
  401. _deflate_decode (csi_file_t *file)
  402. {
  403. _deflate_decode_data_t *data = file->data;
  404. uint8_t *bp;
  405. int len;
  406. data->zlib_stream.next_out = data->out;
  407. data->zlib_stream.avail_out = sizeof (data->out);
  408. bp = data->in;
  409. len = sizeof (data->in);
  410. if (data->zlib_stream.avail_in) {
  411. memmove (data->in,
  412. data->zlib_stream.next_in,
  413. data->zlib_stream.avail_in);
  414. len -= data->zlib_stream.avail_in;
  415. bp += data->zlib_stream.avail_in;
  416. }
  417. len = csi_file_read (file->src, bp, len);
  418. data->zlib_stream.next_in = data->in;
  419. data->zlib_stream.avail_in += len;
  420. inflate (&data->zlib_stream, len == 0 ? Z_FINISH : Z_NO_FLUSH);
  421. data->bytes_available = data->zlib_stream.next_out - data->out;
  422. data->bp = data->out;
  423. }
  424. static int
  425. _deflate_decode_getc (csi_file_t *file)
  426. {
  427. _deflate_decode_data_t *data = file->data;
  428. if (data->bytes_available == 0) {
  429. _deflate_decode (file);
  430. if (data->bytes_available == 0)
  431. return EOF;
  432. }
  433. data->bytes_available--;
  434. return *data->bp++;
  435. }
  436. static void
  437. _deflate_decode_putc (csi_file_t *file, int c)
  438. {
  439. _deflate_decode_data_t *data = file->data;
  440. data->bytes_available++;
  441. data->bp--;
  442. }
  443. static int
  444. _deflate_decode_read (csi_file_t *file, uint8_t *buf, int len)
  445. {
  446. _deflate_decode_data_t *data = file->data;
  447. if (data->bytes_available == 0) {
  448. _deflate_decode (file);
  449. if (data->bytes_available == 0)
  450. return 0;
  451. }
  452. if (len > (int) data->bytes_available)
  453. len = data->bytes_available;
  454. memcpy (buf, data->bp, len);
  455. data->bp += len;
  456. data->bytes_available -= len;
  457. return len;
  458. }
  459. static void
  460. _deflate_destroy (csi_t *ctx, void *closure)
  461. {
  462. _deflate_decode_data_t *data;
  463. data = closure;
  464. inflateEnd (&data->zlib_stream);
  465. _csi_free (ctx, data);
  466. }
  467. csi_status_t
  468. csi_file_new_deflate_decode (csi_t *ctx,
  469. csi_object_t *obj,
  470. csi_dictionary_t *dict,
  471. csi_object_t *src)
  472. {
  473. static const csi_filter_funcs_t funcs = {
  474. _deflate_decode_getc,
  475. _deflate_decode_putc,
  476. _deflate_decode_read,
  477. _deflate_destroy,
  478. };
  479. _deflate_decode_data_t *data;
  480. data = _csi_alloc (ctx, sizeof (_deflate_decode_data_t));
  481. if (data == NULL)
  482. return _csi_error (CAIRO_STATUS_NO_MEMORY);
  483. data->zlib_stream.zalloc = Z_NULL;
  484. data->zlib_stream.zfree = Z_NULL;
  485. data->zlib_stream.opaque = Z_NULL;
  486. data->zlib_stream.next_in = data->in;
  487. data->zlib_stream.avail_in = 0;
  488. data->zlib_stream.next_out = data->out;
  489. data->zlib_stream.avail_out = sizeof (data->out);
  490. data->bytes_available = 0;
  491. if (inflateInit (&data->zlib_stream) != Z_OK) {
  492. _csi_free (ctx, data);
  493. return _csi_error (CAIRO_STATUS_NO_MEMORY);
  494. }
  495. return _csi_file_new_filter (ctx, obj, src, &funcs, data);
  496. }
  497. #endif
  498. #if 0
  499. static int
  500. hex_value (int c)
  501. {
  502. if (c < '0')
  503. return EOF;
  504. if (c <= '9')
  505. return c - '0';
  506. c |= 32;
  507. if (c < 'a')
  508. return EOF;
  509. if (c <= 'f')
  510. return c - 'a' + 0xa;
  511. return EOF;
  512. }
  513. /* Adobe Type 1 Font Format book: p63 */
  514. typedef struct _decrypt_data {
  515. uint8_t putback[32];
  516. uint8_t nputback;
  517. csi_bool_t is_hexadecimal;
  518. unsigned short R;
  519. int eod;
  520. } _decrypt_data_t;
  521. static uint8_t
  522. _decrypt (unsigned short *R, uint8_t cypher)
  523. {
  524. #define c1 52845
  525. #define c2 22719
  526. uint8_t plain;
  527. plain = cypher ^ (*R >> 8);
  528. *R = (cypher + *R) * c1 + c2;
  529. return plain;
  530. #undef c1
  531. #undef c2
  532. }
  533. int
  534. csi_decrypt (uint8_t *in, int length,
  535. unsigned short salt, int binary,
  536. uint8_t *out)
  537. {
  538. const uint8_t * const end = in + length;
  539. uint8_t *base = out;
  540. while (in < end) {
  541. int c;
  542. if (! binary) {
  543. int c_hi = -1, c_lo = 0;
  544. while (in < end && (c_hi = *in++)) {
  545. switch (c_hi) {
  546. case 0x0:
  547. case 0x9:
  548. case 0xa:
  549. case 0xc:
  550. case 0xd:
  551. case 0x20:
  552. continue;
  553. default:
  554. break;
  555. }
  556. }
  557. if (c_hi < 0)
  558. break;
  559. while (in < end && (c_lo = *in++)) {
  560. switch (c_lo) {
  561. case 0x0:
  562. case 0x9:
  563. case 0xa:
  564. case 0xc:
  565. case 0xd:
  566. case 0x20:
  567. continue;
  568. default:
  569. break;
  570. }
  571. }
  572. c = (hex_value (c_hi) << 4) | hex_value (c_lo);
  573. } else
  574. c = *in++;
  575. *out++ = _decrypt (&salt, c);
  576. }
  577. return out - base;
  578. }
  579. static uint8_t
  580. _encrypt (unsigned short *R, uint8_t plain)
  581. {
  582. #define c1 52845
  583. #define c2 22719
  584. uint8_t cypher;
  585. cypher = plain ^ (*R >> 8);
  586. *R = (cypher + *R) * c1 + c2;
  587. return cypher;
  588. #undef c1
  589. #undef c2
  590. }
  591. int
  592. csi_encrypt (uint8_t *in, int length,
  593. unsigned short salt, int discard, int binary,
  594. uint8_t *out)
  595. {
  596. const char hex[]="0123456789abcdef";
  597. const uint8_t * const end = in + length;
  598. uint8_t *base = out;
  599. int col = 0;
  600. while (discard--) {
  601. if (! binary) {
  602. int c = _encrypt (&salt, ' ');
  603. *out++ = hex[(c >> 4) & 0xf];
  604. *out++ = hex[(c >> 0) & 0xf];
  605. } else
  606. *out++ = _encrypt (&salt, 0);
  607. }
  608. while (in < end) {
  609. int c;
  610. c = _encrypt (&salt, *in++);
  611. if (! binary) {
  612. if (col == 78) {
  613. *out++ = '\n';
  614. col = 0;
  615. }
  616. *out++ = hex[(c >> 4) & 0xf];
  617. *out++ = hex[(c >> 0) & 0xf];
  618. col += 2;
  619. } else
  620. *out++ = c;
  621. }
  622. return out - base;
  623. }
  624. static int
  625. _decrypt_getc (csi_file_t *file)
  626. {
  627. _decrypt_data_t *data = file->data;
  628. int c;
  629. if (data->nputback)
  630. return data->putback[--data->nputback];
  631. if (data->is_hexadecimal) {
  632. int c_hi, c_lo;
  633. c_hi = _getc_skip_whitespace (file->src);
  634. c_lo = _getc_skip_whitespace (file->src);
  635. c = (hex_value (c_hi) << 4) | hex_value (c_lo);
  636. } else
  637. c = csi_file_getc (file->src);
  638. if (c == EOF)
  639. return EOF;
  640. return _decrypt (&data->R, c);
  641. }
  642. static void
  643. _decrypt_putc (csi_file_t *file, int c)
  644. {
  645. _decrypt_data_t *data;
  646. data = file->data;
  647. data->putback[data->nputback++] = c;
  648. }
  649. csi_object_t *
  650. csi_file_new_decrypt (csi_t *ctx, csi_object_t *src, int salt, int discard)
  651. {
  652. csi_object_t *obj;
  653. _decrypt_data_t *data;
  654. int n;
  655. data = _csi_alloc0 (ctx, sizeof (_decrypt_data_t));
  656. if (data == NULL)
  657. return NULL;
  658. data->R = salt;
  659. obj = _csi_file_new_filter (ctx, src,
  660. _decrypt_getc,
  661. _decrypt_putc,
  662. NULL,
  663. _csi_free,
  664. data);
  665. if (obj == NULL)
  666. return NULL;
  667. /* XXX determine encoding, eexec only? */
  668. data->is_hexadecimal = salt != 4330;
  669. for (n = 0; n < discard; n++) {
  670. int c;
  671. c = csi_file_getc (obj);
  672. if (c == EOF) {
  673. return obj;
  674. }
  675. }
  676. return obj;
  677. }
  678. #endif
  679. csi_status_t
  680. _csi_file_execute (csi_t *ctx, csi_file_t *obj)
  681. {
  682. return _csi_scan_file (ctx, obj);
  683. }
  684. int
  685. csi_file_getc (csi_file_t *file)
  686. {
  687. int c;
  688. if (_csi_unlikely (file->src == NULL))
  689. return EOF;
  690. switch (file->type) {
  691. case STDIO:
  692. if (_csi_likely (file->rem)) {
  693. c = *file->bp++;
  694. file->rem--;
  695. } else {
  696. file->rem = fread (file->bp = file->data, 1, CHUNK_SIZE, file->src);
  697. case BYTES:
  698. if (_csi_likely (file->rem)) {
  699. c = *file->bp++;
  700. file->rem--;
  701. } else
  702. c = EOF;
  703. }
  704. break;
  705. case PROCEDURE:
  706. #if 0
  707. if (file->data == NULL) {
  708. csi_status_t status;
  709. csi_object_t *string;
  710. RERUN_PROCEDURE:
  711. status = csi_object_execute (file->src);
  712. if (status)
  713. return EOF;
  714. string = csi_pop_operand (file->base.ctx);
  715. if (string == NULL)
  716. return EOF;
  717. file->data = csi_object_as_file (file->base.ctx, string);
  718. csi_object_free (string);
  719. if (file->data == NULL)
  720. return EOF;
  721. }
  722. c = csi_file_getc (file->data);
  723. if (c == EOF) {
  724. csi_object_free (file->data);
  725. file->data = NULL;
  726. goto RERUN_PROCEDURE;
  727. }
  728. #else
  729. c = EOF;
  730. #endif
  731. break;
  732. case FILTER:
  733. c = file->filter->filter_getc (file);
  734. break;
  735. default:
  736. c = EOF;
  737. break;
  738. }
  739. return c;
  740. }
  741. int
  742. csi_file_read (csi_file_t *file, void *buf, int len)
  743. {
  744. int ret;
  745. if (file->src == NULL)
  746. return 0;
  747. switch (file->type) {
  748. case STDIO:
  749. if (file->rem > 0) {
  750. ret = len;
  751. if (file->rem < ret)
  752. ret = file->rem;
  753. memcpy (buf, file->bp, ret);
  754. file->bp += ret;
  755. file->rem -= ret;
  756. } else
  757. ret = fread (buf, 1, len, file->src);
  758. break;
  759. case BYTES:
  760. if (file->rem > 0) {
  761. ret = len;
  762. if (file->rem < ret)
  763. ret = file->rem;
  764. memcpy (buf, file->bp, ret);
  765. file->bp += ret;
  766. file->rem -= ret;
  767. } else
  768. ret = 0;
  769. break;
  770. case PROCEDURE:
  771. #if 0
  772. if (file->data == NULL) {
  773. csi_status_t status;
  774. csi_object_t *string;
  775. RERUN_PROCEDURE:
  776. status = csi_object_execute (file->src);
  777. if (status)
  778. return 0;
  779. string = csi_pop_operand (file->base.ctx);
  780. if (string == NULL)
  781. return 0;
  782. file->data = csi_object_as_file (file->base.ctx, string);
  783. csi_object_free (string);
  784. if (file->data == NULL)
  785. return 0;
  786. }
  787. ret = csi_file_read (file->data, buf, len);
  788. if (ret == 0) {
  789. csi_object_free (file->data);
  790. file->data = NULL;
  791. goto RERUN_PROCEDURE;
  792. }
  793. #else
  794. ret = 0;
  795. #endif
  796. break;
  797. case FILTER:
  798. ret = file->filter->filter_read (file, buf, len);
  799. break;
  800. default:
  801. ret = 0;
  802. break;
  803. }
  804. return ret;
  805. }
  806. void
  807. csi_file_putc (csi_file_t *file, int c)
  808. {
  809. if (file->src == NULL)
  810. return;
  811. switch ((int) file->type) {
  812. case STDIO:
  813. case BYTES:
  814. file->bp--;
  815. file->rem++;
  816. break;
  817. case FILTER:
  818. file->filter->filter_putc (file, c);
  819. break;
  820. default:
  821. break;
  822. }
  823. }
  824. void
  825. csi_file_flush (csi_file_t *file)
  826. {
  827. if (file->src == NULL)
  828. return;
  829. switch ((int) file->type) {
  830. case FILTER: /* need to eat EOD */
  831. while (csi_file_getc (file) != EOF)
  832. ;
  833. break;
  834. default:
  835. break;
  836. }
  837. }
  838. void
  839. csi_file_close (csi_t *ctx, csi_file_t *file)
  840. {
  841. if (file->src == NULL)
  842. return;
  843. switch (file->type) {
  844. case STDIO:
  845. if (file->flags & OWN_STREAM)
  846. fclose (file->src);
  847. break;
  848. case BYTES:
  849. if (file->src != file->data) {
  850. csi_string_t *src = file->src;
  851. if (src != NULL && --src->base.ref == 0)
  852. csi_string_free (ctx, src);
  853. }
  854. break;
  855. case FILTER:
  856. {
  857. csi_file_t *src = file->src;
  858. if (src != NULL && --src->base.ref == 0)
  859. _csi_file_free (ctx, src);
  860. }
  861. break;
  862. case PROCEDURE:
  863. default:
  864. break;
  865. }
  866. file->src = NULL;
  867. }
  868. void
  869. _csi_file_free (csi_t *ctx, csi_file_t *file)
  870. {
  871. csi_file_flush (file);
  872. /* XXX putback */
  873. csi_file_close (ctx, file);
  874. switch (file->type) {
  875. case BYTES:
  876. break;
  877. case PROCEDURE:
  878. #if 0
  879. csi_object_free (ctx, file->data);
  880. #endif
  881. break;
  882. case STDIO:
  883. _csi_free (ctx, file->data);
  884. break;
  885. case FILTER:
  886. file->filter->filter_destroy (ctx, file->data);
  887. break;
  888. default:
  889. break;
  890. }
  891. _csi_slab_free (ctx, file, sizeof (csi_file_t));
  892. }
  893. csi_status_t
  894. _csi_file_as_string (csi_t *ctx,
  895. csi_file_t *file,
  896. csi_object_t *obj)
  897. {
  898. char *bytes;
  899. unsigned int len;
  900. unsigned int allocated;
  901. csi_status_t status;
  902. allocated = 16384;
  903. bytes = _csi_alloc (ctx, allocated);
  904. if (bytes == NULL)
  905. return _csi_error (CAIRO_STATUS_NO_MEMORY);
  906. len = 0;
  907. do {
  908. int ret;
  909. ret = csi_file_read (file, bytes + len, allocated - len);
  910. if (ret == 0)
  911. break;
  912. len += ret;
  913. if (len + 1 > allocated / 2) {
  914. char *newbytes;
  915. int newlen;
  916. if (_csi_unlikely (allocated > INT_MAX / 2))
  917. return _csi_error (CAIRO_STATUS_NO_MEMORY);
  918. newlen = allocated * 2;
  919. newbytes = _csi_realloc (ctx, bytes, newlen);
  920. if (_csi_unlikely (newbytes == NULL)) {
  921. _csi_free (ctx, bytes);
  922. return _csi_error (CAIRO_STATUS_NO_MEMORY);
  923. }
  924. bytes = newbytes;
  925. allocated = newlen;
  926. }
  927. } while (TRUE);
  928. bytes[len] = '\0'; /* better safe than sorry! */
  929. status = csi_string_new_from_bytes (ctx, obj, bytes, len);
  930. if (status) {
  931. _csi_free (ctx, bytes);
  932. return status;
  933. }
  934. return CAIRO_STATUS_SUCCESS;
  935. }