<commit_before>/*
 * pdfshow -- the ultimate pdf debugging tool
 */

#include "mupdf/pdf.h"

static pdf_document *doc = NULL;
static fz_context *ctx = NULL;
static fz_output *out = NULL;
static int showbinary = 0;
static int showdecode = 1;
static int showcolumn;

static void usage(void)
{
	fprintf(stderr, "usage: mutool show [options] file.pdf [grep] [xref] [trailer] [pagetree] [outline] [object numbers]\n");
	fprintf(stderr, "\t-p -\tpassword\n");
	fprintf(stderr, "\t-o -\toutput file\n");
	fprintf(stderr, "\t-b\tprint streams as binary data\n");
	fprintf(stderr, "\t-e\tprint encoded streams (don't decode)\n");
	exit(1);
}

static void showtrailer(void)
{
	if (!doc)
		fz_throw(ctx, FZ_ERROR_GENERIC, "no file specified");
	fz_printf(ctx, out, "trailer\n");
	pdf_print_obj(ctx, out, pdf_trailer(ctx, doc), 0);
	fz_printf(ctx, out, "\n");
}

static void showencrypt(void)
{
	pdf_obj *encrypt;

	if (!doc)
		fz_throw(ctx, FZ_ERROR_GENERIC, "no file specified");
	encrypt = pdf_dict_get(ctx, pdf_trailer(ctx, doc), PDF_NAME_Encrypt);
	if (!encrypt)
		fz_throw(ctx, FZ_ERROR_GENERIC, "document not encrypted");
	fz_printf(ctx, out, "encryption dictionary\n");
	pdf_print_obj(ctx, out, pdf_resolve_indirect(ctx, encrypt), 0);
	fz_printf(ctx, out, "\n");
}

static void showxref(void)
{
	if (!doc)
		fz_throw(ctx, FZ_ERROR_GENERIC, "no file specified");
	pdf_print_xref(ctx, doc);
	fz_printf(ctx, out, "\n");
}

static void showpagetree(void)
{
	pdf_obj *ref;
	int count;
	int i;

	if (!doc)
		fz_throw(ctx, FZ_ERROR_GENERIC, "no file specified");

	count = pdf_count_pages(ctx, doc);
	for (i = 0; i < count; i++)
	{
		ref = pdf_lookup_page_obj(ctx, doc, i);
		fz_printf(ctx, out, "page %d = %d 0 R\n", i + 1, pdf_to_num(ctx, ref));
	}
	fz_printf(ctx, out, "\n");
}

static void showsafe(unsigned char *buf, size_t n)
{
	size_t i;
	for (i = 0; i < n; i++) {
		if (buf[i] == '\r' || buf[i] == '\n') {
			putchar('\n');
			showcolumn = 0;
		}
		else if (buf[i] < 32 || buf[i] > 126) {
			putchar('.');
			showcolumn ++;
		}
		else {
			putchar(buf[i]);
			showcolumn ++;
		}
		if (showcolumn == 79) {
			putchar('\n');
			showcolumn = 0;
		}
	}
}

static void showstream(int num)
{
	fz_stream *stm;
	unsigned char buf[2048];
	size_t n;

	showcolumn = 0;

	if (showdecode)
		stm = pdf_open_stream(ctx, doc, num);
	else
		stm = pdf_open_raw_stream(ctx, doc, num);

	while (1)
	{
		n = fz_read(ctx, stm, buf, sizeof buf);
		if (n == 0)
			break;
		if (showbinary)
			fz_write(ctx, out, buf, n);
		else
			showsafe(buf, n);
	}

	fz_drop_stream(ctx, stm);
}

static void showobject(int num)
{
	pdf_obj *obj;

	if (!doc)
		fz_throw(ctx, FZ_ERROR_GENERIC, "no file specified");

	obj = pdf_load_object(ctx, doc, num);

	if (pdf_is_stream(ctx, obj))
	{
		if (showbinary)
		{
			showstream(num);
		}
		else
		{
			fz_printf(ctx, out, "%d 0 obj\n", num);
			pdf_print_obj(ctx, out, obj, 0);
			fz_printf(ctx, out, "\nstream\n");
			showstream(num);
			fz_printf(ctx, out, "endstream\n");
			fz_printf(ctx, out, "endobj\n\n");
		}
	}
	else
	{
		fz_printf(ctx, out, "%d 0 obj\n", num);
		pdf_print_obj(ctx, out, obj, 0);
		fz_printf(ctx, out, "\nendobj\n\n");
	}

	pdf_drop_obj(ctx, obj);
}

