Sample code for 30+ languages & platforms
SQL Server Requires Chilkat v11.7.0+

Restrict Printing, Copying and Editing of a PDF

See more PDF Protection Examples

Demonstrates a PDF that opens without a password but limits what a reader may do with it. The user password is left empty, the owner password protects the restrictions, and the permissions member of the JSON says what is denied. Chilkat honors these permissions itself: with copying denied, text extraction is refused unless the PDF is loaded with its owner password. An empty owner password is refused when anything is restricted, because anyone opening the file would then have owner rights.

Chilkat SQL Server Downloads

SQL Server
--
CREATE PROCEDURE ChilkatSample
AS
BEGIN
    DECLARE @hr int
    DECLARE @iTmp0 int
    DECLARE @sTmp0 nvarchar(4000)
    DECLARE @success int
    SELECT @success = 0

    --  This example requires the Chilkat API to have been previously unlocked.
    --  See Global Unlock Sample for sample code.

    --  The PDF used in this example is available at two_page_memo.pdf

    DECLARE @pdf int
    EXEC @hr = sp_OACreate 'Chilkat.Pdf', @pdf OUT
    IF @hr <> 0
    BEGIN
        PRINT 'Failed to create ActiveX component'
        RETURN
    END

    EXEC sp_OAMethod @pdf, 'LoadFile', @success OUT, 'qa_data/pdf/two_page_memo.pdf'
    IF @success = 0
      BEGIN
        EXEC sp_OAGetProperty @pdf, 'LastErrorText', @sTmp0 OUT
        PRINT @sTmp0
        EXEC @hr = sp_OADestroy @pdf
        RETURN
      END

    --  No user password: the PDF opens without a prompt.  The owner password is what protects the
    --  restrictions, so it must not be empty when anything is restricted.
    EXEC sp_OASetProperty @pdf, 'UserPassword', ''
    EXEC sp_OASetProperty @pdf, 'OwnerPassword', 'owner-secret'

    DECLARE @json int
    EXEC @hr = sp_OACreate 'Chilkat.JsonObject', @json OUT

    EXEC sp_OAMethod @json, 'UpdateString', @success OUT, 'permissions.print', 'lowQuality'
    EXEC sp_OAMethod @json, 'UpdateBool', @success OUT, 'permissions.copy', 0
    EXEC sp_OAMethod @json, 'UpdateBool', @success OUT, 'permissions.modify', 0
    EXEC sp_OAMethod @json, 'UpdateBool', @success OUT, 'permissions.annotate', 0
    --  The permissions not mentioned (fillForms, assemble, accessibility) stay granted.

    DECLARE @jsonOut int
    EXEC @hr = sp_OACreate 'Chilkat.JsonObject', @jsonOut OUT

    EXEC sp_OAMethod @pdf, 'Protection', @success OUT, 'encrypt', @json, @jsonOut
    IF @success = 0
      BEGIN
        EXEC sp_OAGetProperty @pdf, 'LastErrorText', @sTmp0 OUT
        PRINT @sTmp0
        EXEC @hr = sp_OADestroy @pdf
        EXEC @hr = sp_OADestroy @json
        EXEC @hr = sp_OADestroy @jsonOut
        RETURN
      END
    EXEC sp_OAMethod @pdf, 'WriteFile', @success OUT, 'qa_output/memo_restricted.pdf'
    IF @success = 0
      BEGIN
        EXEC sp_OAGetProperty @pdf, 'LastErrorText', @sTmp0 OUT
        PRINT @sTmp0
        EXEC @hr = sp_OADestroy @pdf
        EXEC @hr = sp_OADestroy @json
        EXEC @hr = sp_OADestroy @jsonOut
        RETURN
      END

    --  Anyone can open the result, with the rights of a user.
    DECLARE @reader int
    EXEC @hr = sp_OACreate 'Chilkat.Pdf', @reader OUT

    EXEC sp_OAMethod @reader, 'LoadFile', @success OUT, 'qa_output/memo_restricted.pdf'
    IF @success = 0
      BEGIN
        EXEC sp_OAGetProperty @reader, 'LastErrorText', @sTmp0 OUT
        PRINT @sTmp0
        EXEC @hr = sp_OADestroy @pdf
        EXEC @hr = sp_OADestroy @json
        EXEC @hr = sp_OADestroy @jsonOut
        EXEC @hr = sp_OADestroy @reader
        RETURN
      END
    DECLARE @empty int
    EXEC @hr = sp_OACreate 'Chilkat.JsonObject', @empty OUT

    DECLARE @info int
    EXEC @hr = sp_OACreate 'Chilkat.JsonObject', @info OUT

    EXEC sp_OAMethod @reader, 'Protection', @success OUT, 'getInfo', @empty, @info
    IF @success = 0
      BEGIN
        EXEC sp_OAGetProperty @reader, 'LastErrorText', @sTmp0 OUT
        PRINT @sTmp0
        EXEC @hr = sp_OADestroy @pdf
        EXEC @hr = sp_OADestroy @json
        EXEC @hr = sp_OADestroy @jsonOut
        EXEC @hr = sp_OADestroy @reader
        EXEC @hr = sp_OADestroy @empty
        EXEC @hr = sp_OADestroy @info
        RETURN
      END

    EXEC sp_OAMethod @info, 'StringOf', @sTmp0 OUT, 'loaded.openedWith'
    PRINT 'opened with: ' + @sTmp0

    EXEC sp_OAMethod @info, 'StringOf', @sTmp0 OUT, 'loaded.permissions.print'
    PRINT 'print: ' + @sTmp0

    EXEC sp_OAMethod @info, 'BoolOf', @iTmp0 OUT, 'loaded.permissions.copy'
    PRINT 'copy: ' + @iTmp0

    EXEC sp_OAMethod @info, 'BoolOf', @iTmp0 OUT, 'loaded.permissions.modify'
    PRINT 'modify: ' + @iTmp0

    --  Chilkat honors the restrictions.  Copying is not permitted, so the text cannot be extracted.
    DECLARE @opts int
    EXEC @hr = sp_OACreate 'Chilkat.JsonObject', @opts OUT

    DECLARE @extractOut int
    EXEC @hr = sp_OACreate 'Chilkat.JsonObject', @extractOut OUT

    DECLARE @sb int
    EXEC @hr = sp_OACreate 'Chilkat.StringBuilder', @sb OUT

    EXEC sp_OAMethod @reader, 'ExtractTextSb', @success OUT, 'text', @opts, @sb, @extractOut
    IF @success = 0
      BEGIN

        PRINT 'Text extraction was refused: the PDF does not permit copying.'
      END

    --  The owner password lifts every restriction.
    DECLARE @owner int
    EXEC @hr = sp_OACreate 'Chilkat.Pdf', @owner OUT

    EXEC sp_OASetProperty @owner, 'OwnerPassword', 'owner-secret'
    EXEC sp_OAMethod @owner, 'LoadFile', @success OUT, 'qa_output/memo_restricted.pdf'
    IF @success = 0
      BEGIN
        EXEC sp_OAGetProperty @owner, 'LastErrorText', @sTmp0 OUT
        PRINT @sTmp0
        EXEC @hr = sp_OADestroy @pdf
        EXEC @hr = sp_OADestroy @json
        EXEC @hr = sp_OADestroy @jsonOut
        EXEC @hr = sp_OADestroy @reader
        EXEC @hr = sp_OADestroy @empty
        EXEC @hr = sp_OADestroy @info
        EXEC @hr = sp_OADestroy @opts
        EXEC @hr = sp_OADestroy @extractOut
        EXEC @hr = sp_OADestroy @sb
        EXEC @hr = sp_OADestroy @owner
        RETURN
      END
    DECLARE @ownerInfo int
    EXEC @hr = sp_OACreate 'Chilkat.JsonObject', @ownerInfo OUT

    EXEC sp_OAMethod @owner, 'Protection', @success OUT, 'getInfo', @empty, @ownerInfo
    IF @success = 0
      BEGIN
        EXEC sp_OAGetProperty @owner, 'LastErrorText', @sTmp0 OUT
        PRINT @sTmp0
        EXEC @hr = sp_OADestroy @pdf
        EXEC @hr = sp_OADestroy @json
        EXEC @hr = sp_OADestroy @jsonOut
        EXEC @hr = sp_OADestroy @reader
        EXEC @hr = sp_OADestroy @empty
        EXEC @hr = sp_OADestroy @info
        EXEC @hr = sp_OADestroy @opts
        EXEC @hr = sp_OADestroy @extractOut
        EXEC @hr = sp_OADestroy @sb
        EXEC @hr = sp_OADestroy @owner
        EXEC @hr = sp_OADestroy @ownerInfo
        RETURN
      END

    EXEC sp_OAMethod @ownerInfo, 'StringOf', @sTmp0 OUT, 'loaded.openedWith'
    PRINT 'opened with: ' + @sTmp0
    EXEC sp_OAMethod @owner, 'ExtractTextSb', @success OUT, 'text', @opts, @sb, @extractOut
    IF @success = 0
      BEGIN
        EXEC sp_OAGetProperty @owner, 'LastErrorText', @sTmp0 OUT
        PRINT @sTmp0
        EXEC @hr = sp_OADestroy @pdf
        EXEC @hr = sp_OADestroy @json
        EXEC @hr = sp_OADestroy @jsonOut
        EXEC @hr = sp_OADestroy @reader
        EXEC @hr = sp_OADestroy @empty
        EXEC @hr = sp_OADestroy @info
        EXEC @hr = sp_OADestroy @opts
        EXEC @hr = sp_OADestroy @extractOut
        EXEC @hr = sp_OADestroy @sb
        EXEC @hr = sp_OADestroy @owner
        EXEC @hr = sp_OADestroy @ownerInfo
        RETURN
      END

    EXEC sp_OAGetProperty @sb, 'Length', @iTmp0 OUT
    PRINT 'characters extracted with the owner password: ' + @iTmp0

    --  Sample output:

    --  opened with: emptyPassword
    --  print: lowQuality
    --  copy: False
    --  modify: False
    --  Text extraction was refused: the PDF does not permit copying.
    --  opened with: owner
    --  characters extracted with the owner password: 1048

    EXEC @hr = sp_OADestroy @pdf
    EXEC @hr = sp_OADestroy @json
    EXEC @hr = sp_OADestroy @jsonOut
    EXEC @hr = sp_OADestroy @reader
    EXEC @hr = sp_OADestroy @empty
    EXEC @hr = sp_OADestroy @info
    EXEC @hr = sp_OADestroy @opts
    EXEC @hr = sp_OADestroy @extractOut
    EXEC @hr = sp_OADestroy @sb
    EXEC @hr = sp_OADestroy @owner
    EXEC @hr = sp_OADestroy @ownerInfo


END
GO