/*
	Antenna House PDF Tool API V8.0
	C++ Interface sample program

	概要：文書情報の取得（バージョン・文書情報・PDFの開き方・セキュリティ情報）

	Copyright 2013-2026 Antenna House, Inc.
*/

#include < PdfTk.h >
#include < stdio.h >

using namespace PdfTk;

int showAction(PtlAction& action);
int showDest(PtlDest& dest);

int main(int argc, char* argv[])
{
	if (argc < 2) {
		printf("usage: GetDocInfo_2.exe in-pdf-file\n");
		return 1;
	}
	try
	{
		PtlParamInput input(argv[1]);
		PtlPDFDocument doc;

		// PDFファイルをロードします。
		doc.load(input);

		//PDFの文書プロパティ
		PtlDocProperty& docproperty = doc.getDocProperty();
		printf("PDF Version\n");
		switch (docproperty.getVersion())
		{
		case PtlDocProperty::PDF_VERSION::PDFV1_0:	// PDF-1.0
			printf(" major : 1\n");
			printf(" minor : 0\n");
			break;
		case PtlDocProperty::PDF_VERSION::PDFV1_1:	// PDF-1.1
			printf(" major : 1\n");
			printf(" minor : 1\n");
			break;
		case PtlDocProperty::PDF_VERSION::PDFV1_2:	// PDF-1.2
			printf(" major : 1\n");
			printf(" minor : 2\n");
			break;
		case PtlDocProperty::PDF_VERSION::PDFV1_3:	// PDF-1.3
			printf(" major : 1\n");
			printf(" minor : 3\n");
			break;
		case PtlDocProperty::PDF_VERSION::PDFV1_4:	// PDF-1.4
			printf(" major : 1\n");
			printf(" minor : 4\n");
			break;
		case PtlDocProperty::PDF_VERSION::PDFV1_5:	// PDF-1.5
			printf(" major : 1\n");
			printf(" minor : 5\n");
			break;
		case PtlDocProperty::PDF_VERSION::PDFV1_6:	// PDF-1.6
			printf(" major : 1\n");
			printf(" minor : 6\n");
			break;
		case PtlDocProperty::PDF_VERSION::PDFV1_7:	// PDF-1.7
			printf(" major : 1\n");
			printf(" minor : 7\n");
			break;
		case PtlDocProperty::PDF_VERSION::PDFV2_0:	// PDF-2.0
			printf(" major : 2\n");
			printf(" minor : 0\n");
			break;
		case PtlDocProperty::PDF_VERSION::PDFV_UNSUPPORTED:	// 未サポートのバージョン
			printf(" 未サポートのバージョン\n");
			break;
		}

		//PDFの文書情報
		printf("\n");
		PtlDocInfo& docinf = docproperty.getDocInfo();
		printf("Document Information\n");

		//タイトル取得
		PtlParamString title = docinf.getTitle();
		printf(" Title    : %s\n", title.c_str());

		//サブジェクト取得
		PtlParamString subject = docinf.getSubject();
		printf(" Subject  : %s\n", subject.c_str());

		//著者取得
		PtlParamString author = docinf.getAuthor();
		printf(" Author   : %s\n", author.c_str());

		//キーワード取得
		PtlParamString keywords = docinf.getKeywords();
		printf(" Keywords : %s\n", keywords.c_str());

		//クリエータ取得
		PtlParamString creator = docinf.getCreator();
		printf(" Creator  : %s\n", creator.c_str());

		//プロデューサ取得
		PtlParamString producer = docinf.getProducer();
		printf(" Producer : %s\n", producer.c_str());

		//作成日付を取得
		PtlDate creationDate = docinf.getCreationDate();
		printf(" CreationDate : %d/%d/%d %d:%d:%d\n"
			, creationDate.getYear()
			, creationDate.getMonth()
			, creationDate.getDay()
			, creationDate.getHour()
			, creationDate.getMin()
			, creationDate.getSec());

		//更新日付を取得
		PtlDate modDate = docinf.getModDate();
		printf(" ModifyDate  : %d/%d/%d %d:%d:%d\n"
			, modDate.getYear()
			, modDate.getMonth()
			, modDate.getDay()
			, modDate.getHour()
			, modDate.getMin()
			, modDate.getSec());

		// ページ数
		printf(" Max Page : %d\n", doc.getPageCount());

		// 開き方情報を取得
		printf("\n\n");
		printf("View Information\n");
		PtlOpenMode& openmode = docproperty.getOpenMode();

		//読み上げオプション取得
		switch (docproperty.getDirection()) {
		case PtlDocProperty::DIRECTION_L2R:
			printf(" Direction  : Left to Right\n");
			break;
		case PtlDocProperty::DIRECTION_R2L:
			printf(" Direction  : Right to Left )\n");
			break;
		}

		// ページレイアウトを取得
		switch (openmode.getPageLayout())
		{
		case PtlOpenMode::PAGE_LAYOUT_SINGLE_PAGE:	// 単一ページ
			printf(" PageLayout : SinglePage\n");
			break;
		case PtlOpenMode::PAGE_LAYOUT_ONE_COLUMN:	// 連続ページ
			printf(" PageLayout : OneColumn\n");
			break;
		case PtlOpenMode::PAGE_LAYOUT_TWO_COLUMN_LEFT:	// 奇数ページを左側にして連続見開きページ
			printf(" PageLayout : TwoColumnLeft\n");
			break;
		case PtlOpenMode::PAGE_LAYOUT_TWO_COLUMN_RIGHT:	// 奇数ページを右側にして連続見開きページ
			printf(" PageLayout : TwoColumnRight\n");
			break;
		case PtlOpenMode::PAGE_LAYOUT_TWO_PAGE_LEFT:	// 奇数ページを左側にして見開きページ
			printf(" PageLayout : TwoPageLeft\n");
			break;
		case PtlOpenMode::PAGE_LAYOUT_TWO_PAGE_RIGHT:	// 奇数ページを右側にして見開きページ
			printf(" PageLayout : TwoPageRight\n");
			break;
		}

		//  PageMode   : Use Outlines
		switch (openmode.getPageMode())
		{
			case PtlOpenMode::PAGE_MODE_USE_NONE:	// ページのみ表示
				printf(" PageMode   : Use None\n");
				break;
			case PtlOpenMode::PAGE_MODE_USE_OUTLINES:	// アウトラインパネルとページ
				printf(" PageMode   : Use Outlines\n");
				break;
			case PtlOpenMode::PAGE_MODE_USE_THUMBS:	// サムネイルパネルとページ
				printf(" PageMode   : Use Thumbs\n");
				break;
			case PtlOpenMode::PAGE_MODE_USE_OC:	// レイヤーパネルとページ
				printf(" PageMode   : Use OC\n");
				break;
			case PtlOpenMode::PAGE_MODE_USE_ATTACHMENTS:	// 添付ファイルパネルとページ
				printf(" PageMode   : Use Atttachments\n");
				break;
		}

		// ウィンドウオプションを取得
		bool fitwindow
			= (openmode.getWindowOption() & PtlOpenMode::WINDOWS_OPTION_FIT_WINDOW)
			== PtlOpenMode::WINDOWS_OPTION_FIT_WINDOW;
		bool centerwindow
			= (openmode.getWindowOption() & PtlOpenMode::WINDOWS_OPTION_CENTER_WINDOW)
			== PtlOpenMode::WINDOWS_OPTION_CENTER_WINDOW;
		bool fullscreen
			= (openmode.getWindowOption() & PtlOpenMode::WINDOWS_OPTION_FULL_SCREEN)
			== PtlOpenMode::WINDOWS_OPTION_FULL_SCREEN;
		if (fitwindow) {
			printf(" FitWindow  : true\n");
		}
		else{
			printf(" FitWindow  : false\n");
		}
		if (centerwindow){
			printf(" CenterWindow : true\n");
		}
		else{
			printf(" CenterWindow : false\n");
		}
		if (fullscreen)	{
			printf(" Full Screen  : true\n");
		}
		else {
			printf(" Full Screen  : false\n");
		}

		// ウィンドウのタイトルバーに文書タイトルを表示するかどうかを取得
		if (openmode.getDisplayDocTitle())
		{
			printf(" Display Doc Title  : true\n");
		}
		else
		{
			printf(" Display Doc Title  : false\n");
		}

		// ユーザーインターフェイスオプションを取得
		int uiopt = openmode.getUIOption();
		bool hidemenu
			= (openmode.getUIOption() & PtlOpenMode::UI_OPTION_HIDE_MENUBAR)
			== PtlOpenMode::UI_OPTION_HIDE_MENUBAR;
		bool hidetool
			= (openmode.getUIOption() & PtlOpenMode::UI_OPTION_HIDE_TOOLBAR)
			== PtlOpenMode::UI_OPTION_HIDE_TOOLBAR;
		bool hidewinui
			= (openmode.getUIOption() & PtlOpenMode::UI_OPTION_HIDE_WINDOWUI)
			== PtlOpenMode::UI_OPTION_HIDE_WINDOWUI;
		if (hidemenu) {
			printf(" Hide Menubar  : true\n");
		}
		else {
			printf(" Hide Menubar : false\n");
		}
		if (hidetool) {
			printf(" Hide Toolbar : true\n");
		}
		else {
			printf(" Hide Toolbar : false\n");
		}
		if (hidewinui) {
			printf(" Hide Window UI  : true\n");
		}
		else {
			printf(" Hide Window UI : false\n");
		}

		// オープンアクションを取得
		showAction(openmode.getOpenAction());

		// カスタムプロパティを取得
		printf("\n\n");
		printf("Custom Property\n");
		PtlCustomProperties& customProperties = docproperty.getCustomProperties();
		int numCustomProperties = customProperties.getCount();
		for (int i = 0; i < numCustomProperties; ++i) {
			PtlCustomProperty prop = customProperties.get(i);
			printf(" Name  : %s\n", prop.getName().c_str());
			printf(" Value : %s\n", prop.getValue().c_str());
		}

		printf("\n\n");
		printf("Security Information\n");
		bool isEncrypted = doc.isEncrypted();
		if (!isEncrypted) {
			printf(" Not Encrypted.\n");
			return 0;
		}
		const PtlEncrypt& encrypt = doc.getEncrypt();
		int filterType = encrypt.getFilterType();
		if (filterType != PtlEncrypt::FILTER_STANDARD) {
			return 0;
		}
		const PtlEncryptStandard& encryptStandard = (const PtlEncryptStandard&)encrypt;
		printf(" Security Handler : Standard Security\n");
		int keyLength = encrypt.getKeyLength();
		printf(" Key Length : %d\n", keyLength);
		int method = encryptStandard.getMethod();
		if (method == PtlEncryptStandard::METHOD_RC4) {
			printf(" Method = RC4\n");
		}
		else
			if (method == PtlEncryptStandard::METHOD_RC4) {
				printf(" Method = AES\n");
			}
		const PtlEncryptPermission& perms = encryptStandard.getPermission();
		switch (perms.getType()) {
		case PtlEncryptPermission::PERM_TYPE1:
		{
			printf(" Permission Type1\n");
			const PtlEncryptPermissionType1& perms1 = reinterpret_cast<const PtlEncryptPermissionType1&>(perms);
			bool print = perms1.getPrint();
			if (print) {
				printf("  Print  : allowed.\n");
			}
			else {
				printf("  Print  : not allowed.\n");
			}
			int modify = perms1.getModify();
			switch (modify) {
			case PtlEncryptPermissionType1::PERM_MODIFY_NOT_ALLOWED:
				printf("  Modify : not allowed.\n");
				break;
			case PtlEncryptPermissionType1::PERM_MODIFY_ANNOTANDFORM:
				printf("  Modify : Commenting, filling in form fields, and signing existing signature fields.\n");
				break;
			case PtlEncryptPermissionType1::PERM_MODIFY_ASSEMBLEANDFORM:
				printf("  Modify : Page layout, filling in form fields, and signing existing signature fields.\n");
				break;
			case PtlEncryptPermissionType1::PERM_MODIFY_MODYFYDOC:
				printf("  Modify : Any except extracting pages.\n");
				break;
			}
			bool copy = perms1.getCopy();
			if (copy) {
				printf("  Copy   : Enable copying of text, images, and other content and access for the visually impaired.\n");
			}
			else {
				printf("  Copy   : Disable copying of text, images, and other content and access for the visually impaired.\n");
			}
		}
		break;
		case PtlEncryptPermission::PERM_TYPE2:
		{
			printf(" Permission Type2\n");
			const PtlEncryptPermissionType2& perms2 = reinterpret_cast<const PtlEncryptPermissionType2&>(perms);
			int print = perms2.getPrint();
			switch (print) {
			case PtlEncryptPermissionType2::PERM_PRINT_NOT_ALLOWED:
				printf("  Print  : not allowed.\n");
				break;
			case PtlEncryptPermissionType2::PERM_PRINT_LOW:
				printf("  Print  : Low resolution.\n");
				break;
			case PtlEncryptPermissionType2::PERM_PRINT_HIGH:
				printf("  Print  : High resolution.\n");
				break;
			}
			int modify = perms2.getModify();
			switch (modify) {
			case PtlEncryptPermissionType2::PERM_MODIFY_NOT_ALLOWED:
				printf("  Modify : not allowed.\n");
				break;
			case PtlEncryptPermissionType2::PERM_MODIFY_ASSEMBLEDOC:
				printf("  Modify : Inserting, deleting, and rotating pages.\n");
				break;
			case PtlEncryptPermissionType2::PERM_MODIFY_FILLFORM:
				printf("  Modify : Filling in form fields, and signing existing signature fields.\n");
				break;
			case PtlEncryptPermissionType2::PERM_MODIFY_ANNOTANDFORM:
				printf("  Modify : Commenting, filling in form fields, and signing existing signature fields.\n");
				break;
			case PtlEncryptPermissionType2::PERM_MODIFY_MODYFYDOC:
				printf("  Modify : Any except extracting pages.\n");
				break;
			}
			bool copy = perms2.getCopy();
			if (copy) {
				printf("  Copy   : Enable copying of text, images, and other content.\n");
			}
			else {
				printf("  Copy   : Disable copying of text, images, and other content.\n");
			}
			bool acc = perms2.getAccessibility();
			if (acc) {
				printf("  Accessibility : Enable text access for screen render devices for the visually impaired.\n");
			}
			else {
				printf("  Accessibility : Disable text access for screen render devices for the visually impaired.\n");
			}
		}
		break;
		}

		printf("\n\n");
		printf("Standard Information\n");
		if (doc.isSignatured()) {
			printf(" Signature  : true\n");
		}
		else {
			printf(" Signature  : false\n");
		}

		if (doc.isPDFA()) {
			printf(" PDF/A      : true\n");
		}
		else {
			printf(" PDF/A      : false\n");
		}
		if (doc.isPDFX()) {
			printf(" PDF/X      : true\n");
		}
		else {
			printf(" PDF/X      : false\n");
		}

		printf("\n");
		printf("完了!\n");
	}
	catch (const PtlException &e)
	{
		fprintf(stderr, "Error code : %d\n %s\n", e.getErrorCode(), e.getErrorMessage().c_str());
	}	
	return 0;
}

