概要
PDFの文書のプロパティにあるセキュリティ情報を取得します。
- 文書プロパティのセキュリティ設定の有り無し
- 「印刷」を許可しない、する
- 「テキストや画像の抽出」を許可しない、する
- 「内容の変更」を許可しない、する
- 「テキスト注釈の追加・変更と対話式フォームフィールドを埋め込む」 許可しない、する
- 「新しい対話式フォームフィールドを作成と変更」 許可しない、する
Xpdf の pdfindo.exe を使って情報を取得します。
Xpdf
Xpdf について初めて知った方は先にコチラを御覧ください。
機能
- PDFの文書のプロパティ情報をXpdf の pdfindo.exe を「-rawdates 」オプションで取得します。
- 結果は標準出力としてテキストに出力します。
- そのテキストからPDFのセキュリティに関する部分を抽出します。
形式
001 Public Sub xpdfGetPdfSecurity( _
002 ByVal strPdfFilePath As String, _
003 ByRef strOut() As String, _
004 ByRef strErr As String)
Highlight:プログラミング言語のソースコードを構文で色分け (GUI編)
戻り値
無し
VBAサンプル
- 事前にXpdf をコチラを参考にダウンロードしてください。
- そして CON_PDFINFO_PATH に pdfinfo.exe のフルパスを設定します。
Download:cLine-xpdfGetPdfSecurity.xls
001 Option Explicit
002
003 Declare Function WaitForSingleObject Lib "kernel32" _
004 (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
005 Declare Function CloseHandle Lib "kernel32" _
006 (ByVal hObject As Long) As Long
007 Declare Function GetExitCodeProcess Lib "kernel32" _
008 (ByVal hProcess As Long, lpExitCode As Long) As Long
009 Declare Function OpenProcess Lib "kernel32" _
010 (ByVal dwDesiredAccess As Long, _
011 ByVal bInheritHandle As Long, _
012 ByVal dwProcessID As Long) As Long
013 Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
014
015 Const SYNCHRONIZE = 1048576
016 Const PROCESS_QUERY_INFORMATION = &H400
017
018 'xpdf-3.04 pdfinfo.exe
019 Const CON_PDFINFO_PATH = _
020 "D:¥Tools¥xpdfbin-win-3.04¥bin32¥pdfinfo.exe"
021
022 ' テスト用呼び出し
023 Sub Main_Test()
024 Dim strOut(10) As String
025 Dim strPdfFilePath As String
026 Dim strErr As String
027
028 strPdfFilePath = Application.ActiveWorkbook.Path & _
029 "¥" & "TEST-3.pdf"
030
031 Call xpdfGetPdfSecurity(strPdfFilePath, strOut, strErr)
032
033 If strErr <> "" Then
034 MsgBox strErr, vbCritical
035 Exit Sub
036 End If
037 If strOut(0) = "" Then
038 MsgBox "取得出来ませんでした"
039 Exit Sub
040 End If
041
042 Dim i As Long
043 For i = 0 To UBound(strOut)
044 Debug.Print "strOut(" & i & ")=[" & strOut(i) & "]"
045 Next i
046 End Sub
047
048 '**************************************************
049 '
050 ' Get Security information for PDF file
051 '
052 ' 機能 : pdfinfo.exe のメタ情報から
053 ' PDF文書のセキュリティ情報を取得する。
054 '
055 ' Create : 2016/06/20
056 ' Update : 2017/09/14
057 ' Vertion : 1.0.4
058 '
059 ' 引数1 : strPdfFilePath As String (IN)
060 ' PDFファイルのフルパス
061 ' 引数2 : strOut() As String (OUT)
062 ' メタデータの「Encrypted:」の内容
063 ' 引数3 : strErr As String (OUT)
064 ' エラーメッセージ
065 '
066 ' 戻り値 : 無し
067 '
068 ' 備考 : strErr<>""の時はエラー扱いとする。
069 ' strOut(0)=""の時はエラー扱いとする。
070 '
071 ' URL : https://pdf-file.nnn2.com/?p=859
072 '
073 ' その他 : 著作権等は主張しません。
074 ' 上記URLにコメントを頂けると嬉しいです。
075 '
076 '**************************************************
077
078 ' 出力例:サンプル
079 ' strOut(0)="yes" セキュリティ設定有り
080 ' strOut(1)="print:no" 「印刷」 許可しない
081 ' strOut(2)="copy:no" 「テキストや画像の抽出」許可しない
082 ' strOut(3)="change:no" 「内容の変更」 許可しない
083 ' strOut(4)="addNotes:no"
084 ' 「テキスト注釈の追加・変更と対話式フォームフィールドを埋め込む」 許可しない
085 ' 「change:noならば、新しい対話式フォームフィールドを作成と変更」 許可しない
086
087 Public Sub xpdfGetPdfSecurity( _
088 ByVal strPdfFilePath As String, _
089 ByRef strOut() As String, _
090 ByRef strErr As String)
091 On Error GoTo Err_xpdfGetPdfSecurity:
092
093 Dim strXpdfPath As String
094 Dim strOutFilePath As String
095 Dim strCmd As String
096 Dim strInput As String
097 Dim strWk
098 Dim i As Long
099 Dim lFileNo As Long
100
101 '初期化
102 For i = 0 To UBound(strOut)
103 strOut(i) = vbNullString
104 Next i
105
106 'エラーチェック
107 If Dir(strPdfFilePath) = "" Then
108 strErr = strPdfFilePath & vbCrLf & _
109 "このファイルは存在しません"
110 Exit Sub
111 End If
112
113 strXpdfPath = CON_PDFINFO_PATH
114 With CreateObject("Scripting.FileSystemObject")
115 If .FileExists(strXpdfPath) = False Then
116 strErr = strXpdfPath & vbCrLf & _
117 "このファイルは存在しません"
118 Exit Sub
119 End If
120 End With
121
122 strOutFilePath = Application.ActiveWorkbook.Path & _
123 "¥" & Format(Now(), "yyyymmdd-hhmmss") & ".txt"
124
125 'オプションは -meta -rawdates -box どれでもOK。
126 '標準出力をリダイレクトに変更する。
127 '注意:strXpdfPathの前後に”を入れると動かない。
128 strCmd = "cmd /c " & strXpdfPath & " -rawdates """ & _
129 strPdfFilePath & """ > """ & strOutFilePath & """"
130
131 'コマンドラインの実行
132 Call RunCommandLine(strCmd, strErr)
133 If strErr <> "" Then Exit Sub
134
135 '標準出力のテキストを読み込む
136 lFileNo = FreeFile
137 Open strOutFilePath For Input As #lFileNo
138 Do Until EOF(lFileNo)
139 Line Input #lFileNo, strInput
140 If Left$(strInput, 10) = "Encrypted:" Then
141 strWk = Split(Mid(strInput, 17), " ")
142 For i = 0 To UBound(strWk)
143 strWk(i) = Replace(strWk(i), "(", "")
144 strWk(i) = Replace(strWk(i), ")", "")
145 strOut(i) = strWk(i)
146 Next i
147 Exit Do
148 End If
149 Loop
150 Close #lFileNo
151
152 Kill strOutFilePath
153 strErr = ""
154 Exit Sub
155 Err_xpdfGetPdfSecurity:
156 strErr = "xpdfGetPdfSecurity:" & Err.Number & vbCrLf & _
157 Err.Description
158 End Sub
159
160 ' shell関数の終了を待つ
161
162 Sub RunCommandLine(ByVal strCmd As String, _
163 ByRef strErr As String)
164 On Error GoTo Err_RunCommandLine:
165
166 Dim hProcess As Long
167 Dim lpdwExitCode As Long
168 Dim dwProcessID As Long
169 Dim retVal As Long
170 Dim lCnt As Long
171 lCnt = 0
172 dwProcessID = Shell(strCmd, vbHide)
173 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, _
174 True, dwProcessID)
175 Do
176 Sleep 20
177 DoEvents
178 retVal = GetExitCodeProcess(hProcess, lpdwExitCode)
179 lCnt = lCnt + 1
180 If lCnt > 250 Then
181 strErr = "Error:Time Orver 5000ms"
182 Exit Sub
183 End If
184 'shell関数で実行したアプリが終了するまでループ
185 Loop While lpdwExitCode <> 0
186 strErr = ""
187 Exit Sub
188 Err_RunCommandLine:
189 strErr = "RunCommandLine:" & Err.Number & vbCrLf & _
190 Err.Description
191 End Sub
Highlight:プログラミング言語のソースコードを構文で色分け (GUI編)
出力結果
001 strOut(0)=[yes]
002 strOut(1)=[print:no]
003 strOut(2)=[copy:no]
004 strOut(3)=[change:no]
005 strOut(4)=[addNotes:no]
006 strOut(5)=[algorithm:RC4] ※<- Poppler を使うと出る
007 strOut(6)=[]
008 strOut(7)=[]
009 strOut(8)=[]
010 strOut(9)=[]
011 strOut(10)=[]
Highlight:プログラミング言語のソースコードを構文で色分け (GUI編)
補足:
- strOut(0) セキュリティー設定が
- [yes] :有る
- [no] :無い。この時はstrOut(1)以降に値は無い。
- strOut(1) 「印刷」は
- [print:yes] :「許可する」 と思われます。
- [print:no] :「許可しない」 と思われます。
- sstrOut(2) 「テキストや画像の抽出」は
- [copy:yes] :「許可する」 と思われます。
- [copy:no] :「許可しない」 と思われます。
- strOut(3) 「内容の変更」は
- [change:yes] :「許可する」 と思われます。
- [change:no] :「許可しない」 と思われます。
- strOut(4) 「テキスト注釈の追加・変更と対話式フォームフィールドを埋め込む」 「change:noならば、新しい対話式フォームフィールドを作成と変更」 に対して
- addNotes:yes] :「許可する」 と思われます。
- [addNotes:no] :「許可しない」 と思われます。
備考
- 上記の出力結果の内容については全て検証はしていません。
- Poppler の pdfinfo を使う時はCON_PDFINFO_PATHの内容を事前に変更します。
- pdfinfo.exe のオプションは -meta -rawdates -box どれを使ってもOKです。どれも「Encrypted:」を出力します。
- pdfinfo.exe からの出力はセキュリティ・ハンドラのリビジョン2の内容です。リビジョン3又は4の内容が欲しい時はQpdf の「例:qpdf --show-encryption PS-2.pdf」を使います。以下は出力例。括弧はビット位置(勘。
001 R = 3 002 P = -3392 003 User password = 004 extract for accessibility: allowed :(?)アクセシビリティを抽出 005 extract for any purpose: not allowed :(5) 任意の目的での抽出 006 print low resolution: not allowed :(3) 低解像度の印刷 007 print high resolution: not allowed :(12) 高解像度の印刷 008 modify document assembly: not allowed :(?) 文書アセンブリ? 009 modify forms: not allowed :(7) フォームを変更 010 modify annotations: not allowed :(6)注釈を変更 011 modify other: not allowed :(?) その他の変更? 012 modify anything: not allowed :(?) 何かを変更?
- pdfinfo.exe のパス中に空白文字が入らないようにして下さい。入るようでしたら入らないフォルダに移動してご使用ください。理由:この様な場合はパスをダブルクオーテーションでくくればイイのですが、コマンドラインの場合はこの位置でのダブルクオーテーションは有効に働きません。ご注意ください。
- Poppler を使うと処理時間では4倍も掛かる結果が出ています。参考までに。
動作環境
- Windows 10 64bit Pro
- Office 2007 Excel 32bit
< Xpdf へ戻る >
正確な処理時間を測定していなかったですが、「vbHide」の指定、「Sleep」時間の調整で速くなったように思います。
ありがとうございます!
(^.^)v