static void showgrep(char *filename)
{
	pdf_obj *obj;
	int i, len;

	len = pdf_count_objects(ctx, doc);
	for (i = 0; i < len; i++)
	{
		pdf_xref_entry *entry = pdf_get_xref_entry(ctx, doc, i);
		if (entry->type == 'n' || entry->type == 'o')
		{
			fz_try(ctx)
			{
				obj = pdf_load_object(ctx, doc, i);
			}
			fz_catch(ctx)
			{
				fz_warn(ctx, "skipping object (%d 0 R)", i);
				continue;
			}

			pdf_sort_dict(ctx, obj);

			fz_printf(ctx, out, "%s:%d: ", filename, i);
			pdf_print_obj(ctx, out, obj, 1);

			pdf_drop_obj(ctx, obj);
		}
	}

	fz_printf(ctx, out, "%s:trailer: ", filename);
	pdf_print_obj(ctx, out, pdf_trailer(ctx, doc), 1);
}

static void showoutline(void)
{
	fz_outline *outline = fz_load_outline(ctx, (fz_document*)doc);
	fz_output *out = NULL;

	fz_var(out);
	fz_try(ctx)
	{
		out = fz_stdout(ctx);
		fz_print_outline(ctx, out, outline);
	}
	fz_always(ctx)
	{
		fz_drop_output(ctx, out);
		fz_drop_outline(ctx, outline);
	}
	fz_catch(ctx)
	{<commit_msg>Re-add line endings for mutool show grep.<commit_after>/*
 * pdfshow -- the ultimate pdf debugging tool
 */

#include "mupdf/pdf.h"

static pdf_document *doc = NULL;
static fz_context *ctx = NULL;
static fz_output *out = NULL;
static int showbinary = 0;
static int showdecode = 1;
static int showcolumn;

static void usage(void)
{
	fprintf(stderr, "usage: mutool show [options] file.pdf [grep] [xref] [trailer] [pagetree] [outline] [object numbers]\n");
	fprintf(stderr, "\t-p -\tpassword\n");
	fprintf(stderr, "\t-o -\toutput file\n");
	fprintf(stderr, "\t-b\tprint streams as binary data\n");
	fprintf(stderr, "\t-e\tprint encoded streams (don't decode)\n");
	exit(1);
}

static void showtrailer(void)
{
	if (!doc)
		fz_throw(ctx, FZ_ERROR_GENERIC, "no file specified");
	fz_printf(ctx, out, "trailer\n");
	pdf_print_obj(ctx, out, pdf_trailer(ctx, doc), 0);
	fz_printf(ctx, out, "\n");
}

static void showencrypt(void)
{
	pdf_obj *encrypt;

	if (!doc)
		fz_throw(ctx, FZ_ERROR_GENERIC, "no file specified");
	encrypt = pdf_dict_get(ctx, pdf_trailer(ctx, doc), PDF_NAME_Encrypt);
	if (!encrypt)
		fz_throw(ctx, FZ_ERROR_GENERIC, "document not encrypted");
	fz_printf(ctx, out, "encryption dictionary\n");
	pdf_print_obj(ctx, out, pdf_resolve_indirect(ctx, encrypt), 0);
	fz_printf(ctx, out, "\n");
}

static void showxref(void)
{
	if (!doc)
		fz_throw(ctx, FZ_ERROR_GENERIC, "no file specified");
	pdf_print_xref(ctx, doc);
	fz_printf(ctx, out, "\n");
}

static void showpagetree(void)
{
	pdf_obj *ref;
	int count;
	int i;

	if (!doc)
		fz_throw(ctx, FZ_ERROR_GENERIC, "no file specified");

	count = pdf_count_pages(ctx, doc);
	for (i = 0; i < count; i++)
	{
		ref = pdf_lookup_page_obj(ctx, doc, i);
		fz_printf(ctx, out, "page %d = %d 0 R\n", i + 1, pdf_to_num(ctx, ref));
	}
	fz_printf(ctx, out, "\n");
}

static void showsafe(unsigned char *buf, size_t n)
{
	size_t i;
	for (i = 0; i < n; i++) {
		if (buf[i] == '\r' || buf[i] == '\n') {
			putchar('\n');
			showcolumn = 0;
		}
		else if (buf[i] < 32 || buf[i] > 126) {
			putchar('.');
			showcolumn ++;
		}
		else {
			putchar(buf[i]);
			showcolumn ++;
		}
		if (showcolumn == 79) {
			putchar('\n');
			showcolumn = 0;
		}
	}
}

static void showstream(int num)
{
	fz_stream *stm;
	unsigned char buf[2048];
	size_t n;

	showcolumn = 0;

	if (showdecode)
		stm = pdf_open_stream(ctx, doc, num);
	else
		stm = pdf_open_raw_stream(ctx, doc, num);

	while (1)
	{
		n = fz_read(ctx, stm, buf, sizeof buf);
		if (n == 0)
			break;
		if (showbinary)
			fz_write(ctx, out, buf, n);
		else
			showsafe(buf, n);
	}

	fz_drop_stream(ctx, stm);
}

static void showobject(int num)
{
	pdf_obj *obj;

	if (!doc)
		fz_throw(ctx, FZ_ERROR_GENERIC, "no file specified");

	obj = pdf_load_object(ctx, doc, num);

	if (pdf_is_stream(ctx, obj))
	{
		if (showbinary)
		{
			showstream(num);
		}
		else
		{
			fz_printf(ctx, out, "%d 0 obj\n", num);
			pdf_print_obj(ctx, out, obj, 0);
			fz_printf(ctx, out, "\nstream\n");
			showstream(num);
			fz_printf(ctx, out, "endstream\n");
			fz_printf(ctx, out, "endobj\n\n");
		}
	}
	else
	{
		fz_printf(ctx, out, "%d 0 obj\n", num);
		pdf_print_obj(ctx, out, obj, 0);
		fz_printf(ctx, out, "\nendobj\n\n");
	}

	pdf_drop_obj(ctx, obj);
}

static void showgrep(char *filename)
{
	pdf_obj *obj;
	int i, len;

	len = pdf_count_objects(ctx, doc);
	for (i = 0; i < len; i++)
	{
		pdf_xref_entry *entry = pdf_get_xref_entry(ctx, doc, i);
		if (entry->type == 'n' || entry->type == 'o')
		{
			fz_try(ctx)
			{
				obj = pdf_load_object(ctx, doc, i);
			}
			fz_catch(ctx)
			{
				fz_warn(ctx, "skipping object (%d 0 R)", i);
				continue;
			}

			pdf_sort_dict(ctx, obj);

			fz_printf(ctx, out, "%s:%d: ", filename, i);
			pdf_print_obj(ctx, out, obj, 1);
			fz_printf(ctx, out, "\n");

			pdf_drop_obj(ctx, obj);
		}
	}

	fz_printf(ctx, out, "%s:trailer: ", filename);
	pdf_print_obj(ctx, out, pdf_trailer(ctx, doc), 1);
	fz_printf(ctx, out, "\n");
}

static void showoutline(void)
{
	fz_outline *outline = fz_load_outline(ctx, (fz_document*)doc);
	fz_output *out = NULL;

	fz_var(out);
	fz_try(ctx)
	{
		out = fz_stdout(ctx);
		fz_print_outline(ctx, out, outline);
	}
	fz_always(ctx)
	{
		fz_drop_output(ctx, out);
		fz_drop_outline(ctx, outline);
	}
	fz_catch(ctx)
	{
{'fraction_non_alphanumeric': 0.17399572141668648, 'fraction_numerical': 0.007844069408129309, 'mean_word_length': 3.929701230228471, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7211758', 'n_tokens_mistral': 3988, 'n_tokens_neox': 3675, 'n_words': 846}