int showAction(PtlAction& action)
{
	try {
		switch (action.getType()) {
		case PtlAction::TYPE_NONE:
			printf(" Action : none\n");
			break;
		case PtlAction::TYPE_UNKNOWN:
			printf(" Action : unknown\n");
			break;
		case PtlAction::TYPE_GOTO:
		{
			printf(" Action : GoTo\n");
			PtlActionGoTo& actGoTo = (PtlActionGoTo&)action;
			PtlDest& dest = actGoTo.getDest();
			int ret = showDest(dest);
			if (ret != 0) {
				return ret;
			}
		}
		break;
		case PtlAction::TYPE_GOTO_R:
		{
			printf(" Action : GoToR\n");
			PtlActionGoToR& actGoToR = (PtlActionGoToR&)action;
			PtlDest& dest = actGoToR.getDest();
			int ret = showDest(dest);
			if (ret != 0) {
				return ret;
			}
		}
		break;
		case PtlAction::TYPE_LAUNCH:
		{
			printf(" Action : Launch\n");
			PtlActionLaunch& actLaunch = (PtlActionLaunch&)action;
			printf("   file name : %s\n", actLaunch.getFileName().c_str());
			bool flag = actLaunch.getNewWindowFlag();
			if (flag) {
				printf("  new window : true\n");
			}
			else {
				printf("  new window : false\n");
			}
		}
		break;
		case PtlAction::TYPE_URI:
		{
			printf(" Action : URI\n");
			PtlActionURI& actURI = (PtlActionURI&)action;
			printf("  uri : %s\n", actURI.getURI().c_str());
		}
		break;
		}
	}
	catch (PtlException e) {
		printf(" Error Message: %s\n", e.getErrorMessage().c_str());
		printf("\n");
		return e.getErrorCode();
	}
	catch (...) {
		printf("Unknown error has occured.\n");
		printf("\n");
		return -2;
	}
	return 0;
}

