/*! ** ** \file pdfaPilotSample.cpp ** ** \brief callas pdfEngine SDK sample (pdfaPilot) ** ** \author © 2011 callas software GmbH, Berlin, Germany - www.callassoftware.com * */ //////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include #include #include #if defined(_WIN32) || defined(_M_X64) # include #elif defined(MAC_ENV) # include "Carbon.h" #endif #include "ptb.h" #if defined(PDFENGINE_USE_PDDOC_INTERFACE) # include "ptbAPDFL.h" // APDFL includes # include "PDFInit.h" # include "ASCalls.h" # include "PDCalls.h" #endif #if WIN_PLATFORM # define APDFL_PATH_(a,b) a##b # define APDFL_PATH(string_literal) APDFL_PATH_(L,string_literal) # define TDirList ASUTF16Val* const std::string kPathDelim = "\\"; #else # define APDFL_PATH(string_literal) string_literal # define TDirList char* const std::string kPathDelim = "/"; #endif #define EXIT_WITH_FAILURE 100 typedef std::basic_string TStringUTF8; //////////////////////////////////////////////////////////////////////////////// /*! Write log statement to console */ template< typename T > void log( const T & t ) { std::cout << t << std::endl; } template< typename T, typename TArg > T stream_cast( const TArg& src ) { std::stringstream ss; ss << src; T tgt; ss >> tgt; return tgt; } //////////////////////////////////////////////////////////////////////////////// /*! Exceptions used in sample app */ class CException: public std::exception { public: CException( const char * msg ) :msg_(msg) { debugger(); } CException( const std::string & msg ) :msg_(msg) { debugger(); } virtual ~CException() throw() { } virtual const char* what() const throw() { return msg_.c_str(); } private: void debugger() const { // std::cerr << "throw: " << msg_ << std::endl; # if MAC_PLATFORM Debugger(); # endif } std::string msg_; }; //////////////////////////////////////////////////////////////////////////////// /*! convert a PTB_StringID to a std::string */ std::string getString( PTB_StringID idStr, bool bDispose = false ) { if( PTB_IsValidStringID( idStr ) ) { PTB_size_t size; PTB_StringLength( idStr, &size ); std::vector< PTB_utf8_char_t > buf( size ); PTB_StringGet( idStr, &buf[0], &size ); if( bDispose ) { PTB_StringRelease( idStr ); } //remove NULL byte buf.pop_back(); return std::string( buf.begin(), buf.end() ); } else { return ""; } } //////////////////////////////////////////////////////////////////////////////// /*! convert a PTB_EError to a std::string */ std::string getErrorString( PTB_EError err ) { PTB_StringID strid; PTB_StringID errid; PTB_EError err2 = PTB_GetErrorMessage2( err, &strid, &errid ); if( err2 == PTB_eerrNone ) { std::string strstr = getString( strid ); std::string errstr = getString( errid ); if( !errstr.empty() ) { return strstr + " -> " + errstr; } return strstr; } return ""; } //////////////////////////////////////////////////////////////////////////////// /*! Check for no error */ void require_noErr( PTB_EError err, bool bThrow = true, bool bUseDict = true ) { if( err != PTB_eerrNone ) { std::ostringstream oss; if( bUseDict ) { oss << "ERROR: 0x" << std::hex << err; oss << " (" << getErrorString( err ) << ")" << std::endl; } else { oss << "ERROR: 0x" << std::hex << err << std::endl; } if( bThrow ) throw CException( oss.str() ); else std::cout << oss.str(); } } void require_noErr( PTB_EError err, PTB_ResultID idResult ) { if( err != PTB_eerrNone ) { require_noErr( err, false ); PTB_StringID strid; PTB_GetMachineErrorText( idResult, &strid ); std::string errsmg = getString( strid, true ); if( idResult != PTB_INVALID_ID && errsmg.size() > 1 ) { std::cout << "MACHINE ERROR TEXT: " << errsmg << std::endl; } } } //////////////////////////////////////////////////////////////////////////////// std::string makeFileName( std::string s ) { const std::string kForbiddenChars(" :/\\*?"); std::string::size_type pos = 0; while( pos != std::string::npos ) { pos = s.find_first_of( kForbiddenChars, pos ); if( pos != std::string::npos ) { s[pos] = '_'; } } return s; } //////////////////////////////////////////////////////////////////////////////// /*! convert a std::string to valid UTF8 string */ TStringUTF8 getUTF8( const std::string& source ) { if( source.empty() ) return TStringUTF8(); std::vector buffer( source.size()+1 ); PTB_size_t size = static_cast( buffer.size() ); const PTB_EError error = PTB_ConvertSysToUTF8( source.c_str(), &buffer[0], &size ); if( error == PTB_eerrStrBufferTooSmall ) { buffer.resize( size ); require_noErr( PTB_ConvertSysToUTF8( source.c_str(), &buffer[0], &size ) ); } return TStringUTF8( buffer.begin() , buffer.begin()+buffer.size()-1 ); } //////////////////////////////////////////////////////////////////////////////// /*! APDFL initialization */ class CLibInit { public: CLibInit() :initialized_( false ) { # if defined(PDFENGINE_USE_PDDOC_INTERFACE) PDFLDataRec pdflData; memset( &pdflData, 0, sizeof( PDFLDataRec ) ); pdflData.size = sizeof( PDFLDataRec ); pdflData.flags = kPDFLInitIgnoreDefaultDirectories; # if defined(WIN32) || defined(_M_X64) pdflData.inst = NULL; # endif // defined(WIN32) || defined(_M_X64) pdflData.dirList = NULL; pdflData.listLen = 0; pdflData.allocator = NULL; pdflData.resProcs = NULL; pdflData.extProcs = NULL; pdflData.cacheFileList = NULL; pdflData.systemCacheFile = NULL; pdflData.commonCacheFile = NULL; # if MAC_PLATFORM || WIN_PLATFORM pdflData.cMapDirectory = NULL; # endif pdflData.unicodeDirectory = NULL; ASInt32 pdflErr = PDFLInitHFT( &pdflData ); if( pdflErr != 0 ) { std::cerr << "Unexpected error while PDFLInitHFT" << std::hex << pdflErr << '\n'; std::exit(EXIT_FAILURE);//skip next call } # endif // defined(PDFENGINE_USE_PDDOC_INTERFACE) } ~CLibInit() { deinit(); # if defined(PDFENGINE_USE_PDDOC_INTERFACE) PDFLTermHFT(); # endif // defined(PDFENGINE_USE_PDDOC_INTERFACE) } void init( const std::string & keycode ) { if( !initialized_ ) { require_noErr( PTB_LibInit( keycode.c_str(), NULL, NULL ), true, false ); log( "callas pdfEngine SDK initialized" ); initialized_ = true; } } void deinit() { if( initialized_ ) { PTB_LibRelease(); log( "callas pdfEngine SDK de-initialized" ); initialized_ = false; } } private: bool initialized_; }; //////////////////////////////////////////////////////////////////////////////// #if defined(PDFENGINE_USE_PDDOC_INTERFACE) struct CPDDoc { CPDDoc(const std::string& file) { # if WIN_PLATFORM || UNIX_PLATFORM static const ASAtom atCstring( ASAtomFromString( "Cstring")); asname = ASFileSysCreatePathName( ASGetDefaultFileSys(), atCstring, file.c_str(), NULL); # else static const ASAtom atPOSIXPath ( ASAtomFromString( "POSIXPath")); asname = ASFileSysCreatePathName( ASGetDefaultFileSys(), atPOSIXPath, file.c_str(), NULL); # endif doc = PDDocOpen( asname, ASGetDefaultFileSys(), NULL, true); } ~CPDDoc() { PDDocClose( doc); ASFileSysReleasePath( ASGetDefaultFileSys(), asname); } PDDoc get() { return doc; } std::string getPath() { ASFile asFile = PDDocGetFile( doc); ASFileSys asFileSys = ASGetDefaultFileSys(); ASPathName asPathName = ASFileAcquirePathName(asFile); ASPlatformPath asPlatformPath = NULL; # if WIN_PLATFORM static const ASAtom atCstring( ASAtomFromString( "Cstring")); ASInt32 ret = ASFileSysAcquirePlatformPath(asFileSys, asPathName, atCstring, &asPlatformPath); if( NULL != asPlatformPath && 0 == ret) { std::string ret( ASPlatformPathGetCstringPtr( asPlatformPath)); ASFileSysReleasePlatformPath( asFileSys, asPlatformPath); ASFileSysReleasePath( asFileSys, asPathName); return ret; } # else static const ASAtom atPOSIXPath ( ASAtomFromString( "POSIXPath")); ASInt32 ret = ASFileSysAcquirePlatformPath(asFileSys, asPathName, atPOSIXPath, &asPlatformPath); if( NULL != asPlatformPath && 0 == ret) { std::string ret( ASPlatformPathGetPOSIXPathPtr( asPlatformPath)); ASFileSysReleasePlatformPath( asFileSys, asPlatformPath); ASFileSysReleasePath( asFileSys, asPathName); return ret; } # endif return ""; } private: PDDoc doc; ASPathName asname; }; #endif // defined(PDFENGINE_USE_PDDOC_INTERFACE) //////////////////////////////////////////////////////////////////////////////// /*! Progress callbacks */ PTB_bool_t progressCB( PTB_uint32_t max /*!< Progress value max */ , PTB_uint32_t current /*!< Current progress value */ , PTB_EPreflightPart /*part*/ /*!< Current Preflight part in process */ , PTB_StringID idStr /*!< String data */ , void* userData /*!< User data */ ) { static int lastval(0); static std::string lastmsg; int val = static_cast(static_cast(current)* 100.0 / static_cast(max)); std::string msg = getString( idStr ); if( lastval != val || lastmsg != msg ) { lastval = val; lastmsg = msg; if( !msg.empty() ) { std::cout << msg << ": " << val << "%" << std::endl; } else { std::cout << val << "%" << std::endl; } } return true; } PTB_bool_t progressCB( PTB_uint32_t max, PTB_uint32_t current, void * userData ) { return progressCB( max, current, PTB_eppPostCheck, PTB_INVALID_ID, userData ); } PTB_bool_t progressCB( PTB_uint32_t max, PTB_uint32_t current, PTB_StringID idStr, void * userData ) { return progressCB( max, current, PTB_eppPostCheck, idStr, userData ); } //////////////////////////////////////////////////////////////////////////////// // find first profile in engine // userData: PTB_PRCProfID * void FindFirstProfileCB( PTB_PRCEngineID idEng, PTB_PRCProfID idProf, void * userData ) { PTB_PRCProfID * firstProfile = reinterpret_cast< PTB_PRCProfID * >( userData ); if( firstProfile && !PTB_PRCIsValidProfID( *firstProfile ) ) { *firstProfile = idProf; } } //////////////////////////////////////////////////////////////////////////////// // log fixups as they occur // userData: NULL void fixupCB( PTB_PRCEngineID idEng /*!< PRC Engine ID */ , PTB_PRCFxupID idFixup /*!< PRC Fixup ID */ , PTB_EFixupState state /*!< Fixup state */ , PTB_StringID idReason /*!< Reason text */ , void* userData /*!< user data */ ) { if( state != PTB_efsFixupNotRequired ) { PTB_StringID idFixupName; PTB_PRCGetFixupData( idEng, idFixup, PTB_PRCEdtName, NULL, &idFixupName ); std::cout << "Fixup \"" << getString( idFixupName, true ) << "\"" << std::endl; std::cout << " Status: "; switch( state ) { case PTB_efsFixupSuccess : std::cout << "Success" ; break; case PTB_efsFixupFailure : std::cout << "Failure" ; break; case PTB_efsFixupNotRequired: std::cout << "Not Required"; break; } std::cout << std::endl; std::string reason = getString( idReason ); if( !reason.empty() && reason.size() > 1 ) { std::cout << " Reason: " << reason << std::endl; } } } //////////////////////////////////////////////////////////////////////////////// // log hits as they occur // userData: NULL PTB_EHitCBResult hitCB( PTB_PRCEngineID idEng /*!< PRC Engine ID */ , PTB_PRCProfID idProf /*!< PRC Profile ID */ , PTB_PRCRuleID idRule /*!< PRC Rule ID */ , PTB_ResultID idResult /*!< Result ID */ , PTB_HitID idHit /*!< Hit ID */ , PTB_PRCERuleCheckSeverity ruleSev /*!< PRC Rule severity */ , PTB_uint32_t pageNum /*!< Current page number */ , void* userData /*!< user data */ ) { if( NULL != userData ) { bool * isPDFA = reinterpret_cast< bool * >( userData ); if( NULL != isPDFA ) *isPDFA = false; } PTB_StringID idRuleName; PTB_PRCGetRuleData( idEng, idRule, PTB_PRCEdtName, NULL, &idRuleName ); std::cout << "Hit with severity \""; switch( ruleSev ) { case PTB_PRCErcsInfo : std::cout << "Info"; break; case PTB_PRCErcsWarning: std::cout << "Warning"; break; case PTB_PRCErcsError : std::cout << "Error"; break; } // std::cout << "\" on page " << pageNum; std::cout << ": " << getString( idRuleName ); std::cout << std::endl; PTB_StringRelease( idRuleName ); return PTB_ehcbrContinue; } PTB_EHitCBResult hitCancelCB( PTB_PRCEngineID /*idEng*/ /*!< PRC Engine ID */ , PTB_PRCProfID /*idProf*/ /*!< PRC Profile ID */ , PTB_PRCRuleID /*idRule*/ /*!< PRC Rule ID */ , PTB_ResultID /*idResult*/ /*!< Result ID */ , PTB_HitID /*idHit*/ /*!< Hit ID */ , PTB_PRCERuleCheckSeverity ruleSev /*!< PRC Rule severity */ , PTB_uint32_t /*pageNum*/ /*!< Current page number */ , void* userData /*!< user data */ ) { if( NULL != userData ) { bool * isPDFA = reinterpret_cast< bool * >( userData ); if( NULL != isPDFA ) *isPDFA = false; } // return PTB_ehcbrContinue; return (ruleSev == PTB_PRCErcsError ? PTB_ehcbrCancel : PTB_ehcbrContinue); } //////////////////////////////////////////////////////////////////////////////// /*! Save callback // userData: string -> result PDF */ PTB_Path_t* saveCB( PTB_ResultID idResult /*!< Result ID */ , PTB_ESaveAsReason reason /*!< */ , PTB_ESaveAsReasonPDFX reasonPDFX /*!< */ , PTB_EPDFXVersion versionPDFX /*!< */ , PTB_ESaveAsReasonPDFA reasonPDFA /*!< */ , PTB_EPDFAVersion versionPDFA /*!< */ , PTB_StringID currentPath /*!< current path of PDF document */ , void* userData /*!< User data */ ) { PTB_Path_t * resultPDF = reinterpret_cast< PTB_Path_t * >( userData ); if( resultPDF != NULL ) { std::cout << "Saving PDF file " << std::string(reinterpret_cast< char* >(resultPDF)) << std::endl; return const_cast< PTB_Path_t* >( resultPDF ); } else if( PTB_IsValidStringID( currentPath)) { PTB_size_t strBufSize = 0; PTB_EError err = PTB_StringLength( currentPath, &strBufSize); if( err != PTB_eerrNone ) return NULL; std::vector strBuffer(strBufSize); err = PTB_StringGet( currentPath, &strBuffer[0], &strBufSize); if( err != PTB_eerrNone ) return NULL; std::cout << "Saving PDF file " << &strBuffer[0] << std::endl; } return NULL; // NULL used default file stored in 'currentPath' } //////////////////////////////////////////////////////////////////////////////// int printVersion( bool check ) { PTB_uint16_t pdfEngineVersion; PTB_uint16_t apiVersion; PTB_uint16_t apiIteration; PTB_uint16_t buildNumber; PTB_bool_t x64; PTB_bool_t threadSafety; PTB_EError err = PTB_LibAPIGetVersion2( &pdfEngineVersion , &apiVersion , &apiIteration , &buildNumber , &x64 , &threadSafety); require_noErr( err, false ); std::string arch_info(""); if (x64) arch_info += "x64"; if (threadSafety) { if (arch_info.size() > 0) arch_info += " "; arch_info += "threadSafe"; } std::cout << "callas pdfEngine SDK " << pdfEngineVersion << '.' << apiVersion << '.' << buildNumber; if (arch_info.size() > 0) { std::cout << " (" << arch_info << ")"; } std::cout << std::endl; if( !check ) return 0; const PTB_uint16_t curPTBVers = dPTBSDK_pdfEngineVersion; const PTB_uint16_t curAPIVersion = dPTBSDK_APIMainVersion; const PTB_uint16_t curAPIIteration = dPTBSDK_APIVersionIteration; if ( curPTBVers != pdfEngineVersion || curAPIVersion != apiVersion //|| curapiIteration < apiIteration //later this should be sufficient. || curAPIIteration != apiIteration //the first prerelease iterations might be incompatible! ) { std::cerr << "internal API version mismatch. Expected: " << curPTBVers << "." << curAPIVersion << "." << curAPIIteration << ". Found: " << pdfEngineVersion << "." << apiVersion << "." << apiIteration << std::endl; return 0; } return EXIT_WITH_FAILURE; } //////////////////////////////////////////////////////////////////////////////// PTB_EError processFile(const char* file, const char* level, const char* xmlfile, const char* htmlfile, const char* mhtfile, const char* saveasfile, const char* customprofile ,const char* fontfolder, const char* fontcachefolder, const char* substitutefile, const char* outputintentfile, bool removexmpmetadata) { PTB_EError err = PTB_eerrNone; PTB_size_t lastValue = 0; bool bIsPDFA = true; PTB_EPDFAVersion version = PTB_epdfa1b_2005; if( NULL != level ) { std::string compliance( level ); if( compliance == "1a" ) { version = PTB_epdfa1a_2005; } else if ( compliance == "1b" ) { version = PTB_epdfa1b_2005; } else if ( compliance == "2a" ) { version = PTB_epdfa2a; } else if ( compliance == "2b" ) { version = PTB_epdfa2b; } else if ( compliance == "2u" ) { version = PTB_epdfa2u; } else if ( compliance == "3a" ) { version = PTB_epdfa3a; } else if ( compliance == "3b" ) { version = PTB_epdfa3b; } else if ( compliance == "3u" ) { version = PTB_epdfa3u; } } if( NULL != saveasfile ) std::cout << "Convert \"" << file << "\"" << std::endl; else std::cout << "Check \"" << file << "\"" << std::endl; PTB_Path_t filePath[255]; PTB_size_t bufSize = sizeof(filePath); require_noErr( PTB_ConvertSysToUTF8( file, filePath, &bufSize ) ); PTB_PRCEngineID idEng = PTB_INVALID_ID; PTB_PRCProfID idProf = PTB_INVALID_ID; if( NULL != customprofile) { PTB_Path_t profPath[255]; bufSize = sizeof(profPath); require_noErr( PTB_ConvertSysToUTF8( customprofile, profPath, &bufSize ) ); err = PTB_PRCEngineCreate( &idEng); require_noErr( err ); err = PTB_PRCEngineImportPackageFromFile( idEng, profPath, NULL, NULL); require_noErr( err ); err = PTB_PRCEnumProfiles( idEng, FindFirstProfileCB, &idProf); require_noErr( err ); } PTB_ResultID idResult = PTB_INVALID_ID; if( NULL != saveasfile ) { PTB_Path_t saveasPath[255]; bufSize = sizeof(saveasPath); require_noErr( PTB_ConvertSysToUTF8( saveasfile, saveasPath, &bufSize ) ); PTB_Path_t fontfolderPath[255]; if( NULL != fontfolder ) { bufSize = sizeof(fontfolderPath); require_noErr( PTB_ConvertSysToUTF8( fontfolder, fontfolderPath, &bufSize ) ); } PTB_Path_t fontCachePath[255]; if( NULL != fontcachefolder ) { bufSize = sizeof(fontCachePath); require_noErr( PTB_ConvertSysToUTF8( fontcachefolder, fontCachePath, &bufSize ) ); } PTB_Path_t substitutePath[255]; if( NULL != substitutefile ) { bufSize = sizeof(substitutePath); require_noErr( PTB_ConvertSysToUTF8( substitutefile, substitutePath, &bufSize ) ); } PTB_Path_t outputintentPath[255]; if( NULL != outputintentfile ) { bufSize = sizeof(outputintentPath); require_noErr( PTB_ConvertSysToUTF8( outputintentfile, outputintentPath, &bufSize ) ); } PTB_uint32_t flags = PTB_ecpfNone; if( !removexmpmetadata ) flags |= PTB_ecpfNoXMPMetadataRemoval; # if defined(PDFENGINE_USE_PDDOC_INTERFACE) CPDDoc pddoc(file); err = PTB_PDDocCheckPDFA( pddoc.get(), version, hitCancelCB, &bIsPDFA, NULL, NULL, idEng, idProf, &idResult, NULL ); if( err == PTB_eerrCancel ) { PTB_PreflightRelease( idResult, NULL ); // release old results idResult = PTB_INVALID_ID; // reset old results bIsPDFA = true; // reset old status err = PTB_PDDocConvertPDFA10( pddoc.get() , version , fixupCB , NULL , hitCB , &bIsPDFA , progressCB , &lastValue , saveCB , &saveasPath , flags , NULL == fontfolder ? NULL : fontfolderPath , NULL == fontcachefolder ? NULL : fontCachePath , NULL == substitutefile ? NULL : substitutePath , NULL == outputintentfile ? NULL : outputintentPath , NULL, NULL, NULL, NULL , NULL , 100 , PTB_MAX_HIT_NUM , PTB_MAX_HIT_NUM, PTB_MAX_PAGE_DEFAULT_NUM , 1, 0, PTB_MAX_END_PAGE , idEng , idProf , &idResult , NULL ); } else { if( err == PTB_eerrNone ) std::cout << "\"" << file << "\" is valid PDF/A no conversion needed." << std::endl; } # else // defined(PDFENGINE_USE_PDDOC_INTERFACE) err = PTB_CheckPDFA( filePath, version, hitCancelCB, &bIsPDFA, NULL, NULL, idEng, idProf, &idResult, NULL ); if( err == PTB_eerrCancel ) { PTB_PreflightRelease( idResult, NULL ); // release old results idResult = PTB_INVALID_ID; // reset old results bIsPDFA = true; // reset old status err = PTB_ConvertPDFA10( filePath , version , fixupCB , NULL , hitCB , &bIsPDFA , progressCB , &lastValue , saveCB , &saveasPath , flags , NULL == fontfolder ? NULL : fontfolderPath , NULL == fontcachefolder ? NULL : fontCachePath , NULL == substitutefile ? NULL : substitutePath , NULL == outputintentfile ? NULL : outputintentPath , NULL, NULL, NULL, NULL , NULL , 100 , PTB_MAX_HIT_NUM , PTB_MAX_HIT_NUM, PTB_MAX_PAGE_DEFAULT_NUM , 1, 0, PTB_MAX_END_PAGE , idEng , idProf , &idResult , NULL ); } else { if( err == PTB_eerrNone ) std::cout << "\"" << file << "\" is valid PDF/A no conversion needed." << std::endl; } # endif // defined(PDFENGINE_USE_PDDOC_INTERFACE) } else { # if defined(PDFENGINE_USE_PDDOC_INTERFACE) CPDDoc pddoc(file); err = PTB_PDDocCheckPDFA3( pddoc.get() , version , hitCB , &bIsPDFA , progressCB , &lastValue , PTB_MAX_HIT_NUM, PTB_MAX_HIT_NUM, PTB_MAX_PAGE_DEFAULT_NUM , idEng , idProf , &idResult , NULL ); # else // defined(PDFENGINE_USE_PDDOC_INTERFACE) err = PTB_CheckPDFA3( filePath , version , hitCB , &bIsPDFA , progressCB , &lastValue , PTB_MAX_HIT_NUM, PTB_MAX_HIT_NUM, PTB_MAX_PAGE_DEFAULT_NUM , idEng , idProf , &idResult , NULL ); # endif // defined(PDFENGINE_USE_PDDOC_INTERFACE) } require_noErr( err, idResult ); if( err == PTB_eerrNone ) { if( bIsPDFA ) { log( "PDF is a valid PDF/A file" ); } else { log( "PDF is not a valid PDF/A file" ); } if( idResult != PTB_INVALID_ID ) { if( xmlfile != NULL ) { std::cout << "Create XML Report \"" << xmlfile << "\"" << std::endl; PTB_Path_t xmlPath[255]; bufSize = sizeof(xmlPath); require_noErr( PTB_ConvertSysToUTF8( xmlfile, xmlPath, &bufSize ) ); lastValue = 0; err = PTB_Report( idResult , xmlPath , PTB_eXMLResults_V2 , PTB_eCR , PTB_eUTF8 , 0 , PTB_eAllDetails , NULL , progressCB , &lastValue , 0 , PTB_MAX_END_PAGE , NULL ); require_noErr( err, false ); } if( htmlfile!= NULL ) { std::cout << "Create HTML Report \"" << htmlfile << "\"" << std::endl; PTB_Path_t htmlPath[255]; bufSize = sizeof(htmlPath); require_noErr( PTB_ConvertSysToUTF8( htmlfile, htmlPath, &bufSize ) ); lastValue = 0; err = PTB_Report( idResult , htmlPath , PTB_eHTML , PTB_eCR , PTB_eUTF8 , PTB_eHTMLNoIcons , PTB_eAllDetails , NULL , progressCB , &lastValue , 0 , PTB_MAX_END_PAGE , NULL ); require_noErr( err, false ); } if( mhtfile!= NULL ) { std::cout << "Create MHT Report \"" << mhtfile << "\"" << std::endl; PTB_Path_t mhtPath[255]; bufSize = sizeof(mhtPath); require_noErr( PTB_ConvertSysToUTF8( mhtfile, mhtPath, &bufSize ) ); lastValue = 0; err = PTB_Report( idResult , mhtPath , PTB_eHTML , PTB_eCR , PTB_eUTF8 , PTB_eHTMLasMHT | PTB_eHTMLNoIcons , PTB_eAllDetails , NULL , progressCB , &lastValue , 0 , PTB_MAX_END_PAGE , NULL ); require_noErr( err, false ); } } } if( NULL != customprofile) { PTB_PRCEngineDispose( idEng); } PTB_PreflightRelease( idResult, NULL ); log( "" ); return err; } //////////////////////////////////////////////////////////////////////////////// PTB_EError doCreateZUGFeRD( const std::string& pdf, const std::string& xml, const std::string& result) { log( "Create ZUGFeRD..."); log( "PDF : " + pdf ); log( "XML : " + xml ); log( "Result : " + result ); PTB_size_t lastValue = 0; PTB_EError err = PTB_CreateZUGFeRD( reinterpret_cast< const PTB_Path_t* >( pdf.c_str() ) , reinterpret_cast< const PTB_Path_t* >( xml.c_str() ) , reinterpret_cast< const PTB_Path_t* >( result.c_str() ) , progressCB , &lastValue ); return err; } //////////////////////////////////////////////////////////////////////////////// void exportZUGFeRDCB( PTB_StringID idFile /*!< Created file */ , void* userData /*!< User data */ ) { log( "file: " + getString( idFile ) ); } PTB_EError doExportZUGFeRD( const std::string& pdf, const std::string& parts, const std::string& folder) { log( "Export ZUGFeRD..."); log( "PDF : " + pdf ); log( "Destination Folder : " + folder ); PTB_size_t lastValue = 0; PTB_EError err = PTB_ExportZUGFeRD( reinterpret_cast< const PTB_Path_t* >( pdf.c_str() ) , stream_cast(parts) , reinterpret_cast< const PTB_Path_t* >( folder.c_str() ) , exportZUGFeRDCB, NULL , progressCB , &lastValue ); return err; } //////////////////////////////////////////////////////////////////////////////// PTB_bool_t emailAttachmentCB( PTB_StringID idAttachment /*!< Full file path to the attachment (located in a temporary location!) */ , PTB_uint32_t flags /*!< Flags (any combination of PTB_EEmailAttachmentFlags values) */ , void* userData /*!< User data */ ) { if( 0 != (flags & PTB_eEmailAttachmentFailed) ) { log( "Attachment could not converted to PDF: " + getString( idAttachment ) ); } return true; } PTB_EError doSaveEmailAsPDF( const std::string& pdf, const std::string& result) { log( "Save e-mail to PDF..."); log( "PDF : " + pdf ); log( "Result : " + result ); PTB_EError err = PTB_SaveEmailAsPDF2( reinterpret_cast< const PTB_Path_t* >( pdf.c_str() ) , NULL , PTB_eEmailNoPDFA , PTB_eEmailDefault , PTB_eEmailNone , PTB_eEmailOnErrorFallback , NULL , NULL , reinterpret_cast< const PTB_Path_t* >( result.c_str() ) , emailAttachmentCB, NULL , progressCB , NULL ); return err; } //////////////////////////////////////////////////////////////////////////////// int usage() { std::cout << "USAGE:" << std::endl; std::cout << " pdfaPilotSample" << " " << " [" << " -l" << " -o" << " [" << " -x -h -m" << " [" << " -f" << " -c" << " -s" << " -i" << " -p" << " ]" << " ]" << " ]" << std::endl; std::cout << " pdfaPilotSample --createzugferd " << std::endl; std::cout << " pdfaPilotSample --exportzugferd " << std::endl; std::cout << " parts:" << std::endl; std::cout << " " << PTB_ezpImages << ": Images from the PDF pages" << std::endl; std::cout << " " << PTB_ezpXML << ": XML invoice" << std::endl; std::cout << " " << PTB_ezpHTML << ": HTML view of the XML" << std::endl; std::cout << " " << PTB_ezpHTMLSynopsis << ": HTML synopsis of PDF images and XML" << std::endl; std::cout << " " << PTB_ezpValidationReport << ": ZUGFeRD validation report" << std::endl; std::cout << " " << PTB_ezpAll << ": All" << std::endl; std::cout << " pdfaPilotSample --emailtopdf " << std::endl; return EXIT_WITH_FAILURE; } //////////////////////////////////////////////////////////////////////////////// typedef std::vector< std::string > TArgumentVec; //////////////////////////////////////////////////////////////////////////////// // main //////////////////////////////////////////////////////////////////////////////// int main(int argc, char* argv[]) { try { if (!printVersion( true )) // print and check version return EXIT_WITH_FAILURE; if( argc < 3 ) { return usage(); } TArgumentVec args; for( std::size_t i = 0; i < argc; ++i) { args.push_back( argv[i] ); std::cout << "argv[" << i << "] = " << args.back() << std::endl; } // to change the internal used cache folder you can use the function PTB_LibSetPath() // this is useful if you use our SDK in a webservice environment where no user preferences exists // PTB_LibSetPath( PTB_eptCache, reinterpret_cast< const PTB_Path_t* >( "" ) ); // note: PTB_LibSetPath() must be called *before* the lib is initialized CLibInit lib; lib.init( args.at( 1 ) ); // to change the reporting language you can use the function PTB_LanguageSet() // the languages codes can be determine by PTB_LanguageEnum() or for example by // using the sample mode --listlanguages // PTB_LanguageSet( reinterpret_cast< const PTB_sys_char_t* >( "de" ) ); // check optional parameters std::string level; std::string xmlfile; std::string htmlfile; std::string mhtfile; std::string savasfile; std::string profile; std::string fontfolder; std::string fontcachefolder; std::string substitutefile; std::string outputintentfile; bool removexmpmetadata = true; for ( int i = 0; i < args.size(); i++) { std::string arg( args.at(i) ); if( arg[0] == '-' && arg.size() >= 1) { switch(arg[1]) { case 'x': case 'X': xmlfile = arg.substr(2); break; case 'h': case 'H': htmlfile = arg.substr(2); break; case 'm': case 'M': mhtfile = arg.substr(2); break; case 'o': case 'O': savasfile = arg.substr(2); break; case 'p': case 'P': profile = arg.substr(2); break; case 'f': case 'F': fontfolder = arg.substr(2); break; case 'c': case 'C': fontcachefolder = arg.substr(2); break; case 's': case 'S': substitutefile = arg.substr(2); break; case 'i': case 'I': outputintentfile = arg.substr(2); break; // case 'd': // case 'D': removexmpmetadata = true; break; case 'l': case 'L': level = arg.substr(2); break; } } } PTB_EError err = PTB_eerrNone; if( args.at(2) == "--createzugferd" ) { err = doCreateZUGFeRD( args.at(3), args.at(4), args.at(5) ); } else if( args.at(2) == "--exportzugferd" ) { err = doExportZUGFeRD( args.at(3), args.at(4), args.at(5) ); } else if( args.at(2) == "--emailtopdf" ) { err = doSaveEmailAsPDF( args.at(3), args.at(4) ); } else if( savasfile.empty()) { err = processFile( args.at( 2 ).c_str() , level.empty() ? NULL : level.c_str() , xmlfile.empty() ? NULL : xmlfile.c_str() , htmlfile.empty() ? NULL : htmlfile.c_str() , mhtfile.empty() ? NULL : mhtfile.c_str() , NULL , profile.empty() ? NULL : profile.c_str() , NULL , NULL , NULL , NULL , removexmpmetadata); } else { err = processFile( args.at( 2 ).c_str() , level.empty() ? NULL : level.c_str() , xmlfile.empty() ? NULL : xmlfile.c_str() , htmlfile.empty() ? NULL : htmlfile.c_str() , mhtfile.empty() ? NULL : mhtfile.c_str() , savasfile.c_str() , profile.empty() ? NULL : profile.c_str() , fontfolder.empty() ? NULL : fontfolder.c_str() , fontcachefolder.empty() ? NULL : fontcachefolder.c_str() , substitutefile.empty() ? NULL : substitutefile.c_str() , outputintentfile.empty() ? NULL : outputintentfile.c_str() , removexmpmetadata); } require_noErr( err, false ); log( "bye..." ); return (err != PTB_eerrNone) ? EXIT_WITH_FAILURE : EXIT_SUCCESS; } catch( const std::out_of_range& ) { std::cerr << "An error occured" << std::endl; std::cerr << "Array index out of bounds" << std::endl; std::cerr << "Maybe to few arguments?" << std::endl; return EXIT_WITH_FAILURE; } catch( const std::exception & x ) { std::cerr << "exception catched: " << x.what() << std::endl; return EXIT_WITH_FAILURE; } } //////////////////////////////////////////////////////////////////////////////// // EOF