示例#1
0
static void renumberobjs(void)
{
	pdf_xref_entry *oldxref;
	int newlen;
	int num;

	/* Apply renumber map to indirect references in all objects in xref */
	renumberobj(xref->trailer);
	for (num = 0; num < xref->len; num++)
	{
		fz_obj *obj = xref->table[num].obj;

		if (fz_is_indirect(obj))
		{
			obj = fz_new_indirect(ctx, renumbermap[fz_to_num(obj)], 0, xref);
			pdf_update_object(xref, num, 0, obj);
			fz_drop_obj(obj);
		}
		else
		{
			renumberobj(obj);
		}
	}

	/* Create new table for the reordered, compacted xref */
	oldxref = xref->table;
	xref->table = fz_malloc_array(xref->ctx, xref->len, sizeof(pdf_xref_entry));
	xref->table[0] = oldxref[0];

	/* Move used objects into the new compacted xref */
	newlen = 0;
	for (num = 1; num < xref->len; num++)
	{
		if (uselist[num])
		{
			if (newlen < renumbermap[num])
				newlen = renumbermap[num];
			xref->table[renumbermap[num]] = oldxref[num];
		}
		else
		{
			if (oldxref[num].obj)
				fz_drop_obj(oldxref[num].obj);
		}
	}

	fz_free(xref->ctx, oldxref);

	/* Update the used objects count in compacted xref */
	xref->len = newlen + 1;

	/* Update list of used objects to fit with compacted xref */
	for (num = 1; num < xref->len; num++)
		uselist[num] = 1;
}
/*
 * Load uncompressed contents of a stream into buf.
 */
fz_error
pdf_load_stream(fz_buffer **bufp, pdf_xref *xref, int num, int gen)
{
	fz_error error;
	fz_stream *stm;
	fz_obj *dict, *obj;
	int i, len;

	error = pdf_open_stream(&stm, xref, num, gen);
	if (error)
		return fz_rethrow(error, "cannot open stream (%d %d R)", num, gen);

	error = pdf_load_object(&dict, xref, num, gen);
	if (error)
		return fz_rethrow(error, "cannot load stream dictionary (%d %d R)", num, gen);

	len = fz_to_int(fz_dict_gets(dict, "Length"));
	obj = fz_dict_gets(dict, "Filter");
	len = pdf_guess_filter_length(len, fz_to_name(obj));
	for (i = 0; i < fz_array_len(obj); i++)
		len = pdf_guess_filter_length(len, fz_to_name(fz_array_get(obj, i)));

	fz_drop_obj(dict);

	error = fz_read_all(bufp, stm, len);
	if (error)
	{
		fz_close(stm);
		return fz_rethrow(error, "cannot read raw stream (%d %d R)", num, gen);
	}

	fz_close(stm);
	return fz_okay;
}
示例#3
0
static void expandstream(fz_obj *obj, int num, int gen)
{
	fz_buffer *buf, *tmp;
	fz_obj *newlen;

	buf = pdf_load_stream(xref, num, gen);

	fz_dict_dels(obj, "Filter");
	fz_dict_dels(obj, "DecodeParms");

	if (doascii && isbinarystream(buf))
	{
		tmp = hexbuf(buf->data, buf->len);
		fz_drop_buffer(ctx, buf);
		buf = tmp;

		addhexfilter(obj);
	}

	newlen = fz_new_int(ctx, buf->len);
	fz_dict_puts(obj, "Length", newlen);
	fz_drop_obj(newlen);

	fprintf(out, "%d %d obj\n", num, gen);
	fz_fprint_obj(out, obj, doexpand == 0);
	fprintf(out, "stream\n");
	fwrite(buf->data, 1, buf->len, out);
	fprintf(out, "endstream\nendobj\n\n");

	fz_drop_buffer(ctx, buf);
}
/*
 * Load raw (compressed but decrypted) contents of a stream into buf.
 */
