/* pCOS sample application for dumping PDF information
 *
 * $Id: dumper.c,v 1.23 2006/09/25 12:17:32 tm Exp $
 */

#include <stdio.h>
#include <stdarg.h>

#include "pcoslib.h"

int
main(int argc, char **argv)
{
    pCOS	*p;

    if (argc != 2)
    {   
        fprintf(stderr, "usage: dumper <filename>\n");
        return(2);
    }

    if ((p = pCOS_new()) == (pCOS *) 0)         /* out of memory */
    {
	fprintf(stderr, "dumper: out of memory\n");
	return 99;
    }

    pCOS_TRY(p)
    {
	int		count, pcosmode, plainmetadata;
	int		objtype, i, doc;
	const char	*docoptlist = "requiredmode=minimum";
	const char	*globaloptlist = "";

	pCOS_set_option(p, globaloptlist);

	if ((doc = pCOS_open_document(p, argv[1], 0, docoptlist)) == -1)
	{
	    printf("ERROR: %s\n", pCOS_get_errmsg(p));
	    pCOS_delete(p);
	    return 98;
	}

	/* --------- general information (always available) */

	pcosmode = (int) pCOS_get_number(p, doc, "pcosmode");

	printf("   File name: %s\n", pCOS_get_string(p, doc, "filename"));

	printf(" PDF version: %.1f\n",
	    pCOS_get_number(p, doc, "pdfversion")/10);

	printf("  Encryption: %s\n",
	    pCOS_get_string(p, doc, "encrypt/description"));

	printf("   Master pw: %s\n",
	    pCOS_get_number(p, doc, "encrypt/master") ? "yes" : "no");

	printf("     User pw: %s\n",
	    pCOS_get_number(p, doc, "encrypt/user") ? "yes" : "no");

	printf("Text copying: %s\n",
	    pCOS_get_number(p, doc, "encrypt/nocopy") ? "no" : "yes");

	printf("  Linearized: %s\n",
	    pCOS_get_number(p, doc, "linearized") ? "yes" : "no");

	if (pcosmode == 0)
	{
	    printf("Minimum mode: no more information available\n\n");
	    pCOS_close_document(p, doc);
	    pCOS_delete(p);
	    return 0;
	}

	/* --------- more details (requires at least user password) */

	printf("PDF/X status: %s\n", pCOS_get_string(p, doc, "pdfx"));

	printf("PDF/A status: %s\n", pCOS_get_string(p, doc, "pdfa"));

	printf("  Tagged PDF: %s\n\n",
	    pCOS_get_number(p, doc, "tagged") ? "yes" : "no");

	printf("No. of pages: %d\n",
	    (int) pCOS_get_number(p, doc, "length:pages"));

	printf(" Page 1 size: width=%g, height=%g\n",
	    pCOS_get_number(p, doc, "pages[%d]/width", 0),
	    pCOS_get_number(p, doc, "pages[%d]/height", 0));

	count = (int) pCOS_get_number(p, doc, "length:fonts");
	printf("No. of fonts: %d\n", count);

	for (i=0; i < count; i++)
	{
	    if (pCOS_get_number(p, doc, "fonts[%d]/embedded", i))
		printf("embedded ");
	    else
		printf("unembedded ");

	    printf("%s font ",
		pCOS_get_string(p, doc, "fonts[%d]/type", i));
	    printf("%s\n",
		pCOS_get_string(p, doc, "fonts[%d]/name", i));
	}

	printf("\n");

	plainmetadata = (int)
	    pCOS_get_number(p, doc, "encrypt/plainmetadata");

	if (pcosmode == 1 && !plainmetadata &&
	    ((int) pCOS_get_number(p, doc, "encrypt/nocopy")))
	{
	    printf("Restricted mode: no more information available\n\n");
	    pCOS_close_document(p, doc);
	    pCOS_delete(p);
	    return 0;
	}

	/* --------- document info keys and XMP metadata (requires master pw
	 * or plaintext metadata)
	 */

	count = (int) pCOS_get_number(p, doc, "length:/Info");

	for (i=0; i < count; i++)
	{
	    objtype = (int) pCOS_get_number(p, doc, "type:/Info[%d]", i);
	    printf("%12s: ", pCOS_get_string(p, doc, "/Info[%d].key", i));

	    /* Info entries can be stored as string or name objects */
	    if (objtype == pcos_ot_string || objtype == pcos_ot_name)
	    {
		printf("'%10s'\n", pCOS_get_string(p, doc, "/Info[%d]", i));
	    }
	    else
	    {
		printf("(%s object)\n",
		    pCOS_get_string(p, doc, "type:/Info[%d]", i));
	    }
	}

	printf("\nXMP meta data: ");

	objtype = (int)pCOS_get_number(p, doc, "type:/Root/Metadata");
	if (objtype == pcos_ot_stream)
	{
	    const char *contents;
	    int len;

	    contents = (const char *)
		pCOS_get_stream(p, doc, &len, "", "/Root/Metadata");
	    printf("%d bytes ", len);

	    /* This demonstrates Unicode conversion */
	    (void) pCOS_utf8_to_utf16(p, contents, "utf16", &len);
	    printf("(%d Unicode characters)\n\n", len/2);
	}
	else
	{
	    printf("not present\n\n");
	}

	pCOS_close_document(p, doc);
    }
    pCOS_CATCH(p)
    {
        printf("pCOS exception occurred in dumper:\n");
        printf("[%d] %s: %s\n",
            pCOS_get_errnum(p), pCOS_get_apiname(p), pCOS_get_errmsg(p));
    }
    pCOS_delete(p);

    return 0;
}
