'---------------------------------------------------------------------------------------
' Copyright (c) 2001-2025 by Apryse Software Inc. All Rights Reserved.
' Consult legal.txt regarding legal and license information.
'---------------------------------------------------------------------------------------
Imports System

Imports pdftron
Imports pdftron.Common
Imports pdftron.Filters
Imports pdftron.SDF
Imports pdftron.PDF

'---------------------------------------------------------------------------------------
' 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.
'---------------------------------------------------------------------------------------
Module EncTestVB
    Dim pdfNetLoader As PDFNetLoader
    Sub New()
        pdfNetLoader = pdftron.PDFNetLoader.Instance()
    End Sub

    ' A custom security handler used to obtain document password dynamically via user feedback. 
    Public Class MySecurityHandler
        Inherits StdSecurityHandler

        Sub New(ByVal key_len As Int32, ByVal enc_code As Int32)
            MyBase.New(key_len, enc_code)
        End Sub

        Sub New(ByVal s As MySecurityHandler)
            MyBase.New(s)
        End Sub

        ' In this callback ask the user for password/authorization data. 
        ' This may invlove a dialog box used to collect authorization data or something else.
        Public Overrides Function GetAuthorizationData(ByVal p As SecurityHandler.Permission) As Boolean
            Console.WriteLine("The input file requires user password.")
            Console.WriteLine("Please enter the password:")
            Dim pass As String = Console.ReadLine()
            InitPassword(pass)
            Return True
        End Function

        ' This callback could be used to customize security handler preferences.
        Public Overloads Function EditSecurityData(ByVal doc As SDFDoc) As Boolean
            Return False
        End Function

        ' This callback is used when authorization process fails. 
        Public Overloads Sub AuthorizeFailed()
            Console.WriteLine("Authorize failed...")
        End Sub

        Public Shared Function Create(ByVal name As String, ByVal key_len As Int32, ByVal enc_code As Int32) As SecurityHandler
            Return New MySecurityHandler(key_len, enc_code)
        End Function

        Public Overloads Function Clone() As SecurityHandler
            Return New MySecurityHandler(Me)
        End Function

    End Class


    Sub Main()

        PDFNet.Initialize(PDFTronLicense.Key)

        ' Relative path to the folder containing test files.
        Dim input_path As String = "../../../../TestFiles/"
        Dim output_path As String = "../../../../TestFiles/Output/"

        ' Example 1: Securing a document with password protection and adjusting permissions 
        ' on the document.
        Try
            ' Open the test file
            Console.WriteLine("-------------------------------------------------")
            Console.WriteLine("Securing an existing document...")
            Using doc As PDFDoc = New PDFDoc(input_path + "fish.pdf")
                If Not doc.InitSecurityHandler() Then
                    Console.WriteLine("Document authentication error...")
                    Return
                End If

                ' 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) Then              ' Optional
                    Console.WriteLine("Replacing the content stream, use flate compression...")

                    ' Get the page dictionary using the following path: trailer/Root/Pages/Kids/0
                    Dim page_dict As Obj = doc.GetTrailer().Get("Root").Value(). _
                     Get("Pages").Value(). _
                     Get("Kids").Value(). _
                     GetAt(0)

                    ' Embed a custom stream (file mystream.txt) using Flate compression.
                    Dim embed_file As MappedFile = New MappedFile(input_path + "my_stream.txt")
                    Dim mystm As FilterReader = New FilterReader(embed_file)
                    page_dict.Put("Contents", doc.CreateIndirectStream(mystm))
                    embed_file.Close()
                End If

                ' Apply a new security handler with given security settings. 
                ' In order to open saved PDF you will need a user password 'test'.
                Dim new_handler As StdSecurityHandler = New StdSecurityHandler

                ' Set a new password required to open a document
                Dim my_password As String = "test"
                new_handler.ChangeUserPassword(my_password)

                ' Set Permissions
                new_handler.SetPermission(SecurityHandler.Permission.e_print, True)
                new_handler.SetPermission(SecurityHandler.Permission.e_extract_content, False)

                ' Note: document takes the ownership of new_handler.
                doc.SetSecurityHandler(new_handler)

                ' Save the changes.
                Console.WriteLine("Saving modified file...")
                doc.Save(output_path + "secured.pdf", 0)
            End Using
            Console.WriteLine("Done. Result saved in secured.pdf...")
        Catch e As PDFNetException
            Console.WriteLine(e.Message)
        End Try

        ' Example 2: Reading password protected document without user feedback.
        Try
            ' In this sample case we will open an encrypted document that 
            ' requires a user password in order to access the content.
            Console.WriteLine("-------------------------------------------------")
            Console.WriteLine("Open the password protected document from the first example...")
            Using doc As PDFDoc = New PDFDoc(output_path + "secured.pdf")     ' Open the encrypted document that we saved in the first example. 
                Console.WriteLine("Initializing security handler without any user interaction...")

                ' 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 Not doc.InitStdSecurityHandler("test") Then
                    Console.WriteLine("Document authentication error...")
                    Console.WriteLine("The password is not valid.")
                    Return
                Else
                    Console.WriteLine("The password is correct! Document can now be used for reading and editing")

                    ' Remove the password security and save the changes to a new file.
                    doc.SetSecurityHandler(Nothing)
                    doc.Save(output_path + "secured_nomore1.pdf", 0)
                    Console.WriteLine("Done. Result saved in secured_nomore1.pdf")
                End If
            End Using
        Catch e As PDFNetException
            Console.WriteLine(e.Message)
        End Try

        ' Example 3: 
        ' Encrypt/Decrypt a PDF using PDFTron custom security handler
        Try
            Console.WriteLine("-------------------------------------------------")
            Console.WriteLine("Encrypt a document using PDFTron Custom Security handler with a custom id and password...")
            Dim doc As PDFDoc = New PDFDoc(input_path & "BusinessCardTemplate.pdf")

            ' Create PDFTron custom security handler with a custom id. Replace this with your own integer
            Dim custom_id As Integer = 123456789
            Dim custom_handler As PDFTronCustomSecurityHandler = New PDFTronCustomSecurityHandler(custom_id)
            ' Add a password to the custom security handler
            Dim pass As String = "test"
            custom_handler.ChangeUserPassword(pass)
            ' Save the encrypted document
            doc.SetSecurityHandler(custom_handler)
            doc.Save(output_path & "BusinessCardTemplate_enc.pdf", 0)
            Console.WriteLine("Decrypt the PDFTron custom security encrypted document above...")
            ' Register the PDFTron Custom Security handler with the same custom id used in encryption
            PDFNet.AddPDFTronCustomHandler(custom_id)
            Dim doc_enc As PDFDoc = New PDFDoc(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", 0)
            Console.WriteLine("Done. Result saved in BusinessCardTemplate_enc_dec.pdf")
        Catch e As PDFNetException
            Console.WriteLine(e.Message)
        End Try

        ' Example 4: Reading password protected document with user feedback.
        Try
            ' Register standard security. Reguired only once per application session.
            Dim del As CreateDelegate = New CreateDelegate(AddressOf MySecurityHandler.Create)
            SecurityManagerSingleton.Instance().RegisterSecurityHandler("Standard", _
             New SecurityDescriptor("Standard Security", del))

            Console.WriteLine("-------------------------------------------------")
            Console.WriteLine("Open the password protected document from the first example...")
            Using doc As PDFDoc = New PDFDoc(output_path + "secured.pdf")     ' Open the encrypted document that we saved in the first example.
                Console.WriteLine("Initializing security handler. The password will now be collected from the user")
                Console.WriteLine("Enter 'test' as the password.")

                ' 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 Not doc.InitSecurityHandler() Then
                    Console.WriteLine("Document authentication error...")
                    Console.WriteLine("The password is not valid.")
                    Return
                Else
                    Console.WriteLine("The password is correct! Document can now be used for reading and editing")

                    ' Remove the password security and save the changes to a new file.
                    doc.SetSecurityHandler(Nothing)
                    doc.Save(output_path + "secured_nomore2.pdf", 0)
                    Console.WriteLine("Done. Result saved in secured_nomore2.pdf")
                End If
            End Using
        Catch e As PDFNetException
            Console.WriteLine(e.Message)
        End Try
        PDFNet.Terminate()
        Console.WriteLine("-------------------------------------------------")
        Console.WriteLine("Tests completed.")
    End Sub
End Module