int showDest(PtlDest& dest)
{
	try {
		int destType = dest.getType();
		int pageNumber = dest.getPageNumber();
		switch (destType) {
		case PtlDest::TYPE_NONE:
			printf("  Dest : none\n");
			break;
		case PtlDest::TYPE_XYZ:
			{
				printf("  Dest page : %d\n", pageNumber);
				printf("  Dest type : XYZ\n");
				float left = 0.0f;
				if (!dest.isLeftNull())
					left = dest.getLeft();
				printf("   left    : %f\n", left);
				float top = 0.0f;
				if (!dest.isTopNull())
					top = dest.getTop();
				printf("   top     : %f\n", top);
				float zoom = 0.0f;
				if (!dest.isZoomNull())
					zoom = dest.getZoom();
				printf("   zoom    : %f\n", zoom);
			}
			break;
		case PtlDest::TYPE_FIT:
			printf("  Dest page : %d\n", pageNumber);
			printf("  Dest type : Fit\n");
			break;
		case PtlDest::TYPE_FIT_H:
			{
				printf("  Dest page : %d\n", pageNumber);
				printf("  Dest type : FitH\n");
				float top = 0.0f;
				if (!dest.isTopNull())
					top = dest.getTop();
				printf("   top     : %f\n", top);
			}
			break;
		case PtlDest::TYPE_FIT_V:
			{
				printf("  Dest page : %d\n", pageNumber);
				printf("  Dest type : FitV\n");
				float left = 0.0f;
				if (!dest.isLeftNull())
					left = dest.getLeft();
				printf("   left    : %f\n", left);
			}
			break;
		case PtlDest::TYPE_FIT_R:
			{
				printf("  Dest page : %d\n", pageNumber);
				printf("  Dest type : FitR\n");
				float left = 0.0f;
				if (!dest.isLeftNull())
					left = dest.getLeft();
				printf("   left    : %f\n", left);
				float bottom = 0.0f;
				if (!dest.isBottomNull())
					bottom = dest.getBottom();
				printf("   bottom  : %f\n", bottom);
				float right = 0.0f;
				if (!dest.isRightNull())
					right = dest.getRight();
				printf("   right   : %f\n", right);
				float top = 0.0f;
				if (!dest.isTopNull())
					top = dest.getTop();
				printf("   top     : %f\n", top);
				float zoom = 0.0f;
				if (!dest.isZoomNull())
					zoom = dest.getZoom();
				printf("   zoom    : %f\n", zoom);
			}
			break;
		case PtlDest::TYPE_FIT_B:
			printf("  Dest page : %d\n", pageNumber);
			printf("  Dest type : FitB\n");
			break;
		case PtlDest::TYPE_FIT_BH:
			printf("  Dest page : %d\n", pageNumber);
			printf("  Dest type : FitBH\n");
			{
				float top = 0.0f;
				if (!dest.isTopNull())
					top = dest.getTop();
				printf("   top     : %f\n", top);
			}
			break;
		case PtlDest::TYPE_FIT_BV:
			{
				printf("  Dest page : %d\n", pageNumber);
				printf("  Dest type : FitBV\n");
				float left = 0.0f;
				if (!dest.isLeftNull())
					left = dest.getLeft();
				printf("   left    : % f\n", left);
			}
			break;
		}
	}
	catch (PtlException e) {
		printf(" Error Message: %s\n", e.getErrorMessage().c_str());
		printf("\n");
		return e.getErrorCode();
	}
	catch (...) {
		printf("Unknown error has occured.\n");
		printf("\n");
		return -2;
	}
	return 0;
}
