Decrypt pdfs while import into DT

I receive pdfs that are always enrypted with the same password. Is there a possibility to automatically decrypt them while importing them into devonthink? E.g. if a pdf is imported to a specific folder, it should be opened with a given password and saved unencrypted in this folder? This would simply fantastic… anyone that has an idea if this is possible? I have no experience with automatisation of devonthink (I only use intelligent rules, as they are easy to manage), but no macros/Applescript etc, therefore I have no idea if this is possible at all …

I doubt that you can decrypt PDFs via AppleScript, given the minimal scripting support in Preview.
The situation might be different with other software (Acrobat, perhaps?).

A quick look at the AppleScript library for PDFPen makes it look like you could script the file to open with the password, then print to a new file without a password, then put that unencrypted file into DEVONthink.

You actually can do this with Preview and AS if you send appropriate keystrokes; I’ll post a script I wrote (for use with Hazel, actually) later this evening.

That sounds scary

I sometimes send inappropriate keystrokes but then I hit backspace several times.
:wink: :stuck_out_tongue:

I have a similar situation whereby I receive PDFs which are highly confidential (not) and which are protected by a simple password known to hundreds of ppl.; let’s not discuss whether there is any point in the PDF being password protected… anyway, a Mail rule saves the PDF to my downloads folder. There Hazel picks it up and executes the following script:

tell application "Finder"
	set thePath to "/Users/myUserName/Downloads/limiter.token"
	if not (exists file thePath as POSIX file) then
		do shell script "> $HOME'/Downloads/limiter.token'"
		do shell script "osascript -e 'display notification \"Rule theNameofMyRule about to execute. Sit back.\" sound name \"Glass\"'"
		delay 5
	end if

# the variable theFile is defined by Hazel to point to the path of the file; 

tell application "Preview"
	open theFile
	activate
	delay 0.5
	tell application "System Events"
		if name of theFile contains "abc" then
		# use key codes to send each letter/digit of the password to the password dialog
			key code 45 using shift down
			key code 5
			#...
		else if name of theFile contains "def" then
			key code 45 using shift down
			key code 3
			#...
		else if name of theFile contains "ghi" then
			key code 45 using shift down
			key code 34
			#...
		end if
		key code 76
	end tell
	ignoring application responses
		print document in window 1 print dialog 1 with properties {copies:1, target printer:"NameOfPrinter"}
	end ignoring
	delay 1
	tell application "System Events"
	# my print dialog has "Send PDF to DEVONthink 3" assigned to Command-P
		key code 35 using command down
	end tell
	delay 1
	close window 1 without saving
end tell
tell application "Finder"
	move theFile to trash
	delay 1
end tell

The script checks to see whether there is what I have called a limiter token. If not present, it creates one and displays a notification to tell me the script is going to run. That’s important, because the script will fail if you move the focus away from Preview whilst it is happening; sometimes I receive a number of these documents in one go, so the limiter token stops Hazel from displaying the notification several times and waiting 5 seconds before working on each document.

The script send the document to Preview, enters the password, presses enter, then sends a print command (the document isn’t actually printed; but I do define a printer, because the print dialog uses the standards defined for that printer, e.g. page size), then a Command-P, which I have set up to send the file to DT as PDF. Preview then closes and Finder deletes the original file.

In DT I have a smart rule which deals with these types of files (i.e. names them, marks them read and moves them to a group). That smart rule ends with the following script:

on performSmartRule(theRecords)
	tell application "Finder"
		set thePath to "/Users/myUserName/Downloads/limiter.token"
		if (exists file thePath as POSIX file) then
			delay 30
			if (exists file thePath as POSIX file) then
				delete file thePath as POSIX file
			end if
		end if
	end tell
end performSmartRule

That script deletes the limiter token 30 seconds after the document(s) have been sent to DT; that way Hazel will display a notification again next time a document of this type arrives and is automatically dealt with.

You could do the whole thing from within DT, of course. Because you can effectively “watch” folders (by indexing them), you don’t actually need Hazel to do what I have done. Equally, you could use any other trigger within DT to run the first script (which would need to be modified, of course).

Obviously, this system is unsafe, in that the password is stored in what is effectively a plain text file (the script). Don’t use it for anything which truly needs protecting.

I’m not claiming this is the easiest way to go about things. But it is a way.

2 Likes

@vinschger I usually leave the PDF’s encrypted in the macOS DT database. For decryption I use 2 possibilities:

(1) I have created a 1Password Autofill macro via a Keyboard Maestro macro, which is executed via a mouse click.

(2) With another Keyboard Maestro macro I get the password stored in the macOS keychain, which unlocks the PDF.

! The password is not included/saved in both macros !

Here is an example video:

For security, both macros (when executed) send a notification to all  devices via the Pushover App.

The encrypted PDF’s provide me with additional security in the DEVONthink To Go App and can be quickly decrypted there via the 1Password App.

would this

would this also possible with a script within DT without having to use hazel?

two possibilities… which one do you recommend?

would you be willing to share the macro here?

how does your third party maestro software realize that a simple mouseclick should open it and start the macro?

There does not seem anything referring to KM in the script. Did you try to run it from DT?

Sure, which is why I wrote:

:wink:

I have absolutely no experience with scripting, and do not even know where to enter such a code in devonthink… (shame on me)… for example. is there a possibility to set up an intelligent rule, that opens each pdf that is imported to a certain DT folder FOLDER1, decrypt it with a given password (doesn’t matter if it is saved in a plain text) and saves it unencrypted in a given DT folder FOLDER2.

Or otherwise, a intelligent rule that only works if I drag and drop an encrypted pdf file on it, so that is saved in the same folder as filename_unencrypted.pdf and the original file is deleted?

Any help (and also explanation to udnerstand what you are doing) would be HIGHLY appreciated… But I understand if this should be too timeconsuming … but just in case if on a rainy sunday anyone here might set up such a script, I would be very interested :slight_smile:

Then you might start by reading the „automation“ part of the manual. It should tell you where to put scripts so that you can execute them from the script menu.

1 Like

You could try this script in Script Editor.app. To test:

  • put an encrypted PDF on your desktop, name Input PDF.pdf
  • set your password in property thePassword
  • run script

If the result is an unencrypted new PDF then the rest should be quite easy.

I’ve never used encrypted PDFs so I may be missing something, but it seems to work over here.

-- Test - Decrypt PDF

use AppleScript version "2.4"
use framework "Foundation"
use framework "Quartz"
use scripting additions

property thePassword : "test"
property theInputPath : POSIX path of (path to desktop) & "Input PDF.pdf" -- path of form "/Users/User/Desktop/Input PDF.pdf" (just in case you want to use something else than the desktop)
property theOutputPath : POSIX path of (path to desktop) & "Output PDF.pdf"

set thePDF to current application's PDFDocument's alloc()'s initWithURL:(current application's |NSURL|'s fileURLWithPath:theInputPath)
thePDF's unlockWithPassword:thePassword
thePDF's writeToFile:theOutputPath

1 Like