fz_error
pdf_load_raw_stream(fz_buffer **bufp, pdf_xref *xref, int num, int gen)
{
	fz_error error;
	fz_stream *stm;
	fz_obj *dict;
	int len;

	error = pdf_load_object(&dict, xref, num, gen);
	if (error)
		return fz_rethrow(error, "cannot load stream dictionary (%d %d R)", num, gen);

	len = fz_to_int(fz_dict_gets(dict, "Length"));

	fz_drop_obj(dict);

	error = pdf_open_raw_stream(&stm, xref, num, gen);
	if (error)
		return fz_rethrow(error, "cannot open raw stream (%d %d R)", num, gen);

	error = fz_read_all(bufp, stm, len);
	if (error)
	{
		fz_close(stm);
		return fz_rethrow(error, "cannot read raw stream (%d %d R)", num, gen);
	}

	fz_close(stm);
	return fz_okay;
}
示例#5
0
static void copystream(fz_obj *obj, int num, int gen)
{
	fz_error error;
	fz_buffer *buf, *tmp;
	fz_obj *newlen;

	error = pdf_load_raw_stream(&buf, xref, num, gen);
	if (error)
		die(error);

	if (doascii && isbinarystream(buf))
	{
		tmp = hexbuf(buf->data, buf->len);
		fz_drop_buffer(ctx, buf);
		buf = tmp;

		addhexfilter(obj);

		newlen = fz_new_int(ctx, buf->len);
		fz_dict_puts(ctx, obj, "Length", newlen);
		fz_drop_obj(ctx, newlen);
	}

	fprintf(out, "%d %d obj\n", num, gen);
	fz_fprint_obj(ctx, out, obj, !doexpand);
	fprintf(out, "stream\n");
	fwrite(buf->data, 1, buf->len, out);
	fprintf(out, "endstream\nendobj\n\n");

	fz_drop_buffer(ctx, buf);
}
示例#6
0
void
pdf_free_xref(pdf_xref *xref)
{
	int i;

	if (xref->store)
		pdf_free_store(xref->store);

	if (xref->table)
	{
		for (i = 0; i < xref->len; i++)
		{
			if (xref->table[i].obj)
			{
				fz_drop_obj(xref->table[i].obj);
				xref->table[i].obj = NULL;
			}
		}
		fz_free(xref->table);
	}

	if (xref->page_objs)
	{
		for (i = 0; i < xref->page_len; i++)
			fz_drop_obj(xref->page_objs[i]);
		fz_free(xref->page_objs);
	}

	if (xref->page_refs)
	{
		for (i = 0; i < xref->page_len; i++)
			fz_drop_obj(xref->page_refs[i]);
		fz_free(xref->page_refs);
	}

	if (xref->file)
		fz_close(xref->file);
	if (xref->trailer)
		fz_drop_obj(xref->trailer);
	if (xref->crypt)
		pdf_free_crypt(xref->crypt);

	pdf_free_ocg(xref->ocg);

	fz_free(xref);
}
示例#7
0
static void addhexfilter(fz_obj *dict)
{
	fz_obj *f, *dp, *newf, *newdp;
	fz_obj *ahx, *nullobj;

	ahx = fz_new_name(ctx, "ASCIIHexDecode");
	nullobj = fz_new_null(ctx);
	newf = newdp = NULL;

	f = fz_dict_gets(dict, "Filter");
	dp = fz_dict_gets(dict, "DecodeParms");

	if (fz_is_name(f))
	{
		newf = fz_new_array(ctx, 2);
		fz_array_push(newf, ahx);
		fz_array_push(newf, f);
		f = newf;
		if (fz_is_dict(dp))
		{
			newdp = fz_new_array(ctx, 2);
			fz_array_push(newdp, nullobj);
			fz_array_push(newdp, dp);
			dp = newdp;
		}
	}
	else if (fz_is_array(f))
	{
		fz_array_insert(f, ahx);
		if (fz_is_array(dp))
			fz_array_insert(dp, nullobj);
	}
	else
		f = ahx;

	fz_dict_puts(dict, "Filter", f);
	if (dp)
		fz_dict_puts(dict, "DecodeParms", dp);

	fz_drop_obj(ahx);
	fz_drop_obj(nullobj);
	if (newf)
		fz_drop_obj(newf);
	if (newdp)
		fz_drop_obj(newdp);
}
示例#8
0
static void writexref(void)
{
	fz_obj *trailer;
	fz_obj *obj;
	int startxref;
	int num;

	startxref = ftell(out);

	fprintf(out, "xref\n0 %d\n", xref->len);
	for (num = 0; num < xref->len; num++)
	{
		if (uselist[num])
			fprintf(out, "%010d %05d n \n", ofslist[num], genlist[num]);
		else
			fprintf(out, "%010d %05d f \n", ofslist[num], genlist[num]);
	}
	fprintf(out, "\n");

	trailer = fz_new_dict(ctx, 5);

	obj = fz_new_int(ctx, xref->len);
	fz_dict_puts(trailer, "Size", obj);
	fz_drop_obj(obj);

	obj = fz_dict_gets(xref->trailer, "Info");
	if (obj)
		fz_dict_puts(trailer, "Info", obj);

	obj = fz_dict_gets(xref->trailer, "Root");
	if (obj)
		fz_dict_puts(trailer, "Root", obj);

	obj = fz_dict_gets(xref->trailer, "ID");
	if (obj)
		fz_dict_puts(trailer, "ID", obj);

	fprintf(out, "trailer\n");
	fz_fprint_obj(out, trailer, doexpand == 0);
	fprintf(out, "\n");

	fz_drop_obj(trailer);

	fprintf(out, "startxref\n%d\n%%%%EOF\n", startxref);
}
示例#9
0
void
pdf_free_link(fz_context *ctx, pdf_link *link)
{
	if (link->next)
		pdf_free_link(ctx, link->next);
		if (link->dest)
			fz_drop_obj(ctx, link->dest);
	fz_free(ctx, link);
}
示例#10
0
static void renumberobj(fz_obj *obj)
{
	int i;
	fz_context *ctx = xref->ctx;

	if (fz_is_dict(obj))
	{
		int n = fz_dict_len(obj);
		for (i = 0; i < n; i++)
		{
			fz_obj *key = fz_dict_get_key(obj, i);
			fz_obj *val = fz_dict_get_val(obj, i);
			if (fz_is_indirect(val))
			{
				val = fz_new_indirect(ctx, renumbermap[fz_to_num(val)], 0, xref);
				fz_dict_put(obj, key, val);
				fz_drop_obj(val);
			}
			else
			{
				renumberobj(val);
			}
		}
	}

	else if (fz_is_array(obj))
	{
		int n = fz_array_len(obj);
		for (i = 0; i < n; i++)
		{
			fz_obj *val = fz_array_get(obj, i);
			if (fz_is_indirect(val))
			{
				val = fz_new_indirect(ctx, renumbermap[fz_to_num(val)], 0, xref);
				fz_array_put(obj, i, val);
				fz_drop_obj(val);
			}
			else
			{
				renumberobj(val);
			}
		}
	}
}
示例#11
0
static void writeobject(int num, int gen)
{
	fz_error error;
	fz_obj *obj;
	fz_obj *type;

	error = pdf_load_object(&obj, xref, num, gen);
	if (error)
		die(error);

	/* skip ObjStm and XRef objects */
	if (fz_is_dict(ctx, obj))
	{
		type = fz_dict_gets(ctx, obj, "Type");
		if (fz_is_name(ctx, type) && !strcmp(fz_to_name(ctx, type), "ObjStm"))
		{
			uselist[num] = 0;
			fz_drop_obj(ctx, obj);
			return;
		}
		if (fz_is_name(ctx, type) && !strcmp(fz_to_name(ctx, type), "XRef"))
		{
			uselist[num] = 0;
			fz_drop_obj(ctx, obj);
			return;
		}
	}

	if (!pdf_is_stream(xref, num, gen))
	{
		fprintf(out, "%d %d obj\n", num, gen);
		fz_fprint_obj(ctx, out, obj, !doexpand);
		fprintf(out, "endobj\n\n");
	}
	else
	{
		if (doexpand && !pdf_is_jpx_image(ctx, obj))
			expandstream(obj, num, gen);
		else
			copystream(obj, num, gen);
	}

	fz_drop_obj(ctx, obj);
}
示例#12
0
static void
pdf_free_ocg(pdf_ocg_descriptor *desc)
{
	if (desc == NULL)
		return;

	if (desc->intent)
		fz_drop_obj(desc->intent);
	fz_free(desc->ocgs);
	fz_free(desc);
}
示例#13
0
static fz_obj *
pdf_clone_for_view_only(pdf_xref *xref, fz_obj *obj)
{
	fz_obj *ocgs = pdf_dict_from_string(xref, ANNOT_OC_VIEW_ONLY);

	obj = fz_copy_dict(xref->ctx, pdf_resolve_indirect(obj));
	fz_dict_puts(xref->ctx, obj, "OC", ocgs);
	fz_drop_obj(xref->ctx, ocgs);

	return obj;
}
示例#14
0
void
pdf_free_annot(fz_context *ctx, pdf_annot *annot)
{
	if (annot->next)
		pdf_free_annot(ctx, annot->next);
		if (annot->ap)
		pdf_drop_xobject(ctx, annot->ap);
		if (annot->obj)
		fz_drop_obj(ctx, annot->obj);
	fz_free(ctx, annot);
}
示例#15
0
void
pdf_drop_pattern(pdf_pattern *pat)
{
	if (pat && --pat->refs == 0)
	{
		if (pat->resources)
			fz_drop_obj(pat->resources);
		if (pat->contents)
			fz_drop_buffer(pat->contents);
		fz_free(pat);
	}
}
示例#16
0
static fz_error
pdf_read_xref_sections(pdf_xref *xref, int ofs, char *buf, int cap)
{
	fz_error error;
	fz_obj *trailer;
	fz_obj *prev;
	fz_obj *xrefstm;

	error = pdf_read_xref(&trailer, xref, ofs, buf, cap);
	if (error)
		return fz_rethrow(error, "cannot read xref section");

	/* FIXME: do we overwrite free entries properly? */
	xrefstm = fz_dict_gets(trailer, "XRefStm");
	if (xrefstm)
	{
		error = pdf_read_xref_sections(xref, fz_to_int(xrefstm), buf, cap);
		if (error)
		{
			fz_drop_obj(trailer);
			return fz_rethrow(error, "cannot read /XRefStm xref section");
		}
	}

	prev = fz_dict_gets(trailer, "Prev");
	if (prev)
	{
		error = pdf_read_xref_sections(xref, fz_to_int(prev), buf, cap);
		if (error)
		{
			fz_drop_obj(trailer);
			return fz_rethrow(error, "cannot read /Prev xref section");
		}
	}

	fz_drop_obj(trailer);
	return fz_okay;
}
示例#17
0
static void preloadobjstms(void)
{
	fz_obj *obj;
	int num;

	for (num = 0; num < xref->len; num++)
	{
		if (xref->table[num].type == 'o')
		{
			obj = pdf_load_object(xref, num, 0);
			fz_drop_obj(obj);
		}
	}
}
示例#18
0
static void preloadobjstms(void)
{
	fz_error error;
	fz_obj *obj;
	int num;

	for (num = 0; num < xref->len; num++)
	{
		if (xref->table[num].type == 'o')
		{
			error = pdf_load_object(&obj, xref, num, 0);
			if (error)
				die(error);
			fz_drop_obj(ctx, obj);
		}
	}
}
示例#19
0
static void showobject(int num)
{
	fz_error error;
	fz_obj *obj;

	if (!xref)
		die(fz_error_make(ctx, "no file specified"));

	error = pdf_load_object(&obj, xref, num, 0);
	if (error)
		die(error);

	if (isimage(obj))
		saveimage(num);
	else if (isfontdesc(obj))
		savefont(obj, num);

	fz_drop_obj(ctx, obj);
}
示例#20
0
void
fz_array_put(fz_obj *obj, int i, fz_obj *item)
{
	RESOLVE(obj);

	if (!obj)
		return; /* Can't warn :( */
	if (obj->kind != FZ_ARRAY)
		fz_warn(obj->ctx, "assert: not an array (%s)", fz_objkindstr(obj));
	else if (i < 0)
		fz_warn(obj->ctx, "assert: index %d < 0", i);
	else if (i >= obj->u.a.len)
		fz_warn(obj->ctx, "assert: index %d > length %d", i, obj->u.a.len);
	else
	{
		if (obj->u.a.items[i])
			fz_drop_obj(obj->u.a.items[i]);
		obj->u.a.items[i] = fz_keep_obj(item);
	}
}
示例#21
0
/* Replace numbered object -- for use by pdfclean and similar tools */
void
pdf_update_object(pdf_xref *xref, int num, int gen, fz_obj *newobj)
{
	pdf_xref_entry *x;

	if (num < 0 || num >= xref->len)
	{
		fz_warn("object out of range (%d %d R); xref size %d", num, gen, xref->len);
		return;
	}

	x = &xref->table[num];

	if (x->obj)
		fz_drop_obj(x->obj);

	x->obj = fz_keep_obj(newobj);
	x->type = 'n';
	x->ofs = 0;
}
示例#22
0
static void
xps_hacky_get_prop(fz_context *ctx, char *data, fz_obj *dict, char *name, char *tag_name)
{
	char *start, *end;
	fz_obj *value;

	start = strstr(data, tag_name);
	if (!start || start == data || start[-1] != '<')
		return;
	end = strstr(start + 1, tag_name);
	start = strchr(start, '>');
	if (!start || !end || start >= end || end[-2] != '<' || end[-1] != '/')
		return;

	for (start++; iswhite(*start); start++);
	for (end -= 3; iswhite(*end) && end > start; end--);

	value = fz_new_string(ctx, start, end - start + 1);
	fz_dict_puts(ctx, dict, name, value);
	fz_drop_obj(ctx, value);
}
示例#23
0
文件: res_font.c 项目: plotnick/mupdf
void
fz_drop_font(fz_context *ctx, fz_font *font)
{
	int fterr;
	int i, drop;

	fz_lock(ctx, FZ_LOCK_ALLOC);
	drop = (font && --font->refs == 0);
	fz_unlock(ctx, FZ_LOCK_ALLOC);
	if (!drop)
		return;

	if (font->t3procs)
	{
		if (font->t3resources)
			fz_drop_obj(font->t3resources);
		for (i = 0; i < 256; i++)
			if (font->t3procs[i])
				fz_drop_buffer(ctx, font->t3procs[i]);
		fz_free(ctx, font->t3procs);
		fz_free(ctx, font->t3widths);
		fz_free(ctx, font->t3flags);
	}

	if (font->ft_face)
	{
		fz_lock(ctx, FZ_LOCK_FREETYPE);
		fterr = FT_Done_Face((FT_Face)font->ft_face);
		fz_unlock(ctx, FZ_LOCK_FREETYPE);
		if (fterr)
			fz_warn(ctx, "freetype finalizing face: %s", ft_error_string(fterr));
		fz_drop_freetype(ctx);
	}

	fz_free(ctx, font->ft_file);
	fz_free(ctx, font->ft_data);
	fz_free(ctx, font->bbox_table);
	fz_free(ctx, font->width_table);
	fz_free(ctx, font);
}
示例#24
0
static void saveimage(int num)
{
	fz_error error;
	fz_pixmap *img;
	fz_obj *ref;
	char name[1024];

	ref = fz_new_indirect(ctx, num, 0, xref);

	/* TODO: detect DCTD and save as jpeg */

	error = pdf_load_image(&img, xref, ref);
	if (error)
		die(error);

	if (dorgb && img->colorspace && img->colorspace != fz_device_rgb)
	{
		fz_pixmap *temp;
		temp = fz_new_pixmap_with_rect(ctx, fz_device_rgb, fz_bound_pixmap(img));
		fz_convert_pixmap(ctx, img, temp);
		fz_drop_pixmap(ctx, img);
		img = temp;
	}

	if (img->n <= 4)
	{
		sprintf(name, "img-%04d.png", num);
		printf("extracting image %s\n", name);
		fz_write_png(ctx, img, name, 0);
	}
	else
	{
		sprintf(name, "img-%04d.pam", num);
		printf("extracting image %s\n", name);
		fz_write_pam(ctx, img, name, 0);
	}

	fz_drop_pixmap(ctx, img);
	fz_drop_obj(ctx, ref);
}
示例#25
0
static int
xps_decode_tiff_fax(struct tiff *tiff, int comp, fz_stream *chain, byte *wp, int wlen)
{
	fz_stream *stm;
	fz_obj *params;
	fz_obj *columns, *rows, *black_is_1, *k, *encoded_byte_align;
	int n;
	fz_context *ctx = tiff->ctx;

	columns = fz_new_int(ctx, tiff->imagewidth);
	rows = fz_new_int(ctx, tiff->imagelength);
	black_is_1 = fz_new_bool(ctx, tiff->photometric == 0);
	k = fz_new_int(ctx, comp == 4 ? -1 : 0);
	encoded_byte_align = fz_new_bool(ctx, comp == 2);

	params = fz_new_dict(ctx, 5);
	fz_dict_puts(ctx, params, "Columns", columns);
	fz_dict_puts(ctx, params, "Rows", rows);
	fz_dict_puts(ctx, params, "BlackIs1", black_is_1);
	fz_dict_puts(ctx, params, "K", k);
	fz_dict_puts(ctx, params, "EncodedByteAlign", encoded_byte_align);

	fz_drop_obj(ctx, columns);
	fz_drop_obj(ctx, rows);
	fz_drop_obj(ctx, black_is_1);
	fz_drop_obj(ctx, k);
	fz_drop_obj(ctx, encoded_byte_align);

	stm = fz_open_faxd(chain, params);
	n = fz_read(stm, wp, wlen);
	fz_close(stm);
	fz_drop_obj(ctx, params);

	if (n < 0)
		return fz_error_note(ctx, n, "cannot read fax strip");
	return fz_okay;
}
示例#26
0
static void writeobject(int num, int gen)
{
	fz_obj *obj;
	fz_obj *type;

	obj = pdf_load_object(xref, num, gen);

	/* skip ObjStm and XRef objects */
	if (fz_is_dict(obj))
	{
		type = fz_dict_gets(obj, "Type");
		if (fz_is_name(type) && !strcmp(fz_to_name(type), "ObjStm"))
		{
			uselist[num] = 0;
			fz_drop_obj(obj);
			return;
		}
		if (fz_is_name(type) && !strcmp(fz_to_name(type), "XRef"))
		{
			uselist[num] = 0;
			fz_drop_obj(obj);
			return;
		}
	}

	if (!pdf_is_stream(xref, num, gen))
	{
		fprintf(out, "%d %d obj\n", num, gen);
		fz_fprint_obj(out, obj, doexpand == 0);
		fprintf(out, "endobj\n\n");
	}
	else
	{
		int dontexpand = 0;
		if (doexpand != 0 && doexpand != expand_all)
		{
			fz_obj *o;

			if ((o = fz_dict_gets(obj, "Type"), !strcmp(fz_to_name(o), "XObject")) &&
				(o = fz_dict_gets(obj, "Subtype"), !strcmp(fz_to_name(o), "Image")))
				dontexpand = !(doexpand & expand_images);
			if (o = fz_dict_gets(obj, "Type"), !strcmp(fz_to_name(o), "Font"))
				dontexpand = !(doexpand & expand_fonts);
			if (o = fz_dict_gets(obj, "Type"), !strcmp(fz_to_name(o), "FontDescriptor"))
				dontexpand = !(doexpand & expand_fonts);
			if ((o = fz_dict_gets(obj, "Length1")) != NULL)
				dontexpand = !(doexpand & expand_fonts);
			if ((o = fz_dict_gets(obj, "Length2")) != NULL)
				dontexpand = !(doexpand & expand_fonts);
			if ((o = fz_dict_gets(obj, "Length3")) != NULL)
				dontexpand = !(doexpand & expand_fonts);
			if (o = fz_dict_gets(obj, "Subtype"), !strcmp(fz_to_name(o), "Type1C"))
				dontexpand = !(doexpand & expand_fonts);
			if (o = fz_dict_gets(obj, "Subtype"), !strcmp(fz_to_name(o), "CIDFontType0C"))
				dontexpand = !(doexpand & expand_fonts);
		}
		if (doexpand && !dontexpand && !pdf_is_jpx_image(ctx, obj))
			expandstream(obj, num, gen);
		else
			copystream(obj, num, gen);
	}

	fz_drop_obj(obj);
}
示例#27
0
static void retainpages(int argc, char **argv)
{
	fz_obj *oldroot, *root, *pages, *kids, *countobj, *parent, *olddests;

	/* Keep only pages/type and (reduced) dest entries to avoid
	 * references to unretained pages */
	oldroot = fz_dict_gets(xref->trailer, "Root");
	pages = fz_dict_gets(oldroot, "Pages");
	olddests = pdf_load_name_tree(xref, "Dests");

	root = fz_new_dict(ctx, 2);
	fz_dict_puts(root, "Type", fz_dict_gets(oldroot, "Type"));
	fz_dict_puts(root, "Pages", fz_dict_gets(oldroot, "Pages"));

	pdf_update_object(xref, fz_to_num(oldroot), fz_to_gen(oldroot), root);

	fz_drop_obj(root);

	/* Create a new kids array with only the pages we want to keep */
	parent = fz_new_indirect(ctx, fz_to_num(pages), fz_to_gen(pages), xref);
	kids = fz_new_array(ctx, 1);

	/* Retain pages specified */
	while (argc - fz_optind)
	{
		int page, spage, epage;
		char *spec, *dash;
		char *pagelist = argv[fz_optind];

		spec = fz_strsep(&pagelist, ",");
		while (spec)
		{
			dash = strchr(spec, '-');

			if (dash == spec)
				spage = epage = pdf_count_pages(xref);
			else
				spage = epage = atoi(spec);

			if (dash)
			{
				if (strlen(dash) > 1)
					epage = atoi(dash + 1);
				else
					epage = pdf_count_pages(xref);
			}

			if (spage > epage)
				page = spage, spage = epage, epage = page;

			if (spage < 1)
				spage = 1;
			if (epage > pdf_count_pages(xref))
				epage = pdf_count_pages(xref);

			for (page = spage; page <= epage; page++)
			{
				fz_obj *pageobj = xref->page_objs[page-1];
				fz_obj *pageref = xref->page_refs[page-1];

				fz_dict_puts(pageobj, "Parent", parent);

				/* Store page object in new kids array */
				fz_array_push(kids, pageref);
			}

			spec = fz_strsep(&pagelist, ",");
		}

		fz_optind++;
	}

	fz_drop_obj(parent);

	/* Update page count and kids array */
	countobj = fz_new_int(ctx, fz_array_len(kids));
	fz_dict_puts(pages, "Count", countobj);
	fz_drop_obj(countobj);
	fz_dict_puts(pages, "Kids", kids);
	fz_drop_obj(kids);

	/* Also preserve the (partial) Dests name tree */
	if (olddests)
	{
		int i;
		fz_obj *names = fz_new_dict(ctx, 1);
		fz_obj *dests = fz_new_dict(ctx, 1);
		fz_obj *names_list = fz_new_array(ctx, 32);

		for (i = 0; i < fz_dict_len(olddests); i++)
		{
			fz_obj *key = fz_dict_get_key(olddests, i);
			fz_obj *val = fz_dict_get_val(olddests, i);
			fz_obj *key_str = fz_new_string(ctx, fz_to_name(key), strlen(fz_to_name(key)));
			fz_obj *dest = fz_dict_gets(val, "D");

			dest = fz_array_get(dest ? dest : val, 0);
			if (fz_array_contains(fz_dict_gets(pages, "Kids"), dest))
			{
				fz_array_push(names_list, key_str);
				fz_array_push(names_list, val);
			}
			fz_drop_obj(key_str);
		}

		root = fz_dict_gets(xref->trailer, "Root");
		fz_dict_puts(dests, "Names", names_list);
		fz_dict_puts(names, "Dests", dests);
		fz_dict_puts(root, "Names", names);

		fz_drop_obj(names);
		fz_drop_obj(dests);
		fz_drop_obj(names_list);
		fz_drop_obj(olddests);
	}
}
示例#28
0
fz_error
pdf_open_xref_with_stream(pdf_xref **xrefp, fz_stream *file, char *password)
{
	pdf_xref *xref;
	fz_error error;
	fz_obj *encrypt, *id;
	fz_obj *dict, *obj;
	int i, repaired = 0;

	/* install pdf specific callback */
	fz_resolve_indirect = pdf_resolve_indirect;

	xref = fz_malloc(sizeof(pdf_xref));

	memset(xref, 0, sizeof(pdf_xref));

	xref->file = fz_keep_stream(file);

	error = pdf_load_xref(xref, xref->scratch, sizeof xref->scratch);
	if (error)
	{
		fz_catch(error, "trying to repair");
		if (xref->table)
		{
			fz_free(xref->table);
			xref->table = NULL;
			xref->len = 0;
		}
		if (xref->trailer)
		{
			fz_drop_obj(xref->trailer);
			xref->trailer = NULL;
		}
		error = pdf_repair_xref(xref, xref->scratch, sizeof xref->scratch);
		if (error)
		{
			pdf_free_xref(xref);
			return fz_rethrow(error, "cannot repair document");
		}
		repaired = 1;
	}

	encrypt = fz_dict_gets(xref->trailer, "Encrypt");
	id = fz_dict_gets(xref->trailer, "ID");
	if (fz_is_dict(encrypt))
	{
		error = pdf_new_crypt(&xref->crypt, encrypt, id);
		if (error)
		{
			pdf_free_xref(xref);
			return fz_rethrow(error, "cannot decrypt document");
		}
	}

	if (pdf_needs_password(xref))
	{
		/* Only care if we have a password */
		if (password)
		{
			int okay = pdf_authenticate_password(xref, password);
			if (!okay)
			{
				pdf_free_xref(xref);
				return fz_throw("invalid password");
			}
		}
	}

	if (repaired)
	{
		int hasroot, hasinfo;

		error = pdf_repair_obj_stms(xref);
		if (error)
		{
			pdf_free_xref(xref);
			return fz_rethrow(error, "cannot repair document");
		}

		hasroot = fz_dict_gets(xref->trailer, "Root") != NULL;
		hasinfo = fz_dict_gets(xref->trailer, "Info") != NULL;

		for (i = 1; i < xref->len; i++)
		{
			if (xref->table[i].type == 0 || xref->table[i].type == 'f')
				continue;

			error = pdf_load_object(&dict, xref, i, 0);
			if (error)
			{
				fz_catch(error, "ignoring broken object (%d 0 R)", i);
				continue;
			}

			if (!hasroot)
			{
				obj = fz_dict_gets(dict, "Type");
				if (fz_is_name(obj) && !strcmp(fz_to_name(obj), "Catalog"))
				{
					obj = fz_new_indirect(i, 0, xref);
					fz_dict_puts(xref->trailer, "Root", obj);
					fz_drop_obj(obj);
				}
			}

			if (!hasinfo)
			{
				if (fz_dict_gets(dict, "Creator") || fz_dict_gets(dict, "Producer"))
				{
					obj = fz_new_indirect(i, 0, xref);
					fz_dict_puts(xref->trailer, "Info", obj);
					fz_drop_obj(obj);
				}
			}

			fz_drop_obj(dict);
		}
	}

	error = pdf_read_ocg(xref);
	if (error)
	{
		pdf_free_xref(xref);
		return fz_rethrow(error, "Broken Optional Content");
	}

	*xrefp = xref;
	return fz_okay;
}
示例#29
0
static fz_error
pdf_load_obj_stm(pdf_xref *xref, int num, int gen, char *buf, int cap)
{
	fz_error error;
	fz_stream *stm;
	fz_obj *objstm;
	int *numbuf;
	int *ofsbuf;

	fz_obj *obj;
	int first;
	int count;
	int i, n;
	int tok;

	error = pdf_load_object(&objstm, xref, num, gen);
	if (error)
		return fz_rethrow(error, "cannot load object stream object (%d %d R)", num, gen);

	count = fz_to_int(fz_dict_gets(objstm, "N"));
	first = fz_to_int(fz_dict_gets(objstm, "First"));

	numbuf = fz_calloc(count, sizeof(int));
	ofsbuf = fz_calloc(count, sizeof(int));

	error = pdf_open_stream(&stm, xref, num, gen);
	if (error)
	{
		error = fz_rethrow(error, "cannot open object stream (%d %d R)", num, gen);
		goto cleanupbuf;
	}

	for (i = 0; i < count; i++)
	{
		error = pdf_lex(&tok, stm, buf, cap, &n);
		if (error || tok != PDF_TOK_INT)
		{
			error = fz_rethrow(error, "corrupt object stream (%d %d R)", num, gen);
			goto cleanupstm;
		}
		numbuf[i] = atoi(buf);

		error = pdf_lex(&tok, stm, buf, cap, &n);
		if (error || tok != PDF_TOK_INT)
		{
			error = fz_rethrow(error, "corrupt object stream (%d %d R)", num, gen);
			goto cleanupstm;
		}
		ofsbuf[i] = atoi(buf);
	}

	fz_seek(stm, first, 0);

	for (i = 0; i < count; i++)
	{
		fz_seek(stm, first + ofsbuf[i], 0);

		error = pdf_parse_stm_obj(&obj, xref, stm, buf, cap);
		if (error)
		{
			error = fz_rethrow(error, "cannot parse object %d in stream (%d %d R)", i, num, gen);
			goto cleanupstm;
		}

		if (numbuf[i] < 1 || numbuf[i] >= xref->len)
		{
			fz_drop_obj(obj);
			error = fz_throw("object id (%d 0 R) out of range (0..%d)", numbuf[i], xref->len - 1);
			goto cleanupstm;
		}

		if (xref->table[numbuf[i]].type == 'o' && xref->table[numbuf[i]].ofs == num)
		{
			if (xref->table[numbuf[i]].obj)
				fz_drop_obj(xref->table[numbuf[i]].obj);
			xref->table[numbuf[i]].obj = obj;
		}
		else
		{
			fz_drop_obj(obj);
		}
	}

	fz_close(stm);
	fz_free(ofsbuf);
	fz_free(numbuf);
	fz_drop_obj(objstm);
	return fz_okay;

cleanupstm:
	fz_close(stm);
cleanupbuf:
	fz_free(ofsbuf);
	fz_free(numbuf);
	fz_drop_obj(objstm);
	return error; /* already rethrown */
}
示例#30
0
static fz_outline *
pdf_load_outline_imp(pdf_xref *xref, fz_obj *dict)
{
    pdf_link *link;
    fz_outline *node;
    fz_obj *obj;
    /* SumatraPDF: prevent potential stack overflow */
    fz_outline *prev, *root = NULL;
    fz_obj *origDict = dict;
    fz_context *ctx = xref->ctx;

    if (fz_is_null(ctx, dict))
        return NULL;

    /* SumatraPDF: prevent cyclic outlines */
    do
    {
        if (fz_dict_gets(ctx, dict, ".seen"))
            break;
        obj = fz_new_null(ctx);
        fz_dict_puts(ctx, dict, ".seen", obj);
        fz_drop_obj(ctx, obj);

        node = fz_malloc(ctx, sizeof(fz_outline));
        node->title = NULL;
        node->page = -1;
        node->down = NULL;
        node->next = NULL;

        obj = fz_dict_gets(ctx, dict, "Title");
        if (obj)
            node->title = pdf_to_utf8(ctx, obj);

        /* SumatraPDF: support expansion states */
        node->is_open = fz_to_int(ctx, fz_dict_gets(ctx, dict, "Count")) >= 0;
        /* SumatraPDF: extended outline actions */
        node->data = node->free_data = NULL;

        if (fz_dict_gets(ctx, dict, "Dest") || fz_dict_gets(ctx, dict, "A"))
        {
            link = pdf_load_link(xref, dict);
            if (link) /* SumatraPDF: don't crash if it's no link after all */
            {
                if (link->kind == PDF_LINK_GOTO)
                    node->page = pdf_find_page_number(xref, fz_array_get(ctx, link->dest, 0));
                /* SumatraPDF: extended outline actions */
                node->data = link;
                node->free_data = pdf_free_link;
            }
        }

        obj = fz_dict_gets(ctx, dict, "First");
        if (obj)
            node->down = pdf_load_outline_imp(xref, obj);

        /* SumatraPDF: prevent potential stack overflow */
        if (!root)
            prev = root = node;
        else
            prev = prev->next = node;

        dict = fz_dict_gets(ctx, dict, "Next");
    } while (dict && !fz_is_null(ctx, dict));
    node = root;
    /* SumatraPDF: prevent cyclic outlines */
    for (dict = origDict; dict && fz_dict_gets(ctx, dict, ".seen"); dict = fz_dict_gets(ctx, dict, "Next"))
        fz_dict_dels(ctx, dict, ".seen");

    return node;
}