More languages
Some test text!
More languages
Sample C++ code for using PDFTron SDK to read encrypted (password protected) documents, secure a document with encryption, or remove encryption. Learn more about our C++ PDF Library.
Get Started Samples DownloadTo run this sample, get started with a free trial of Apryse SDK.
//---------------------------------------------------------------------------------------
// Copyright (c) 2001-2023 by Apryse Software Inc. All Rights Reserved.
// Consult legal.txt regarding legal and license information.
//---------------------------------------------------------------------------------------
#include <PDF/PDFNet.h>
#include <PDF/PDFDoc.h>
#include <SDF/SecurityHandler.h>
#include <SDF/PDFTronCustomSecurityHandler.h>
#include <Filters/FilterReader.h>
#include <Filters/FlateEncode.h>
#include <Filters/MappedFile.h>
#include <iostream>
#include <string>
#include "../../LicenseKey/CPP/LicenseKey.h"
using namespace std;
using namespace pdftron;
using namespace SDF;
using namespace PDF;
using namespace Filters;
//---------------------------------------------------------------------------------------
// This sample shows encryption support in PDFNet. The sample reads an encrypted document and
// sets a new SecurityHandler. The sample also illustrates how password protection can
// be removed from an existing PDF document.
//---------------------------------------------------------------------------------------
int main(int argc, char *argv[])
{
int ret = 0;
PDFNet::Initialize(LicenseKey);
// Relative path to the folder containing test files.
string input_path = "../../TestFiles/";
string output_path = "../../TestFiles/Output/";
// Example 1:
// secure a PDF document with password protection and adjust permissions
try
{
// Open the test file
cout << "-------------------------------------------------" << endl << "Securing an existing document..." << endl;
PDFDoc doc((input_path + "fish.pdf").c_str());
if (!doc.InitSecurityHandler())
{
cout << "Document authentication error..." << endl;
ret = 1;
}
// Perform some operation on the document. In this case we use low level SDF API
// to replace the content stream of the first page with contents of file 'my_stream.txt'
if (true) // Optional
{
cout << "Replacing the content stream, use flate compression..." << endl;
// Get the page dictionary using the following path: trailer/Root/Pages/Kids/0
Obj page_dict = doc.GetTrailer().Get("Root").Value()
.Get("Pages").Value()
.Get("Kids").Value()
.GetAt(0);
// Embed a custom stream (file mystream.txt) using Flate compression.
MappedFile embed_file((input_path + "my_stream.txt"));
FilterReader mystm(embed_file);
page_dict.Put("Contents",
doc.CreateIndirectStream(mystm,
FlateEncode(Filter())));
}
//encrypt the document
// Apply a new security handler with given security settings.
// In order to open saved PDF you will need a user password 'test'.
SecurityHandler new_handler;
// Set a new password required to open a document
const char* user_password="test";
new_handler.ChangeUserPassword(user_password);
// Set Permissions
new_handler.SetPermission (SecurityHandler::e_print, true);
new_handler.SetPermission (SecurityHandler::e_extract_content, false);
// Note: document takes the ownership of new_handler.
doc.SetSecurityHandler(new_handler);
// Save the changes.
cout << "Saving modified file..." << endl;
doc.Save((output_path + "secured.pdf").c_str(), 0, NULL);
cout << "Done. Result saved in secured.pdf" << endl;
}
catch(Common::Exception& e) {
cout << e << endl;
ret = 1;
}
catch(...) {
cout << "Unknown Exception" << endl;
ret = 1;
}
// Example 2:
// Opens an encrypted PDF document and removes its security.
try
{
cout << "-------------------------------------------------" << endl;
cout << "Open the password protected document from the first example..." << endl;
// Open the encrypted document that we saved in the first example.
PDFDoc doc((output_path + "secured.pdf").c_str());
cout << "Initializing security handler without any user interaction..." << endl;
// At this point MySecurityHandler callbacks will be invoked.
// MySecurityHandler.GetAuthorizationData() should collect the password and
// AuthorizeFailed() is called if user repeatedly enters a wrong password.
if (!doc.InitStdSecurityHandler("test"))
{
cout << "Document authentication error..." << endl << "The password is not valid." << endl;
ret = 1;
}
else
{
cout << "The password is correct! Document can now be used for reading and editing" << endl;
// Remove the password security and save the changes to a new file.
doc.RemoveSecurity();
doc.Save(output_path + "secured_nomore1.pdf", 0, NULL);
cout << "Done. Result saved in secured_nomore1.pdf" << endl;
/*
SecurityHandler hdlr = doc.GetSecurityHandler();
cout << "Document Open Password: " << hdlr.IsUserPasswordRequired() << endl;
cout << "Permissions Password: " << hdlr.IsMasterPasswordRequired() << endl;
cout << "Permissions: "
<< "\n\tHas 'owner' permissions: " << hdlr.GetPermission(SecurityHandler::e_owner)
<< "\n\tOpen and decrypt the document: " << hdlr.GetPermission(SecurityHandler::e_doc_open)
<< "\n\tAllow content extraction: " << hdlr.GetPermission(SecurityHandler::e_extract_content)
<< "\n\tAllow full document editing: " << hdlr.GetPermission(SecurityHandler::e_doc_modify)
<< "\n\tAllow printing: " << hdlr.GetPermission(SecurityHandler::e_print)
<< "\n\tAllow high resolution printing: " << hdlr.GetPermission(SecurityHandler::e_print_high)
<< "\n\tAllow annotation editing: " << hdlr.GetPermission(SecurityHandler::e_mod_annot)
<< "\n\tAllow form fill: " << hdlr.GetPermission(SecurityHandler::e_fill_forms)
<< "\n\tAllow content extraction for accessibility: " << hdlr.GetPermission(SecurityHandler::e_access_support)
<< "\n\tAllow document assembly: " << hdlr.GetPermission(SecurityHandler::e_assemble_doc)
<< endl;
*/
}
}
catch(Common::Exception& e) {
cout << e << endl;
ret = 1;
}
catch(...) {
cout << "Unknown Exception" << endl;
ret = 1;
}
// An advanced example showing how to work with custom security handlers.
// A custom security handler is a class derived from a SecurityHandler.
// Define a custom security handler used to obtain document password dynamically via user feedback.
class MySecurityHandler : public SecurityHandler
{
public:
MySecurityHandler (int key_len, int enc_code) : SecurityHandler("Standard", key_len, enc_code) {}
MySecurityHandler (const MySecurityHandler& s) : SecurityHandler(s) {}
virtual ~MySecurityHandler() {
// cout << "MySecurityHandler Destroy";
}
// In this callback ask the user for password/authorization data.
// This may involve a dialog box used to collect authorization data or something else.
virtual bool GetAuthorizationData (Permission p)
{
cout << "The input file requires user password." << endl;
cout << "Please enter the password:" << endl;
string password;
cin >> password;
InitPassword(password.c_str());
return true;
}
// This callback could be used to customize security handler preferences.
virtual bool EditSecurityData(SDF::SDFDoc& doc) { return false; }
// This callback is used when authorization process fails.
virtual void AuthorizeFailed() { cout << "Authorize failed...." << endl; }
MySecurityHandler(const MySecurityHandler& s, TRN_SecurityHandler base)
: SecurityHandler(base, true, s.m_derived_procs)
{
}
virtual SecurityHandler* Clone(TRN_SecurityHandler base) const
{
return new MySecurityHandler(*this, base);
}
// MySecurityHandler's factory method
static TRN_SecurityHandler Create(const char* name, int key_len, int enc_code, void* custom_data)
{
MySecurityHandler* ret = new MySecurityHandler (key_len, enc_code);
// Explicitly specify which methods are overloaded.
ret->SetDerived(
has_CloneProc | // Clone - must be implemented in every derived class.
has_AuthFailedProc |
has_GetAuthDataProc);
return (TRN_SecurityHandler) ret->mp_handler;
}
};
// Example 3:
// Encrypt/Decrypt a PDF using PDFTron custom security handler
try
{
cout << "-------------------------------------------------" << endl;
cout << "Encrypt a document using PDFTron Custom Security handler with a custom id and password..." << endl;
PDFDoc doc(input_path + "BusinessCardTemplate.pdf");
// Create PDFTron custom security handler with a custom id. Replace this with your own integer
UInt32 custom_id = 123456789;
SDF::PDFTronCustomSecurityHandler custom_handler(custom_id);
// Add a password to the custom security handler
const UString pass("test");
custom_handler.ChangeUserPassword(pass);
// Save the encrypted document
doc.SetSecurityHandler(custom_handler);
doc.Save((output_path + "BusinessCardTemplate_enc.pdf").c_str(), SDFDoc::e_linearized, 0);
cout << "Decrypt the PDFTron custom security encrypted document above..." << endl;
// Register the PDFTron Custom Security handler with the same custom id used in encryption
PDFNet::AddPDFTronCustomHandler(custom_id);
PDFDoc doc_enc(output_path + "BusinessCardTemplate_enc.pdf");
doc_enc.InitStdSecurityHandler(pass);
doc_enc.RemoveSecurity();
// Save the decrypted document
doc_enc.Save((output_path + "BusinessCardTemplate_enc_dec.pdf").c_str(), SDFDoc::e_linearized, 0);
cout << "Done. Result saved in BusinessCardTemplate_enc_dec.pdf" << endl;
}
catch (Common::Exception & e) {
cout << e << endl;
ret = 1;
}
catch (...) {
cout << "Unknown Exception" << endl;
ret = 1;
}
// Example 4:
// Read a password protected PDF using a custom security handler.
try
{
// Register standard security. Required only once per application session.
PDFNet::RegisterSecurityHandler("Standard", "Standard Security", MySecurityHandler::Create);
cout << "-------------------------------------------------" << endl;
cout << "Open the password protected document from the first example..." << endl;
PDFDoc doc((output_path + "secured.pdf").c_str()); // Open the encrypted document that we saved in the first example.
cout << "Initializing security handler. The password will now be collected from the user" << endl;
cout << "Enter 'test' as the password." << endl;
// this data is just to show how you can pass your own custom data through InitSecurityHandler
void* custom_data = const_cast<char*>("my custom pointer");
// At this point MySecurityHandler callbacks will be invoked.
// MySecurityHandler.GetAuthorizationData() should collect the password and
// AuthorizeFailed() is called if user repeatedly enters a wrong password.
if (!doc.InitSecurityHandler(custom_data))
{
cout << "Document authentication error..." << endl;
cout << "The password is not valid." << endl;
}
else
{
cout << "\nThe password is correct! Document can now be used for reading and editing" << endl;
// Remove the password security and save the changes to a new file.
doc.RemoveSecurity();
doc.Save((output_path + "secured_nomore2.pdf").c_str(), 0, NULL);
cout << "Done. Result saved in secured_nomore2.pdf" << endl;
}
}
catch(Common::Exception& e) {
cout << e << endl;
ret = 1;
}
catch(...) {
cout << "Unknown Exception" << endl;
ret = 1;
}
cout << "-------------------------------------------------" << endl;
cout << "Tests completed." << endl;
PDFNet::Terminate();
return ret;
}