20260324

【macOS】PDFの暗号化とパスワード設定(Acrobat不要)


【macOS】PDFの暗号化とパスワード設定(Acrobat不要)

NOTE記事一覧ですnote.com
ダウンロードはこちらから


【スクリプトエディタで開く】 |

PDFパスワード設定.scpt
ソース
001#!/usr/bin/env osascript
002#coding: utf-8
003----+----1----+----2----+-----3----+----4----+----5----+----6----+----7
004(*
005別名で保存からアプリケーションにすると便利です
006
007v2 選択内容に依存がある場合の対応をした
008v3 UIの呼び出しを SystemUIServer に変更した
009v3.1 note投稿用に少し整理した
010v3.2 メタデータ削除を選択できるようにした
011
012 com.cocolog-nifty.quicktimer.icefloe *)
013----+----1----+----2----+-----3----+----4----+----5----+----6----+----7
014use AppleScript version "2.8"
015use framework "Foundation"
016use framework "AppKit"
017use framework "PDFKit"
018use scripting additions
019
020property refMe : a reference to current application
021
022####所有者パスワード
023property boolOwnerPW : true as boolean
024####アクアセス権
025##   property intAllowNo : 0 as integer
026(*
027例:全部OKの場合 255 全部ロックは0
028許可する番号を『足し算』する
029低解像度印刷      (*1*) refMe's PDFAllowsLowQualityPrinting
030高解像度印刷      (*2*) refMe's PDFAllowsHighQualityPrinting
031文書に変更         (*4*) refMe's PDFAllowsDocumentChanges
032アッセンブリ      (*8*) refMe's PDFAllowsDocumentAssembly
033コンテンツコピー(*16*) refMe's PDFAllowsContentCopying
034アクセシビリティ(*32*) refMe's PDFAllowsContentAccessibility
035コメント注釈      (*64*) refMe's PDFAllowsCommenting
036フォーム入力      (*128*) refMe's PDFAllowsFormFieldEntry
037
038log refMe's PDFAllowsLowQualityPrinting as integer
039log refMe's PDFAllowsHighQualityPrinting as integer
040log refMe's PDFAllowsDocumentChanges as integer
041log refMe's PDFAllowsDocumentAssembly as integer
042log refMe's PDFAllowsContentCopying as integer
043log refMe's PDFAllowsContentAccessibility as integer
044log refMe's PDFAllowsCommenting as integer
045log refMe's PDFAllowsFormFieldEntry as integer
046
047quartz系は32bit
048"kCGPDFAllowsLowQualityPrinting"
049"kCGPDFAllowsHighQualityPrinting"
050"kCGPDFAllowsDocumentChanges"
051"kCGPDFAllowsDocumentAssembly"
052"kCGPDFAllowsContentCopying"
053"kCGPDFAllowsContentAccessibility"
054"kCGPDFAllowsCommenting"
055"kCGPDFAllowsFormFieldEntry"
056
057
058log refMe's kCGPDFAllowsLowQualityPrinting as integer
059log refMe's kCGPDFAllowsHighQualityPrinting as integer
060log refMe's kCGPDFAllowsDocumentChanges as integer
061log refMe's kCGPDFAllowsDocumentAssembly as integer
062log refMe's kCGPDFAllowsContentCopying as integer
063log refMe's kCGPDFAllowsContentAccessibility as integer
064log refMe's kCGPDFAllowsCommenting as integer
065log refMe's kCGPDFAllowsFormFieldEntry as integer
066*)
067
068##############################
069# RUN
070on run {listDropObject}
071   
072   (*
073ワークフロー用
074
075on run
076   
077   ##############################
078   #ダイアログ
079   set appFileManager to refMe's NSFileManager's defaultManager()
080   set ocidUserDesktopPathArray to (appFileManager's URLsForDirectory:(refMe's NSDesktopDirectory) inDomains:(refMe's NSUserDomainMask))
081   set ocidUserDesktopPathURL to ocidUserDesktopPathArray's firstObject()
082   set aliasUserDesktopPath to (ocidUserDesktopPathURL's absoluteURL()) as alias
083   set listChooseFileUTI to {"com.adobe.pdf"} as list
084   set strPromptText to ("PDFファイルを選んでください") as text
085   tell application "SystemUIServer"
086      activate
087      set listDropObject to (choose file with prompt strPromptText default location aliasUserDesktopPath of type listChooseFileUTI with multiple selections allowed without invisibles and showing package contents) as list
088   end tell
089      *)
090   
091   
092   
093   #選択済みファイルリストをOpenに渡す
094   set boolDone to (open listDropObject) as boolean
095   
096   return boolDone
097end run
098
099##############################
100# OPEN
101on open listDropObject
102   ##############################
103   # ダイアログ
104   set recordOption to {|0A開封PW無し|:999, |0Bメタ情報削除|:888, |1低解像度印刷可|:1, |2高解像度印刷可|:2, |4文書に変更可|:4, |8内容変更可|:8, |16コンテンツコピー可|:16, |32アクセシビリティ可|:32, |64コメント注釈可|:64, |128フォーム入力可|:128} as record
105   #↑のレコードからキーだけを取り出す
106   set ocidOptionDict to refMe's NSMutableDictionary's alloc()'s init()
107   ocidOptionDict's setDictionary:(recordOption)
108   #キーを取り出して
109   set ocidAllKeys to ocidOptionDict's allKeys()
110   #正順に並び替え
111   set ocidSortedArray to ocidAllKeys's sortedArrayUsingSelector:("localizedStandardCompare:")
112   #ダイアログ用にArrayをリストにしておく
113   set listAllKeys to ocidSortedArray as list
114   #
115   set strLF to ("" & linefeed & "") as text
116   set strCR to ("" & return & "") as text
117   set strCRLF to ("" & return & linefeed & "") as text
118   set strSpace to ("" & space & "") as text
119   set strTab to ("" & tab & "") as text
120   set strTitle to "『許可設定する』オプション選択(複数可)" as text
121   set strPrompt to "『許可設定』するオプションを選択してください" & strCR & "何も選択しない=全部禁止" & strCR & "全部選択で全部許可の暗号化のみ" as text
122   try
123      tell application "System Events"
124         activate
125         set listResponse to (choose from list listAllKeys with title strTitle with prompt strPrompt default items (first item of listAllKeys) OK button name "OK" cancel button name "キャンセル" with multiple selections allowed and empty selection allowed) as list
126      end tell
127   on error strErrMsg number numErrNo
128      tell application "System Events" to quit
129      log strErrMsg & numErrNo
130      return false
131   end try
132   tell application "System Events" to quit
133   if listResponse is {} then
134      log "何も選択していない"
135      set strPermissionText to ("全ての処理を禁止") as text
136      set boolOpenPW to true as boolean
137      
138      set intAllowNo to 0 as integer
139   else if (first item of listResponse) is false then
140      log "キャンセルしました"
141      return false
142   else
143      set boolOpenPW to true as boolean
144      set intAllowNo to 0 as integer
145      #保存テキスト用
146      set strPermissionText to (strLF) as text
147      repeat with itemResponse in listResponse
148         set strPermissionText to ("" & strPermissionText & strLF & itemResponse & strLF) as text
149      end repeat
150      #メタデータ削除
151      set boolMetaDel to false as boolean
152      repeat with itemResponse in listResponse
153         set intValue to (ocidOptionDict's valueForKey:(itemResponse)) as integer
154         #戻り値が999ならOPEN時のパスワード設定しない
155         if intValue = 999 then
156            set boolOpenPW to false as boolean
157         else if intValue = 888 then
158            set boolMetaDel to true as boolean
159         else
160            set intAllowNo to (intAllowNo + intValue) as integer
161         end if
162      end repeat
163   end if
164   #許可番号
165   
166   
167   ########################################
168   #実際の処理するPDFのURLを格納するリスト
169   set ocidDropPathURLArray to refMe's NSMutableArray's alloc()'s init()
170   #ドロップされたエイリアスの数だけ繰り返し
171   repeat with itemDropObject in listDropObject
172      #処理除外するエイリアスを判定する
173      set strFilePaht to (POSIX path of itemDropObject) as text
174      set ocidFilePathStr to (refMe's NSString's stringWithString:(strFilePaht))
175      set ocidFilePath to ocidFilePathStr's stringByStandardizingPath()
176      set ocidFilePathURL to (refMe's NSURL's alloc()'s initFileURLWithPath:(ocidFilePath))
177      ###フォルダか?判定
178      set listResponse to (ocidFilePathURL's getResourceValue:(reference) forKey:(refMe's NSURLIsDirectoryKey) |error|:(reference))
179      if (1st item of listResponse) is true then
180         log "getResourceValue 正常処理"
181         set boolIsDir to (2nd item of listResponse) as boolean
182      else if (1st item of listResponse) is false then
183         set strErrorNO to (3rd item of listDone)'s code() as text
184         set strErrorMes to (3rd item of listDone)'s localizedDescription() as text
185         refMe's NSLog("■:" & strErrorNO & strErrorMes)
186         return false
187      end if
188      #フォルダじゃ無いって事は?
189      if boolIsDir is false then
190         set listResponse to (ocidFilePathURL's getResourceValue:(reference) forKey:(refMe's NSURLContentTypeKey) |error|:(reference))
191         if (1st item of listResponse) is true then
192            log "getResourceValue 正常処理"
193            #UTIを取得して
194            set stUTI to (2nd item of listResponse)'s identifier() as text
195         else if (1st item of listResponse) is false then
196            set strErrorNO to (3rd item of listDone)'s code() as text
197            set strErrorMes to (3rd item of listDone)'s localizedDescription() as text
198            refMe's NSLog("■:" & strErrorNO & strErrorMes)
199            return false
200         end if
201         ###getResourceValueの戻り値がNULLだった場合対策
202         if stUTI is "" then
203            tell application "Finder"
204               set refInfoFor to info for aliasFilePath
205               set stUTI to (type identifier of refInfoFor) as text
206            end tell
207         end if
208         #TIがPDFのエイリアスだけ処理する
209         if stUTI is ("com.adobe.pdf") then
210            #PDFDocumentとして読み込み
211            set ocidChkDoc to (refMe's PDFDocument's alloc()'s initWithURL:(ocidFilePathURL))
212            ########################################
213            #暗号化チェック
214            set boolEncrypted to ocidChkDoc's isEncrypted()
215            if boolEncrypted is true then
216               set strMsg to ("エラー:すでに暗号化されているので変更できません") as text
217               set listBottons to {"OK", "キャンセル"} as list
218               tell application "System Events"
219                  activate
220                  display alert strMsg buttons listBottons default button (first item of listBottons) cancel button (last item of listBottons) as informational giving up after 3
221               end tell
222               tell application "System Events" to quit
223               refMe's NSLog("■:" & strMsg)
224               return false
225            end if
226            ########################################
227            #ロック確認
228            set boolLocked to ocidChkDoc's isLocked()
229            log boolLocked
230            if boolLocked is true then
231               set strMsg to "エラー:すでにパスワードでロックされているので変更できません" as text
232               set listBottons to {"OK", "キャンセル"} as list
233               tell application "System Events"
234                  activate
235                  display alert strMsg buttons listBottons default button (first item of listBottons) cancel button (last item of listBottons) as informational giving up after 3
236                  refMe's NSLog("■:" & strMsg)
237               end tell
238               tell application "System Events" to quit
239               return strMes
240            end if
241            #次工程に回す
242            (ocidDropPathURLArray's addObject:(ocidFilePathURL))
243         else
244            set strMsg to "エラー:PDF専用です" as text
245            set listBottons to {"OK", "キャンセル"} as list
246            tell application "System Events"
247               activate
248               display alert strMsg buttons listBottons default button (first item of listBottons) cancel button (last item of listBottons) as informational giving up after 3
249            end tell
250            tell application "System Events" to quit
251            refMe's NSLog("■:" & strMsg)
252            return false
253         end if
254      end if
255   end repeat
256   
257   
258   ########################################
259   #本処理
260   repeat with itemPathURL in ocidDropPathURLArray
261      set ocidFileName to itemPathURL's lastPathComponent()
262      set strBaseFileName to ocidFileName's stringByDeletingPathExtension() as text
263      #PW設定は複製したPDFに対して行うため保存先ディレクトリを作る
264      set strDateNo to doGetDateNo("yyyyMMddHHmmss") as text
265      set strDirName to (strBaseFileName & "_PW設定済_" & strDateNo & "") as text
266      set ocidContainerDirURL to itemPathURL's URLByDeletingLastPathComponent()
267      set ocidDistFolderURL to (ocidContainerDirURL's URLByAppendingPathComponent:(strDirName))
268      set ocidSavePdfURL to (ocidDistFolderURL's URLByAppendingPathComponent:(ocidFileName))
269      #ファイル移動先
270      set appFileManager to refMe's NSFileManager's defaultManager()
271      set ocidAttrDict to (refMe's NSMutableDictionary's alloc()'s initWithCapacity:0)
272      (ocidAttrDict's setValue:511 forKey:(refMe's NSFilePosixPermissions))
273      set listDone to (appFileManager's createDirectoryAtURL:(ocidDistFolderURL) withIntermediateDirectories:true attributes:ocidAttrDict |error|:(reference))
274      if (first item of listDone) is true then
275         log "createDirectoryAtURL 正常処理"
276      else if (first item of listDone) is false then
277         set strErrorNO to (item 2 of listDone)'s code() as text
278         set strErrorMes to (item 2 of listDone)'s localizedDescription() as text
279         refMe's NSLog("■:createDirectoryAtURLでエラー" & strErrorNO & strErrorMes)
280         return false
281      end if
282      
283      #コピー
284      set listDone to (appFileManager's copyItemAtURL:(itemPathURL) toURL:(ocidSavePdfURL) |error|:(reference))
285      if (first item of listDone) is true then
286         log "copyItemAtURL 正常処理"
287      else if (first item of listDone) is false then
288         set strErrorNO to (item 2 of listDone)'s code() as text
289         set strErrorMes to (item 2 of listDone)'s localizedDescription() as text
290         refMe's NSLog("■:コピーでエラー" & strErrorNO & strErrorMes)
291         return false
292      end if
293      
294      #####PDFDocumentとして読み込み
295      set ocidActivDoc to (refMe's PDFDocument's alloc()'s initWithURL:(ocidSavePdfURL))
296      ########################################
297      #パスワード生成 UUIDを利用
298      set strTextFileName to strBaseFileName & ".pw.txt"
299      set ocidTextFilePathURL to (ocidDistFolderURL's URLByAppendingPathComponent:strTextFileName)
300      #生成したUUIDからハイフンを取り除く
301      set ocidConcreteUUID to refMe's NSUUID's UUID()
302      set ocidUUIDString to ocidConcreteUUID's UUIDString()
303      set ocidUUIDString to (ocidUUIDString's stringByReplacingOccurrencesOfString:("-") withString:(""))
304      set strOwnerPassword to ocidUUIDString as text
305      #保存用テキストにする
306      set strTextFile to ("このPDFには所有者PWが『設定』されています" & strLF & "") as text
307      set strTextFile to (strTextFile & "所有者用Pw(教えてはいけないヤツ)" & strLF & strOwnerPassword & strLF) as text
308      if boolOpenPW is true then
309         #生成したUUIDからハイフンを取り除く
310         set ocidConcreteUUID to refMe's NSUUID's UUID()
311         set ocidUUIDString to ocidConcreteUUID's UUIDString()
312         set ocidUUIDString to (ocidUUIDString's stringByReplacingOccurrencesOfString:("-") withString:(""))
313         ##保存用テキストにする
314         set strUserPassword to ocidUUIDString as text
315         set strTextFile to (strTextFile & strLF & "利用者用Pw(他者に教える場合はこちら↓)") as text
316         
317         set strTextFile to (strTextFile & "別に送付しましたPDFの開封パスワードです。" & strLF & "コピペ時には改行が入らないように留意ください") as text
318         set strTextFile to (strTextFile & strLF & strUserPassword & strLF) as text
319      else
320         
321         set strTextFile to (strTextFile & strLF & strLF & strLF & "利用者用パスワード(開封パスワード)は『未設定』です" & strLF & "このまま配布できます" & strLF) as text
322         set strTextFile to (strTextFile & "誰でも閲覧は可能です" & strLF) as text
323      end if
324      set strTextFile to (strTextFile & strLF & strLF & strLF & "設定された許可項目:" & strPermissionText & "です") as text
325      
326      set ocidPWString to (refMe's NSString's stringWithString:(strTextFile))
327      set ocidUUIDData to (ocidPWString's dataUsingEncoding:(refMe's NSUTF8StringEncoding))
328      #NSDATA
329      set ocidOption to (refMe's NSDataWritingAtomic)
330      set listDone to (ocidUUIDData's writeToURL:(ocidTextFilePathURL) options:(ocidOption) |error|:(reference))
331      
332      ########################################
333      #保存OPTION
334      set ocidOptionDict to refMe's NSMutableDictionary's alloc()'s init()
335      if boolOwnerPW is true then
336         (ocidOptionDict's setObject:(strOwnerPassword) forKey:(refMe's PDFDocumentOwnerPasswordOption))
337      end if
338      if boolOpenPW is true then
339         #開封パスワード
340         (ocidOptionDict's setObject:(strUserPassword) forKey:(refMe's PDFDocumentUserPasswordOption))
341      end if
342      ##############################
343      #セキュリティ設定
344      log intAllowNo
345      (ocidOptionDict's setObject:(intAllowNo) forKey:(refMe's PDFDocumentAccessPermissionsOption))
346      
347      
348      ##############################
349      #メタデータ削除
350      if boolMetaDel is true then
351         set ocidAttarDict to refMe's NSMutableDictionary's alloc()'s init()
352         (ocidAttarDict's setObject:("") forKey:("PDFDocumentTitleAttribute"))
353         (ocidAttarDict's setObject:("") forKey:("PDFDocumentAuthorAttribute"))
354         (ocidAttarDict's setObject:("") forKey:("PDFDocumentSubjectAttribute"))
355         (ocidAttarDict's setObject:("") forKey:("PDFDocumentCreatorAttribute"))
356         (ocidAttarDict's setObject:("") forKey:("PDFDocumentKeywordsAttribute"))
357         (ocidAttarDict's setObject:("") forKey:("PDFDocumentProducerAttribute"))
358         (ocidAttarDict's setObject:("") forKey:("PDFDocumentModificationDateAttribute"))
359         (ocidAttarDict's setObject:("") forKey:("PDFDocumentCreationDateAttribute"))
360         #
361         (ocidActivDoc's setDocumentAttributes:(ocidAttarDict))
362      end if
363      ########################################
364      #保存
365      set boolDone to (ocidActivDoc's writeToURL:(ocidSavePdfURL) withOptions:(ocidOptionDict))
366   end repeat
367   ########################################
368   #保存先を開く
369   set appSharedWorkspace to refMe's NSWorkspace's sharedWorkspace()
370   set boolDone to appSharedWorkspace's openURL:(ocidDistFolderURL)
371   return boolDone
372end open
373
374
375########################################
376#フォルダ名重複回避用の日付時間
377to doGetDateNo(argFormatStrings)
378   set ocidDate to refMe's NSDate's |date|()
379   set ocidNSDateFormatter to refMe's NSDateFormatter's alloc()'s init()
380   ocidNSDateFormatter's setLocale:(refMe's NSLocale's localeWithLocaleIdentifier:"ja_JP_POSIX")
381   ocidNSDateFormatter's setDateFormat:(argFormatStrings)
382   set ocidDateAndTime to ocidNSDateFormatter's stringFromDate:(ocidDate)
383   set strDateAndTime to ocidDateAndTime as text
384   return strDateAndTime
385end doGetDateNo
AppleScriptで生成しました