static void complete_signatures(fz_context *ctx, pdf_document *doc, pdf_write_state *opts, const char *filename)
{
	pdf_unsaved_sig *usig;
	char buf[5120];
	int s;
	int i;
	int last_end;
	FILE *f;

	for (s = 0; s < doc->num_incremental_sections; s++)
	{
		pdf_xref *xref = &doc->xref_sections[doc->num_incremental_sections - s - 1];

		if (xref->unsaved_sigs)
		{
			pdf_obj *byte_range;

			f = fopen(filename, "rb+");
			if (!f)
				fz_throw(ctx, FZ_ERROR_GENERIC, "Failed to open %s to complete signatures", filename);

			/* Locate the byte ranges and contents in the saved file */
			for (usig = xref->unsaved_sigs; usig; usig = usig->next)
			{
				char *bstr, *cstr, *fstr;
				int pnum = pdf_obj_parent_num(ctx, pdf_dict_getl(ctx, usig->field, PDF_NAME_V, PDF_NAME_ByteRange, NULL));
				fseek(f, opts->ofs_list[pnum], SEEK_SET);
				(void)fread(buf, 1, sizeof(buf), f);
				buf[sizeof(buf)-1] = 0;

				bstr = strstr(buf, "/ByteRange");
				cstr = strstr(buf, "/Contents");
				fstr = strstr(buf, "/Filter");

				if (bstr && cstr && fstr && bstr < cstr && cstr < fstr)
				{
					usig->byte_range_start = bstr - buf + 10 + opts->ofs_list[pnum];
					usig->byte_range_end = cstr - buf + opts->ofs_list[pnum];
					usig->contents_start = cstr - buf + 9 + opts->ofs_list[pnum];
					usig->contents_end = fstr - buf + opts->ofs_list[pnum];
				}
			}

			/* Recreate ByteRange with correct values. Initially store the
			* recreated object in the first of the unsaved signatures */
			byte_range = pdf_new_array(ctx, doc, 4);
			pdf_dict_putl_drop(ctx, xref->unsaved_sigs->field, byte_range, PDF_NAME_V, PDF_NAME_ByteRange, NULL);

			last_end = 0;
			for (usig = xref->unsaved_sigs; usig; usig = usig->next)
			{
				pdf_array_push_drop(ctx, byte_range, pdf_new_int(ctx, doc, last_end));
				pdf_array_push_drop(ctx, byte_range, pdf_new_int(ctx, doc, usig->contents_start - last_end));
				last_end = usig->contents_end;
			}
			pdf_array_push_drop(ctx, byte_range, pdf_new_int(ctx, doc, last_end));
			pdf_array_push_drop(ctx, byte_range, pdf_new_int(ctx, doc, xref->end_ofs - last_end));

			/* Copy the new ByteRange to the other unsaved signatures */
			for (usig = xref->unsaved_sigs->next; usig; usig = usig->next)
				pdf_dict_putl_drop(ctx, usig->field, pdf_copy_array(ctx, byte_range), PDF_NAME_V, PDF_NAME_ByteRange, NULL);

			/* Write the byte range into buf, padding with spaces*/
			i = pdf_sprint_obj(ctx, buf, sizeof(buf), byte_range, 1);
			memset(buf+i, ' ', sizeof(buf)-i);

			/* Write the byte range to the file */
			for (usig = xref->unsaved_sigs; usig; usig = usig->next)
			{
				fseek(f, usig->byte_range_start, SEEK_SET);
				fwrite(buf, 1, usig->byte_range_end - usig->byte_range_start, f);
			}

			fclose(f);

			/* Write the digests into the file */
			for (usig = xref->unsaved_sigs; usig; usig = usig->next)
				pdf_write_digest(ctx, doc, filename, byte_range, usig->contents_start, usig->contents_end - usig->contents_start, usig->signer);

			/* delete the unsaved_sigs records */
			while ((usig = xref->unsaved_sigs) != NULL)
			{
				xref->unsaved_sigs = usig->next;
				pdf_drop_obj(ctx, usig->field);
				pdf_drop_signer(ctx, usig->signer);
				fz_free(ctx, usig);
			}
		}
	}
}