mirror of
https://github.com/apprenticeharper/DeDRM_tools
synced 2024-11-18 21:25:39 +00:00
2191 lines
163 KiB
Plaintext
2191 lines
163 KiB
Plaintext
property prefsFileName : "com.apprenticealf.dedrm.plist"
|
||
property tempFileName : "DeDRM_temp.log"
|
||
property prefsFolderName : "com.apprenticealf.dedrm"
|
||
property newKeysFolderName : "newKeys"
|
||
property handledExtensions : {"epub", "pdf", "prc", "azw", "azw1", "tpz", "azw3", "azw4", "mobi", "pobi", "pdb"}
|
||
|
||
global python
|
||
global oldAppleScript
|
||
|
||
global eReaderTool
|
||
global MobipocketTool
|
||
global KindlePIDTool
|
||
global BNKeyGenTool
|
||
global BNKeyFetchTool
|
||
global BNePubTool
|
||
global KindleKeyTool
|
||
global NookKeyTool
|
||
global AdobeKeyGenTool
|
||
global AdobeePubTool
|
||
global ePubTestTool
|
||
global AdobePDFTool
|
||
global ZipFixTool
|
||
global ProgressApp
|
||
|
||
global PIDs
|
||
global UDIDs
|
||
global bnKeys
|
||
global KindleSerialList
|
||
global AndroidKeyList
|
||
global KindleKeyList
|
||
global AdeptKeyList
|
||
|
||
global ErrorList
|
||
global WarningList
|
||
global CompletedList
|
||
global ErrorCount
|
||
global WarningCount
|
||
global CompletedCount
|
||
global totalebooks
|
||
global completedebooks
|
||
global outputFolder
|
||
global logFilePath
|
||
global tempfilepath
|
||
|
||
global paraend
|
||
|
||
on writetolog(logstring)
|
||
try
|
||
set fileRef to open for access logFilePath with write permission
|
||
write logstring & "
|
||
" to fileRef starting at eof as «class utf8»
|
||
close access fileRef
|
||
end try
|
||
end writetolog
|
||
|
||
on clearlog()
|
||
try
|
||
set fileRef to open for access logFilePath with write permission
|
||
set eof fileRef to 0
|
||
close access fileRef
|
||
end try
|
||
end clearlog
|
||
|
||
on cleartemp()
|
||
try
|
||
set fileRef to open for access tempfilepath with write permission
|
||
set eof fileRef to 0
|
||
close access fileRef
|
||
end try
|
||
end cleartemp
|
||
|
||
on readtemp()
|
||
set tempContents to ""
|
||
try
|
||
set fileRef to open for access tempfilepath
|
||
if (get eof fileRef) > 0 then
|
||
set tempContents to read fileRef from 1 as «class utf8»
|
||
end if
|
||
close access fileRef
|
||
end try
|
||
return tempContents
|
||
end readtemp
|
||
|
||
on readtemplist()
|
||
set templist to {}
|
||
try
|
||
set fileRef to open for access tempfilepath
|
||
if (get eof fileRef) > 0 then
|
||
set tempContents to paragraphs of (read fileRef from 1 as «class utf8»)
|
||
end if
|
||
close access fileRef
|
||
end try
|
||
repeat with nextLine in tempContents
|
||
if length of nextLine is greater than 0 then
|
||
copy nextLine to the end of templist
|
||
end if
|
||
end repeat
|
||
return templist
|
||
end readtemplist
|
||
|
||
on quotedtemppath()
|
||
set tempFile to POSIX path of file tempfilepath
|
||
return quoted form of tempFile
|
||
end quotedtemppath
|
||
|
||
on folderexists(inputFolder)
|
||
try
|
||
--display dialog "test -d " & quoted form of (POSIX path of inputFolder)
|
||
do shell script "test -d " & quoted form of (POSIX path of inputFolder)
|
||
return true
|
||
end try
|
||
|
||
return false
|
||
end folderexists
|
||
|
||
on fileexists(inputFile)
|
||
try
|
||
do shell script "test -f " & quoted form of (POSIX path of inputFile)
|
||
return true
|
||
end try
|
||
|
||
return false
|
||
end fileexists
|
||
|
||
on GetFileExtension(fileName)
|
||
set fileExtension to ""
|
||
if fileName contains "." then
|
||
set oldTIDs to AppleScript's text item delimiters
|
||
set AppleScript's text item delimiters to "."
|
||
set fileExtension to the last text item of fileName
|
||
set AppleScript's text item delimiters to oldTIDs
|
||
end if
|
||
return fileExtension
|
||
end GetFileExtension
|
||
|
||
on GetFileNameOnly(fileName)
|
||
set fileNameOnly to fileName
|
||
if fileName contains "." then
|
||
set oldTIDs to AppleScript's text item delimiters
|
||
set AppleScript's text item delimiters to "."
|
||
set fileNameOnly to (text items 1 through -2 of fileName) as string
|
||
set AppleScript's text item delimiters to oldTIDs
|
||
end if
|
||
return fileNameOnly
|
||
end GetFileNameOnly
|
||
|
||
on GetTools()
|
||
set paraend to "
|
||
"
|
||
set ASnumber to (text 1 thru 3 of (AppleScript's version as text) as real)
|
||
set oldAppleScript to (ASnumber < 2.0)
|
||
set python to "/usr/local/bin/python"
|
||
if not fileexists(python) then
|
||
set python to "/usr/bin/python"
|
||
end if
|
||
set pythonversion to "2.3"
|
||
try
|
||
set pythonversion to do shell script python & " -c \"from sys import version; print version[:3]\""
|
||
end try
|
||
-- display dialog pythonversion
|
||
if (pythonversion is not "2.5") and (pythonversion is not "2.6") and (pythonversion is not "2.7") then
|
||
set dialogresult to (display dialog "This AppleScript requires Python 2.7x.
|
||
|
||
Please install python 2.7x and try again." buttons {"Quit"} default button 1 with title "DeDRM" with icon stop)
|
||
return false
|
||
end if
|
||
-- we always want a space after the command
|
||
set python to python & " "
|
||
|
||
set eReaderTool to POSIX path of (path to resource "erdr2pml.py")
|
||
set MobipocketTool to POSIX path of (path to resource "k4mobidedrm.py")
|
||
set KindlePIDTool to POSIX path of (path to resource "kindlepid.py")
|
||
set BNKeyGenTool to POSIX path of (path to resource "ignoblekeygen.py")
|
||
set BNKeyFetchTool to POSIX path of (path to resource "ignoblekeyfetch.py")
|
||
set BNePubTool to POSIX path of (path to resource "ignobleepub.py")
|
||
set KindleKeyTool to POSIX path of (path to resource "kindlekey.py")
|
||
set NookKeyTool to POSIX path of (path to resource "ignoblekey.py")
|
||
set AdobeKeyGenTool to POSIX path of (path to resource "adobekey.py")
|
||
set AdobeePubTool to POSIX path of (path to resource "ineptepub.py")
|
||
set ePubTestTool to POSIX path of (path to resource "epubtest.py")
|
||
set AdobePDFTool to POSIX path of (path to resource "ineptpdf.py")
|
||
set ZipFixTool to POSIX path of (path to resource "zipfix.py")
|
||
set ProgressApp to POSIX path of (path to resource "DeDRM Progress.app")
|
||
if not fileexists(eReaderTool) then
|
||
set dialogresult to (display dialog "The eReader script (erdr2pml.py) is missing from this package. Get a fresh copy." buttons {"Quit", "Continue Anyway"} default button 1 with title "DeDRM" with icon stop)
|
||
if button returned of dialogresult is "Quit" then
|
||
return false
|
||
end if
|
||
end if
|
||
if not fileexists(MobipocketTool) then
|
||
--display dialog MobipocketTool
|
||
set dialogresult to (display dialog "The Mobipocket script (k4mobidedrm.py) is missing from this package. Get a fresh copy." buttons {"Quit", "Continue Anyway"} default button 1 with title "DeDRM" with icon stop)
|
||
if button returned of dialogresult is "Quit" then
|
||
return false
|
||
end if
|
||
end if
|
||
if not fileexists(KindlePIDTool) then
|
||
--display dialog KindlePIDTool
|
||
set dialogresult to (display dialog "The KindlePID script (kindlepid.py) is missing from this package. Get a fresh copy." buttons {"Quit", "Continue Anyway"} default button 1 with title "DeDRM" with icon stop)
|
||
if button returned of dialogresult is "Quit" then
|
||
return false
|
||
end if
|
||
end if
|
||
if not fileexists(BNKeyGenTool) then
|
||
set dialogresult to (display dialog "The B&N Key Generation script (ignoblekeygen.py) is missing from this package. Get a fresh copy." buttons {"Quit", "Continue Anyway"} default button 1 with title "DeDRM" with icon stop)
|
||
if button returned of dialogresult is "Quit" then
|
||
return false
|
||
end if
|
||
end if
|
||
if not fileexists(BNKeyFetchTool) then
|
||
set dialogresult to (display dialog "The B&N Key Fetch script (ignoblekeyfetch.py) is missing from this package. Get a fresh copy." buttons {"Quit", "Continue Anyway"} default button 1 with title "DeDRM" with icon stop)
|
||
if button returned of dialogresult is "Quit" then
|
||
return false
|
||
end if
|
||
end if
|
||
if not fileexists(BNePubTool) then
|
||
set dialogresult to (display dialog "The B&N script (ignobleepub.py) is missing from this package. Get a fresh copy." buttons {"Quit", "Continue Anyway"} default button 1 with title "DeDRM" with icon stop)
|
||
if button returned of dialogresult is "Quit" then
|
||
return false
|
||
end if
|
||
end if
|
||
if not fileexists(NookKeyTool) then
|
||
set dialogresult to (display dialog "The B&N Key Retrieval script (ignoblekey.py) is missing from this package. Get a fresh copy." buttons {"Quit", "Continue Anyway"} default button 1 with title "DeDRM" with icon stop)
|
||
if button returned of dialogresult is "Quit" then
|
||
return false
|
||
end if
|
||
end if
|
||
if not fileexists(KindleKeyTool) then
|
||
set dialogresult to (display dialog "The Kindle Key Generation script (kindlekey.py) is missing from this package. Get a fresh copy." buttons {"Quit", "Continue Anyway"} default button 1 with title "DeDRM" with icon stop)
|
||
if button returned of dialogresult is "Quit" then
|
||
return false
|
||
end if
|
||
end if
|
||
if not fileexists(AdobeKeyGenTool) then
|
||
set dialogresult to (display dialog "The Adobe Key Generation script (adobekey.py) is missing from this package. Get a fresh copy." buttons {"Quit", "Continue Anyway"} default button 1 with title "DeDRM" with icon stop)
|
||
if button returned of dialogresult is "Quit" then
|
||
return false
|
||
end if
|
||
end if
|
||
if not fileexists(AdobePDFTool) then
|
||
set dialogresult to (display dialog "The Adobe PDF script (ineptpdf.py) is missing from this package. Get a fresh copy." buttons {"Quit", "Continue Anyway"} default button 1 with title "DeDRM" with icon stop)
|
||
if button returned of dialogresult is "Quit" then
|
||
return false
|
||
end if
|
||
end if
|
||
if not fileexists(AdobeePubTool) then
|
||
set dialogresult to (display dialog "The Adobe ePub script (ineptepub.py) is missing from this package. Get a fresh copy." buttons {"Quit", "Continue Anyway"} default button 1 with title "DeDRM" with icon stop)
|
||
if button returned of dialogresult is "Quit" then
|
||
return false
|
||
end if
|
||
end if
|
||
if not fileexists(ePubTestTool) then
|
||
set dialogresult to (display dialog "The ePub encryption test script (epubtesttool.py) is missing from this package. Get a fresh copy." buttons {"Quit", "Continue Anyway"} default button 1 with title "DeDRM" with icon stop)
|
||
if button returned of dialogresult is "Quit" then
|
||
return false
|
||
end if
|
||
end if
|
||
if not folderexists(ProgressApp) then
|
||
set dialogresult to (display dialog "The Progress dialog application (DeDRM Progress.app) is missing from this package. Get a fresh copy." buttons {"Quit", "Continue Anyway"} default button 1 with title "DeDRM" with icon stop)
|
||
if button returned of dialogresult is "Quit" then
|
||
return false
|
||
end if
|
||
end if
|
||
return true
|
||
end GetTools
|
||
|
||
on unlockmobifile(encryptedFile)
|
||
--check it's a mobi file.
|
||
set BOOKMOBI to "NOTAMOBI"
|
||
try
|
||
set BOOKMOBI to read file encryptedFile from 61 for 8
|
||
end try
|
||
if BOOKMOBI is not "BOOKMOBI" and BOOKMOBI is not "TEXtREAd" then
|
||
set TOPAZ to "NOT"
|
||
try
|
||
set TOPAZ to read file encryptedFile from 1 for 4
|
||
end try
|
||
if TOPAZ is not "TPZ0" then
|
||
set ErrorCount to ErrorCount + 1
|
||
set ErrorList to ErrorList & encryptedFile & " is neither a Kindle not a Mobipocket file.
|
||
"
|
||
return
|
||
end if
|
||
end if
|
||
set encryptedFilePath to POSIX path of file encryptedFile
|
||
tell application "Finder"
|
||
set parent_folder to (container of file encryptedFile) as text
|
||
set fileName to (name of file encryptedFile) as text
|
||
end tell
|
||
set fileExtension to "." & GetFileExtension(fileName)
|
||
set fileName to GetFileNameOnly(fileName)
|
||
if outputFolder is "" or not folderexists(outputFolder) then
|
||
set dedrmFolder to POSIX path of file parent_folder
|
||
else
|
||
set dedrmFolder to POSIX path of file outputFolder
|
||
end if
|
||
set shellcommand to python & (quoted form of MobipocketTool)
|
||
repeat with KindleKeyPath in KindleKeyList
|
||
set shellcommand to shellcommand & " -k " & quoted form of KindleKeyPath
|
||
end repeat
|
||
repeat with AndroidKeyPath in AndroidKeyList
|
||
set shellcommand to shellcommand & " -a " & quoted form of AndroidKeyPath
|
||
end repeat
|
||
set Serialstring to GetSerialstring()
|
||
if Serialstring is not "" then set shellcommand to shellcommand & " -s " & quoted form of Serialstring
|
||
set PIDstring to GetPIDstring()
|
||
if PIDstring is "" then
|
||
set PIDstring to GetUDIDPIDs()
|
||
else
|
||
set PIDstring to PIDstring & "," & GetUDIDPIDs()
|
||
end if
|
||
|
||
if PIDstring is not "" then set shellcommand to shellcommand & " -p " & quoted form of PIDstring
|
||
set shellcommand to shellcommand & " " & (quoted form of encryptedFilePath) & " " & (quoted form of dedrmFolder)
|
||
set shellcommand to shellcommand & " > " & quotedtemppath()
|
||
--display dialog "shellcommand: " default answer shellcommand buttons {"OK"} default button 1 giving up after 10
|
||
writetolog("shellcommand: " & shellcommand)
|
||
cleartemp()
|
||
set DecodingError to false
|
||
set shellresult to ""
|
||
set ErrorText to ""
|
||
set decoded to true
|
||
try
|
||
do shell script shellcommand
|
||
on error ErrorText number errnum
|
||
set DecodingError to true
|
||
set decoded to false
|
||
end try
|
||
set shellresult to readtemp()
|
||
writetolog("shellresult: " & shellresult & " " & ErrorText)
|
||
if decoded then
|
||
set decoded to ((offset of "No key found" in shellresult) is 0)
|
||
end if
|
||
if not decoded then
|
||
DecodingError = true
|
||
set newKeyList to GetKindleKeys()
|
||
if length of newKeyList > 0 then
|
||
set shellcommand to python & (quoted form of MobipocketTool)
|
||
repeat with KindleKeyPath in newKeyList
|
||
set shellcommand to shellcommand & " -k " & quoted form of KindleKeyPath
|
||
end repeat
|
||
set shellcommand to shellcommand & " " & (quoted form of encryptedFilePath) & " " & (quoted form of dedrmFolder)
|
||
set shellcommand to shellcommand & " > " & quotedtemppath()
|
||
--display dialog "shellcommand: " default answer shellcommand buttons {"OK"} default button 1 giving up after 10
|
||
writetolog("shellcommand: " & shellcommand)
|
||
cleartemp()
|
||
set DecodingError to false
|
||
set shellresult to ""
|
||
set ErrorText to ""
|
||
set decoded to true
|
||
try
|
||
do shell script shellcommand
|
||
on error ErrorText number errnum
|
||
set DecodingError to true
|
||
set decoded to false
|
||
end try
|
||
set shellresult to readtemp()
|
||
writetolog("shellresult: " & shellresult & " " & ErrorText)
|
||
if decoded then
|
||
set DecodingError to not ((offset of "No key found" in shellresult) is 0)
|
||
end if
|
||
if not DecodingError then
|
||
set KindleKeyList to KindleKeyList & newKeyList
|
||
end if
|
||
end if
|
||
end if
|
||
if DecodingError then
|
||
set ErrorCount to ErrorCount + 1
|
||
set ErrorList to ErrorList & fileName & fileExtension & " couldn't be decrypted.
|
||
"
|
||
else if (offset of "not encrypted" in shellresult) > 0 then
|
||
set WarningCount to WarningCount + 1
|
||
set WarningList to WarningList & fileName & fileExtension & " is not encrypted.
|
||
"
|
||
else
|
||
set CompletedCount to CompletedCount + 1
|
||
set CompletedList to CompletedList & fileName & fileExtension & paraend
|
||
end if
|
||
end unlockmobifile
|
||
|
||
on unlockpdbfile(encryptedFile)
|
||
--check it's an eReader file.
|
||
set PNRdPPrs to "NOT_eREADER"
|
||
try
|
||
set PNRdPPrs to read file encryptedFile from 61 for 8
|
||
end try
|
||
if PNRdPPrs is not "PNRdPPrs" then
|
||
set ErrorCount to ErrorCount + 1
|
||
set ErrorList to ErrorList & encryptedFile & " is not an eReader file.
|
||
"
|
||
return
|
||
end if
|
||
set encryptedFilePath to POSIX path of file encryptedFile
|
||
tell application "Finder"
|
||
set parent_folder to (container of file encryptedFile) as text
|
||
set fileName to (name of file encryptedFile) as text
|
||
end tell
|
||
set fileExtension to "." & GetFileExtension(fileName)
|
||
set fileName to GetFileNameOnly(fileName)
|
||
if outputFolder is "" or not folderexists(outputFolder) then
|
||
set dedrmFolder to parent_folder
|
||
else
|
||
set dedrmFolder to outputFolder
|
||
end if
|
||
set pmlFile to dedrmFolder & fileName & "_Source:" & fileName & ".pml"
|
||
set clearFile to dedrmFolder & fileName & "_Source:" & fileName & ".pdb"
|
||
set clearFileNew to dedrmFolder & fileName & "_Source:" & fileName & "_nodrm.pdb"
|
||
set clearFileNewName to fileName & "_nodrm.pdb"
|
||
set sourcePath to POSIX path of file dedrmFolder & fileName & "_Source/"
|
||
set pmlzFilePath to POSIX path of file dedrmFolder & fileName & "_nodrm.pmlz"
|
||
if length of GeteReaderKeystring() is 0 then
|
||
GeteReaderKeys("DeDRM Configure for eReader")
|
||
end if
|
||
set shellresult to "Error: No eReader keys supplied. Can't decrypt."
|
||
repeat with BNKey in bnKeys
|
||
set encryptionName to first item of BNKey
|
||
set encryptionNumber to second item of BNKey
|
||
if length of encryptionName > 0 and length of encryptionNumber > 0 then
|
||
set shellcommand to python & (quoted form of eReaderTool) & " " & (quoted form of encryptedFilePath) & " " & (quoted form of sourcePath) & " " & (quoted form of encryptionName) & " " & (quoted form of encryptionNumber)
|
||
set shellcommand to shellcommand & " > " & quotedtemppath()
|
||
--display dialog "shellcommand: " & shellcommand buttons {"OK"} default button 1 giving up after 10
|
||
writetolog("shellcommand: " & shellcommand)
|
||
set shellresult to "no result"
|
||
cleartemp()
|
||
set DecodingError to false
|
||
set ErrorText to ""
|
||
try
|
||
do shell script shellcommand
|
||
on error ErrorText
|
||
set DecodingError to true
|
||
end try
|
||
set shellresult to readtemp()
|
||
writetolog("shellresult: " & shellresult & " " & ErrorText)
|
||
--display dialog shellresult
|
||
if not DecodingError then
|
||
-- try to run dropbook and move compiled book to same folder as encrypted book
|
||
try
|
||
try
|
||
tell application "Finder" to set DropBook to (application file id "PPDr") as string
|
||
on error
|
||
error "Couldn't find DropBook application"
|
||
end try
|
||
-- now also compile back up into pdb file using DropBook if it's on this system
|
||
tell application DropBook to open file pmlFile
|
||
delay 1 -- probably don't need this, but just in case.
|
||
tell application DropBook to quit -- DropBook will quit only after the compilation has happened
|
||
try
|
||
tell application "Finder"
|
||
set name of file clearFile to clearFileNewName
|
||
move clearFileNew to dedrmFolder
|
||
end tell
|
||
on error errmsg
|
||
error "DropBook failed to compile the source folder into a pdb file."
|
||
end try
|
||
on error errmsg
|
||
set WarningCount to WarningCount + 1
|
||
set WarningList to (WarningList & fileName & fileExtension & " couldn't be compiled back to pdb:
|
||
" & errmsg as text) & "
|
||
"
|
||
end try
|
||
-- try to compress source folder contensts to a pmlz file for easy import into Calibre
|
||
try
|
||
set shellcommand to "cd " & quoted form of sourcePath & "; zip -r " & quoted form of pmlzFilePath & " *"
|
||
--display dialog shellcommand
|
||
writetolog("shellcommand: " & shellcommand)
|
||
set zipshellresult to ""
|
||
set zipshellresult to do shell script shellcommand
|
||
writetolog("shellresult: " & zipshellresult)
|
||
--display dialog zipshellresult
|
||
tell application "Finder"
|
||
-- move source folder to the trash
|
||
move dedrmFolder & fileName & "_Source" to trash
|
||
end tell
|
||
on error errmsg
|
||
set WarningCount to WarningCount + 1
|
||
set WarningList to (WarningList & fileName & fileExtension & "source folder couldn't be compressed to pmlz:
|
||
" & errmsg as text) & "
|
||
|
||
"
|
||
end try
|
||
-- we've done the decrypting so exit the loop.
|
||
exit repeat
|
||
end if
|
||
end if
|
||
end repeat
|
||
try
|
||
if (offset of "incorrect eReader version 10" in shellresult) > 0 then
|
||
set WarningCount to WarningCount + 1
|
||
set WarningList to WarningList & fileName & fileExtension & " is not encrypted.
|
||
"
|
||
else if DecodingError then
|
||
set ErrorCount to ErrorCount + 1
|
||
set ErrorList to (ErrorList & fileName & fileExtension & " couldn't be decoded:
|
||
" & ErrorText as text) & "
|
||
"
|
||
else
|
||
set CompletedCount to CompletedCount + 1
|
||
set CompletedList to CompletedList & fileName & fileExtension & paraend
|
||
end if
|
||
end try
|
||
end unlockpdbfile
|
||
|
||
on unlockepubfile(encryptedFile)
|
||
set encryptedFilePath to POSIX path of file encryptedFile
|
||
tell application "Finder"
|
||
set parent_folder to (container of file encryptedFile) as text
|
||
set fileName to (name of file encryptedFile) as text
|
||
end tell
|
||
set fileExtension to "." & GetFileExtension(fileName)
|
||
set fileName to GetFileNameOnly(fileName)
|
||
|
||
set decoded to false
|
||
-- first we must fix any possible zip problems with the epub
|
||
if outputFolder is "" or not folderexists(outputFolder) then
|
||
set fixedFilePath to POSIX path of file (parent_folder & fileName & "_fixed" & fileExtension)
|
||
else
|
||
set fixedFilePath to POSIX path of file (outputFolder & fileName & "_fixed" & fileExtension)
|
||
end if
|
||
set shellcommand to python & (quoted form of ZipFixTool) & " " & (quoted form of encryptedFilePath) & " " & (quoted form of fixedFilePath)
|
||
set shellcommand to shellcommand & " > " & quotedtemppath()
|
||
writetolog("shellcommand: " & shellcommand)
|
||
cleartemp()
|
||
set ZipErrorText to ""
|
||
set ZipFixError to false
|
||
try
|
||
--display dialog "shellcommand: " default answer shellcommand buttons {"OK"} default button 1 giving up after 10
|
||
do shell script shellcommand
|
||
on error errmsg
|
||
set ZipErrorText to errmsg
|
||
set ZipFixError to true
|
||
end try
|
||
set shellresult to readtemp()
|
||
writetolog("shellresult: " & shellresult & " " & ZipErrorText)
|
||
--display dialog shellresult
|
||
|
||
if ZipFixError then
|
||
set ErrorCount to ErrorCount + 1
|
||
set ErrorList to ((ErrorList & fileName & fileExtension & " had a problem with ZipFix:
|
||
" & ZipErrorText as text) & "
|
||
")
|
||
return
|
||
end if
|
||
|
||
--check it's an ePub file.
|
||
set ePubSig to "NOT_ePub"
|
||
try
|
||
set ePubSig to read POSIX file fixedFilePath from 31 for 28
|
||
end try
|
||
--display dialog ePubSig
|
||
if ePubSig is not "mimetypeapplication/epub+zip" then
|
||
set ErrorCount to ErrorCount + 1
|
||
set ErrorList to ErrorList & encryptedFile & " is not an ePub file.
|
||
"
|
||
tell application "Finder"
|
||
move alias ((POSIX file fixedFilePath) as text) to trash
|
||
end tell
|
||
return
|
||
end if
|
||
|
||
if outputFolder is "" or not folderexists(outputFolder) then
|
||
set unlockedFilePath to POSIX path of file (parent_folder & fileName & "_nodrm" & fileExtension)
|
||
else
|
||
set unlockedFilePath to POSIX path of file (outputFolder & fileName & "_nodrm" & fileExtension)
|
||
end if
|
||
set shellresult to "no keys"
|
||
set ErrorText to ""
|
||
|
||
-- get encryption type
|
||
set TryBandNePub to true
|
||
set TryAdobeePub to true
|
||
set shellcommand to python & (quoted form of ePubTestTool) & " " & (quoted form of fixedFilePath)
|
||
set shellcommand to shellcommand & " > " & quotedtemppath()
|
||
--display dialog "shellcommand: " & shellcommand buttons {"OK"} default button 1 giving up after 10
|
||
writetolog("shellcommand: " & shellcommand)
|
||
cleartemp()
|
||
set TestError to false
|
||
set ErrorText to ""
|
||
try
|
||
do shell script shellcommand
|
||
on error ErrorText
|
||
set TestError to true
|
||
end try
|
||
set shellresult to readtemp()
|
||
writetolog("shellresult: " & shellresult & " " & ErrorText)
|
||
--display dialog shellresult
|
||
if not TestError then
|
||
if (offset of "B&N" in shellresult) > 0 then
|
||
set TryAdobeePub to false
|
||
else if (offset of "Adobe" in shellresult) > 0 then
|
||
set TryBandNePub to false
|
||
else if (offset of "Unencrypted" in shellresult) > 0 then
|
||
set TryAdobeePub to false
|
||
set TryBandNePub to false
|
||
end if
|
||
end if
|
||
|
||
|
||
-- first we'll try the Barnes & Noble keys
|
||
if TryBandNePub then
|
||
set decoded to decodebandnepub(fixedFilePath, unlockedFilePath, bnKeys)
|
||
if not decoded then
|
||
set newKeyList to GetNookKeys()
|
||
set decoded to decodebandnepub(fixedFilePath, unlockedFilePath, newKeyList)
|
||
if decoded then
|
||
set bnKeys to bnKeys & newKeyList
|
||
end if
|
||
end if
|
||
|
||
end if
|
||
|
||
if (not decoded) and TryAdobeePub then
|
||
set decoded to decodeadobeepub(fixedFilePath, unlockedFilePath, AdeptKeyList)
|
||
if not decoded then
|
||
set newKeyList to GetAdeptKeys()
|
||
set decoded to decodeadobeepub(fixedFilePath, unlockedFilePath, newKeyList)
|
||
if decoded then
|
||
set AdeptKeyList to AdeptKeyList & newKeyList
|
||
end if
|
||
end if
|
||
end if
|
||
|
||
if decoded then
|
||
set CompletedCount to CompletedCount + 1
|
||
set CompletedList to CompletedList & fileName & fileExtension & paraend
|
||
else if not TryAdobeePub and not TryBandNePub then
|
||
set WarningCount to WarningCount + 1
|
||
set WarningList to (WarningList & fileName & " doesn't seem to be encrypted.
|
||
")
|
||
else if shellresult is "no keys" then
|
||
set ErrorCount to ErrorCount + 1
|
||
set ErrorList to (ErrorList & fileName & fileExtension & " couldn't be decoded: no keys.
|
||
")
|
||
else
|
||
set ErrorCount to ErrorCount + 1
|
||
set ErrorList to ((ErrorList & fileName & fileExtension & " couldn't be decoded:
|
||
" & ErrorText as text) & "
|
||
")
|
||
end if
|
||
|
||
tell application "Finder"
|
||
move alias ((POSIX file fixedFilePath) as text) to trash
|
||
end tell
|
||
end unlockepubfile
|
||
|
||
on decodebandnepub(fixedFilePath, unlockedFilePath, keyList)
|
||
set decoded to false
|
||
repeat with BNKey in keyList
|
||
set keyfilepath to third item of BNKey
|
||
if length of keyfilepath > 0 then
|
||
set shellcommand to python & (quoted form of BNePubTool) & " " & (quoted form of keyfilepath) & " " & (quoted form of fixedFilePath) & " " & (quoted form of unlockedFilePath)
|
||
set shellcommand to shellcommand & " > " & quotedtemppath()
|
||
--display dialog "shellcommand: " & shellcommand buttons {"OK"} default button 1 giving up after 10
|
||
writetolog("shellcommand: " & shellcommand)
|
||
cleartemp()
|
||
set DecodingError to false
|
||
set ErrorText to ""
|
||
try
|
||
do shell script shellcommand
|
||
on error ErrorText
|
||
set DecodingError to true
|
||
end try
|
||
set shellresult to readtemp()
|
||
writetolog("shellresult: " & shellresult & " " & ErrorText)
|
||
--display dialog shellresult
|
||
if not DecodingError then
|
||
set decoded to true
|
||
exit repeat
|
||
end if
|
||
end if
|
||
end repeat
|
||
return decoded
|
||
end decodebandnepub
|
||
|
||
on decodeadobeepub(fixedFilePath, unlockedFilePath, keyList)
|
||
set decoded to false
|
||
repeat with AdeptKey in keyList
|
||
set shellcommand to python & (quoted form of AdobeePubTool) & " " & (quoted form of AdeptKey) & " " & (quoted form of fixedFilePath) & " " & (quoted form of unlockedFilePath)
|
||
set shellcommand to shellcommand & " > " & quotedtemppath()
|
||
--display dialog "shellcommand: " default answer shellcommand buttons {"OK"} default button 1 giving up after 10
|
||
writetolog("shellcommand: " & shellcommand)
|
||
cleartemp()
|
||
set DecodingError to false
|
||
set ErrorText to ""
|
||
try
|
||
do shell script shellcommand
|
||
on error ErrorText
|
||
set DecodingError to true
|
||
end try
|
||
set shellresult to readtemp() as text
|
||
writetolog("shellresult: " & shellresult & " " & ErrorText)
|
||
--display dialog shellresult
|
||
if not DecodingError then
|
||
set decoded to true
|
||
exit repeat
|
||
end if
|
||
end repeat
|
||
return decoded
|
||
end decodeadobeepub
|
||
|
||
|
||
on unlockpdffile(encryptedFile)
|
||
--check it's an ePub file.
|
||
set PDFSig to "NOT_PDF"
|
||
try
|
||
set PDFSig to read file encryptedFile from 1 for 4
|
||
end try
|
||
--display dialog PDFSig
|
||
if PDFSig is not "%PDF" then
|
||
set ErrorCount to ErrorCount + 1
|
||
set ErrorList to ErrorList & encryptedFile & " is not a PDF file.
|
||
"
|
||
return
|
||
end if
|
||
set encryptedFilePath to POSIX path of file encryptedFile
|
||
tell application "Finder"
|
||
set parent_folder to (container of file encryptedFile) as text
|
||
set fileName to (name of file encryptedFile) as text
|
||
end tell
|
||
set fileExtension to "." & GetFileExtension(fileName)
|
||
set fileName to GetFileNameOnly(fileName)
|
||
|
||
set decoded to "NO"
|
||
-- first we must check we have a PDF script
|
||
if not fileexists(AdobePDFTool) then
|
||
set ErrorCount to ErrorCount + 1
|
||
set ErrorList to ErrorList & encryptedFile & " is a PDF file and no ineptpdf script found.
|
||
"
|
||
return
|
||
end if
|
||
|
||
if outputFolder is "" or not folderexists(outputFolder) then
|
||
set unlockedFilePath to POSIX path of file (parent_folder & fileName & "_nodrm" & fileExtension)
|
||
else
|
||
set unlockedFilePath to POSIX path of file (outputFolder & fileName & "_nodrm" & fileExtension)
|
||
end if
|
||
set decoded to false
|
||
set shellresult to "no keys"
|
||
set ErrorText to ""
|
||
|
||
repeat with AdeptKey in AdeptKeyList
|
||
set shellcommand to python & (quoted form of AdobePDFTool) & " " & (quoted form of AdeptKey) & " " & (quoted form of encryptedFilePath) & " " & (quoted form of unlockedFilePath)
|
||
set shellcommand to shellcommand & " > " & quotedtemppath()
|
||
--display dialog "shellcommand: " default answer shellcommand buttons {"OK"} default button 1 giving up after 10
|
||
writetolog("shellcommand: " & shellcommand)
|
||
cleartemp()
|
||
set DecodingError to false
|
||
set ErrorText to ""
|
||
try
|
||
do shell script shellcommand
|
||
on error ErrorText
|
||
set DecodingError to true
|
||
end try
|
||
set shellresult to readtemp()
|
||
writetolog("shellresult: " & shellresult & " " & ErrorText)
|
||
--display dialog shellresult
|
||
if not DecodingError then
|
||
set decoded to true
|
||
exit repeat
|
||
end if
|
||
end repeat
|
||
|
||
if decoded then
|
||
set CompletedCount to CompletedCount + 1
|
||
set CompletedList to CompletedList & fileName & fileExtension & paraend
|
||
else if shellresult is "no keys" then
|
||
set ErrorCount to ErrorCount + 1
|
||
set ErrorList to (ErrorList & fileName & fileExtension & " couldn't be decoded: no keys.
|
||
")
|
||
else
|
||
set ErrorCount to ErrorCount + 1
|
||
set ErrorList to ((ErrorList & fileName & fileExtension & " couldn't be decoded:
|
||
" & ErrorText as text) & "
|
||
")
|
||
end if
|
||
end unlockpdffile
|
||
|
||
on handlefile(droppedFile)
|
||
tell application "Finder"
|
||
set fileName to (name of file droppedFile) as text
|
||
end tell
|
||
writetolog("Processing file: " & fileName)
|
||
set fileExtension to GetFileExtension(fileName)
|
||
set fileName to GetFileNameOnly(fileName)
|
||
if fileExtension is "prc" or fileExtension is "mobi" or fileExtension is "pobi" or fileExtension is "azw" or fileExtension is "azw1" or fileExtension is "tpz" or fileExtension is "azw3" or fileExtension is "azw4" then
|
||
set completedebooks to completedebooks + 1
|
||
IncProgress(fileName, completedebooks)
|
||
unlockmobifile(droppedFile as text)
|
||
else if fileExtension is "pdb" then
|
||
set completedebooks to completedebooks + 1
|
||
IncProgress(fileName, completedebooks)
|
||
unlockpdbfile(droppedFile as text)
|
||
else if fileExtension is "epub" then
|
||
set completedebooks to completedebooks + 1
|
||
IncProgress(fileName, completedebooks)
|
||
unlockepubfile(droppedFile as text)
|
||
else if fileExtension is "pdf" then
|
||
set completedebooks to completedebooks + 1
|
||
IncProgress(fileName, completedebooks)
|
||
unlockpdffile(droppedFile as text)
|
||
end if
|
||
end handlefile
|
||
|
||
on handlefolder(droppedFolder)
|
||
tell application "Finder" to set fileList to (every file in folder droppedFolder)
|
||
tell application "Finder" to set folderList to (every folder in folder droppedFolder)
|
||
repeat with this_item in fileList
|
||
if not ProgressActive() then
|
||
exit repeat
|
||
end if
|
||
handlefile(this_item as text)
|
||
end repeat
|
||
repeat with this_item in folderList
|
||
if not ProgressActive() then
|
||
exit repeat
|
||
end if
|
||
handlefolder(this_item as text)
|
||
end repeat
|
||
end handlefolder
|
||
|
||
on countfile(droppedFile)
|
||
tell application "Finder"
|
||
set fileName to (name of file droppedFile) as text
|
||
end tell
|
||
set fileExtension to GetFileExtension(fileName)
|
||
set fileName to GetFileNameOnly(fileName)
|
||
--display dialog "fileName: " & fileName & "
|
||
--extension: " & fileExtension
|
||
if fileExtension is in handledExtensions then
|
||
set totalebooks to totalebooks + 1
|
||
end if
|
||
end countfile
|
||
|
||
on GetSerialstring()
|
||
set Serialstring to ""
|
||
repeat with Serial in KindleSerialList
|
||
if Serialstring is "" then
|
||
set Serialstring to Serial
|
||
else
|
||
set Serialstring to Serialstring & "," & Serial
|
||
end if
|
||
end repeat
|
||
return Serialstring
|
||
end GetSerialstring
|
||
|
||
on GetPIDstring()
|
||
set PIDstring to ""
|
||
repeat with PID in PIDs
|
||
if PIDstring is "" then
|
||
set PIDstring to PID
|
||
else
|
||
set PIDstring to PIDstring & "," & PID
|
||
end if
|
||
end repeat
|
||
return PIDstring
|
||
end GetPIDstring
|
||
|
||
on GetUDIDstring()
|
||
set UDIDstring to ""
|
||
repeat with UDIDPair in UDIDs
|
||
if UDIDstring is "" then
|
||
set UDIDstring to first item of UDIDPair
|
||
else
|
||
set UDIDstring to UDIDstring & "," & first item of UDIDPair
|
||
end if
|
||
end repeat
|
||
return UDIDstring
|
||
end GetUDIDstring
|
||
|
||
on GetUDIDPIDs()
|
||
set UDIDPIDs to ""
|
||
repeat with UDIDPair in UDIDs
|
||
if UDIDPIDs is "" then
|
||
set UDIDPIDs to second item of UDIDPair
|
||
else
|
||
set UDIDPIDs to UDIDPIDs & "," & second item of UDIDPair
|
||
end if
|
||
end repeat
|
||
return UDIDPIDs
|
||
end GetUDIDPIDs
|
||
|
||
on GetAdeptstring()
|
||
set Adeptstring to ""
|
||
repeat with AdeptKeyFile in AdeptKeyList
|
||
set AppleTypeFile to POSIX file (AdeptKeyFile as text)
|
||
tell application "Finder"
|
||
set fileName to name of file (AppleTypeFile as text)
|
||
end tell
|
||
|
||
if Adeptstring is "" then
|
||
set Adeptstring to fileName
|
||
else
|
||
set Adeptstring to Adeptstring & "
|
||
" & fileName
|
||
end if
|
||
end repeat
|
||
return Adeptstring
|
||
end GetAdeptstring
|
||
|
||
on GetAndroidstring()
|
||
set Androidstring to ""
|
||
repeat with AndroidKeyFile in AndroidKeyList
|
||
set AppleTypeFile to POSIX file (AndroidKeyFile as text)
|
||
tell application "Finder"
|
||
set fileName to name of file (AppleTypeFile as text)
|
||
end tell
|
||
|
||
if Androidstring is "" then
|
||
set Androidstring to fileName
|
||
else
|
||
set Androidstring to Androidstring & "
|
||
" & fileName
|
||
end if
|
||
end repeat
|
||
return Androidstring
|
||
end GetAndroidstring
|
||
|
||
on GetKindlestring()
|
||
set Kindlestring to ""
|
||
repeat with KindleKeyFile in KindleKeyList
|
||
set AppleTypeFile to POSIX file (KindleKeyFile as text)
|
||
tell application "Finder"
|
||
set fileName to name of file (AppleTypeFile as text)
|
||
end tell
|
||
|
||
if Kindlestring is "" then
|
||
set Kindlestring to fileName
|
||
else
|
||
set Kindlestring to Kindlestring & "
|
||
" & fileName
|
||
end if
|
||
end repeat
|
||
return Kindlestring
|
||
end GetKindlestring
|
||
|
||
on GeteReaderKeystring()
|
||
set Keystring to ""
|
||
repeat with key in bnKeys
|
||
if length of first item of key > 0 and length of second item of key > 0 then
|
||
if Keystring is "" then
|
||
set Keystring to first item of key & ":" & second item of key
|
||
else
|
||
set Keystring to Keystring & "
|
||
" & first item of key & ":" & second item of key
|
||
end if
|
||
end if
|
||
end repeat
|
||
return Keystring
|
||
end GeteReaderKeystring
|
||
|
||
on GetBNKeystring()
|
||
set BNKeystring to ""
|
||
repeat with BNKey in bnKeys
|
||
if (length of BNKey > 2) and ((length of (third item of BNKey)) > 0) then
|
||
if BNKeystring is "" then
|
||
set BNKeystring to first item of BNKey
|
||
else
|
||
set BNKeystring to BNKeystring & "
|
||
" & first item of BNKey
|
||
end if
|
||
end if
|
||
end repeat
|
||
return BNKeystring
|
||
end GetBNKeystring
|
||
|
||
on DeleteeReaderKeys()
|
||
set newKeys to {}
|
||
repeat with BNKey in bnKeys
|
||
if length of third item of BNKey > 0 then
|
||
|
||
set newKeys to newKeys & {{first item of BNKey, "", third item of BNKey}}
|
||
end if
|
||
end repeat
|
||
set bnKeys to newKeys
|
||
end DeleteeReaderKeys
|
||
|
||
on DeleteBNKeys()
|
||
set newKeys to {}
|
||
repeat with BNKey in bnKeys
|
||
if length of second item of BNKey > 0 then
|
||
|
||
set newKeys to newKeys & {{first item of BNKey, second item of BNKey, ""}}
|
||
end if
|
||
end repeat
|
||
set bnKeys to newKeys
|
||
end DeleteBNKeys
|
||
|
||
|
||
on GetUDIDs(DialogTitle)
|
||
set UDID to ""
|
||
repeat
|
||
set UDIDstring to GetUDIDstring()
|
||
if UDIDstring is "" then
|
||
set DialogPrompt to "Enter any iPod/iPhone/iPad UDIDs (40 characters) one at a time. Note: This only works for older versions of Kindle for iOS."
|
||
set FinishedButton to "Close"
|
||
else
|
||
set DialogPrompt to "Current UDIDs: " & UDIDstring & ".
|
||
|
||
Enter any additional iPod/iPhone/iPad UDIDs (40 characters) one at a time:"
|
||
set FinishedButton to "Close"
|
||
end if
|
||
set dialogresult to (display dialog DialogPrompt default answer UDID buttons {"Delete All", "Add", FinishedButton} with title DialogTitle default button 2)
|
||
if button returned of dialogresult is "Add" then
|
||
set UDID to text returned of dialogresult
|
||
set UDIDlength to length of UDID
|
||
if UDIDlength is 40 then
|
||
set shellresult to ""
|
||
set scriptError to ""
|
||
set shellcommand to python & (quoted form of KindlePIDTool) & " " & (quoted form of UDID)
|
||
writetolog("shellcommand: " & shellcommand)
|
||
try
|
||
set shellresult to do shell script shellcommand
|
||
on error errmsg
|
||
set shellresult to ""
|
||
set scriptError to "KindlePID Script failed:" & " " & errmsg
|
||
end try
|
||
writetolog("shellresult: " & scriptError & " " & shellresult)
|
||
--display dialog shellresult
|
||
|
||
if shellresult is not "" then
|
||
set PID to (text -10 thru -1 of shellresult)
|
||
if UDIDs contains {{UDID, PID}} then
|
||
display dialog "UDID " & UDID & " is already in your list of UDIDs." buttons {"OK"} default button 1 with title "DeDRM" with icon caution
|
||
else
|
||
display dialog "The equivalent UDID for UDID " & UDID & " is " & PID & ". Adding to list." buttons {"OK"} default button 1 with title "DeDRM" with icon note
|
||
set UDIDs to UDIDs & {{UDID, PID}}
|
||
set UDID to ""
|
||
end if
|
||
else
|
||
writetolog(scriptError)
|
||
display dialog "Error generating PID from this UDID, error message was: " & scriptError buttons {"OK"} default button 1 with title "DeDRM" with icon caution
|
||
end if
|
||
else
|
||
display dialog "UDIDs must be 40 characters." buttons {"OK"} default button 1 with title "DeDRM" with icon caution
|
||
end if
|
||
else if button returned of dialogresult is "Delete All" then
|
||
if UDIDstring is not "" then
|
||
try
|
||
set dialogresult to (display dialog "Are you sure you want to delete all stored UDIDs?" buttons {"Cancel", "Delete"} default button 1 with title "DeDRM")
|
||
end try
|
||
if button returned of dialogresult is "Delete" then
|
||
set UDIDs to {}
|
||
end if
|
||
end if
|
||
else
|
||
set UDID to text returned of dialogresult
|
||
if UDID is not "" then
|
||
try
|
||
set dialogresult to (display dialog "You entered some text, but didn't click Add. Are you sure you want to more on to the next dialog?" buttons {"Whoops", "Yes, Move on"} default button 1 with title "DeDRM")
|
||
end try
|
||
if button returned of dialogresult is "Yes, Move on" then
|
||
exit repeat
|
||
end if
|
||
else
|
||
exit repeat
|
||
end if
|
||
end if
|
||
end repeat
|
||
end GetUDIDs
|
||
|
||
on GetPIDs(DialogTitle)
|
||
set PID to ""
|
||
repeat
|
||
set PIDstring to GetPIDstring()
|
||
if PIDstring is "" then
|
||
set DialogPrompt to "Enter any Mobipocket PIDs one at a time:"
|
||
set FinishedButton to "Close"
|
||
else
|
||
set DialogPrompt to "Current PIDs: " & PIDstring & ".
|
||
|
||
Enter any additional Mobipocket PIDs one at a time:"
|
||
set FinishedButton to "Close"
|
||
end if
|
||
set dialogresult to (display dialog DialogPrompt default answer PID buttons {"Delete All", "Add", FinishedButton} with title DialogTitle default button 2)
|
||
if button returned of dialogresult is "Add" then
|
||
set PID to text returned of dialogresult
|
||
set PIDlength to length of PID
|
||
if PIDlength is 8 or PIDlength is 10 then
|
||
if PIDs contains PID then
|
||
display dialog "PID" & PID & " is already in your list of PIDs." buttons {"OK"} default button 1 with title "DeDRM" with icon caution
|
||
else
|
||
set PIDs to PIDs & PID
|
||
set PID to ""
|
||
end if
|
||
else
|
||
display dialog "PIDs must be 8 or 10 characters long, and UDIDs must be 40 characters." buttons {"OK"} default button 1 with title "DeDRM" with icon caution
|
||
end if
|
||
else if button returned of dialogresult is "Delete All" then
|
||
if PIDstring is not "" then
|
||
try
|
||
set dialogresult to (display dialog "Are you sure you want to delete all stored PIDs?" buttons {"Cancel", "Delete"} default button 1 with title "DeDRM")
|
||
end try
|
||
if button returned of dialogresult is "Delete" then
|
||
set PIDs to {}
|
||
end if
|
||
end if
|
||
else
|
||
set PID to text returned of dialogresult
|
||
if PID is not "" then
|
||
try
|
||
set dialogresult to (display dialog "You entered some text, but didn't click Add. Are you sure you want to more on to the next dialog?" buttons {"Whoops", "Yes, Move on"} default button 1 with title "DeDRM")
|
||
end try
|
||
if button returned of dialogresult is "Yes, Move on" then
|
||
exit repeat
|
||
end if
|
||
else
|
||
exit repeat
|
||
end if
|
||
end if
|
||
end repeat
|
||
end GetPIDs
|
||
|
||
on GetSerials(DialogTitle)
|
||
set Serial to ""
|
||
repeat
|
||
set Serialstring to GetSerialstring()
|
||
if Serialstring is "" then
|
||
set DialogPrompt to "Enter any Kindle (not Kindle Fire) Serial Numbers one at a time:"
|
||
set FinishedButton to "Close"
|
||
else
|
||
set DialogPrompt to "Current Kindle Serial Numbers: " & Serialstring & ".
|
||
|
||
Enter any additional Kindle (not Kindle Fire) Serial Numbers one at a time:"
|
||
set FinishedButton to "Close"
|
||
end if
|
||
set dialogresult to (display dialog DialogPrompt default answer Serial buttons {"Delete All", "Add", FinishedButton} with title DialogTitle default button 2)
|
||
if button returned of dialogresult is "Add" then
|
||
set Serial to text returned of dialogresult
|
||
set Seriallength to length of Serial
|
||
if Seriallength is 16 then
|
||
set KindleSerialList to KindleSerialList & Serial
|
||
set Serial to ""
|
||
else
|
||
display dialog "Kindle Serial Numbers are 16 characters long." buttons {"OK"} default button 1 with title "DeDRM" with icon caution
|
||
end if
|
||
else if button returned of dialogresult is "Delete All" then
|
||
if Serialstring is not "" then
|
||
try
|
||
set dialogresult to (display dialog "Are you sure you want to delete all stored Kindle Serial Numbers?" buttons {"Cancel", "Delete"} default button 1 with title "DeDRM")
|
||
end try
|
||
if button returned of dialogresult is "Delete" then
|
||
set KindleSerialList to {}
|
||
end if
|
||
end if
|
||
else
|
||
set Serial to text returned of dialogresult
|
||
if Serial is not "" then
|
||
try
|
||
set dialogresult to (display dialog "You entered some text, but didn't click Add. Are you sure you want to more on to the next dialog?" buttons {"Whoops", "Yes, Move on"} default button 1 with title "DeDRM")
|
||
end try
|
||
if button returned of dialogresult is "Yes, Move on" then
|
||
exit repeat
|
||
end if
|
||
else
|
||
exit repeat
|
||
end if
|
||
end if
|
||
end repeat
|
||
end GetSerials
|
||
|
||
on GetOutputFolder(DialogTitle)
|
||
set newFolder to ""
|
||
try
|
||
tell me to activate
|
||
repeat
|
||
|
||
if folderexists(outputFolder) then
|
||
set DialogPrompt to "The deDRMed ebooks will be saved to the following folder:
|
||
" & (outputFolder) & "
|
||
|
||
"
|
||
else
|
||
set outputFolder to ""
|
||
set DialogPrompt to "The deDRMed ebooks will be saved in the same folder as the original DRMed ebooks.
|
||
|
||
"
|
||
end if
|
||
set DialogPrompt to DialogPrompt & "To keep this choice, click 'Close', otherwise select the option you want by clicking on one of the other buttons."
|
||
set dialogresult to (display dialog DialogPrompt buttons {"Use Same Folder as DRMed Ebooks", "Choose Output Folder…", "Close"} with title DialogTitle default button 3)
|
||
if button returned of dialogresult is "Choose Output Folder…" then
|
||
try
|
||
if outputFolder is "" then
|
||
set outputFolder to ((choose folder with prompt "DRM Application
|
||
Please choose the Output Folder for DeDRMed ebooks.") as text)
|
||
else
|
||
set outputFolder to ((choose folder with prompt "DRM Application
|
||
Please choose the Output Folder for DeDRMed ebooks." default location alias outputFolder) as text)
|
||
end if
|
||
end try
|
||
else if button returned of dialogresult is "Use Same Folder as DRMed Ebooks" then
|
||
set outputFolder to ""
|
||
else
|
||
exit repeat
|
||
end if
|
||
--on error errormessage
|
||
-- display dialog errormessage
|
||
end repeat
|
||
end try
|
||
WritePrefs()
|
||
end GetOutputFolder
|
||
|
||
on GeteReaderKeys(DialogTitle)
|
||
set keyText to ""
|
||
repeat
|
||
set Keystring to GeteReaderKeystring()
|
||
if Keystring is "" then
|
||
set DialogPrompt to "Please enter any "
|
||
set FinishedButton to "Close"
|
||
else
|
||
set DialogPrompt to "eReader keys:
|
||
" & Keystring & "
|
||
|
||
|
||
Please enter any additional "
|
||
set FinishedButton to "Close"
|
||
end if
|
||
set DialogPrompt to DialogPrompt & "eReader Name,Number key pairs one at a time. The name is usually your name as on your credit card, but might be your user name. Only the last 8 digits of the Number are needed. If you enter more digits, only the last eight will be stored or displayed. Please separate the name and number with a colon (:) and click \"Add\"."
|
||
set dialogresult to (display dialog DialogPrompt default answer keyText with title DialogTitle buttons {"Delete All", "Add", FinishedButton} default button 2)
|
||
if button returned of dialogresult is "Add" then
|
||
set keyText to text returned of dialogresult
|
||
if not (keyText contains ":") then
|
||
display dialog "Name and Number must be separated by a colon (:)." buttons {"OK"} default button 1 with title "DeDRM" with icon caution
|
||
else
|
||
set oldTIDs to AppleScript's text item delimiters
|
||
set AppleScript's text item delimiters to ":"
|
||
set keyNumber to the last text item of keyText
|
||
set keyName to (text items 1 through -2 of keyText) as string
|
||
set AppleScript's text item delimiters to oldTIDs
|
||
|
||
if ((length of keyNumber) = 16 or (length of keyNumber) = 15 or (length of keyNumber) = 8) and (length of keyName) > 0 then
|
||
set bnKeys to bnKeys & {{keyName, (text -8 thru -1 of keyNumber), ""}}
|
||
set keyText to ""
|
||
else
|
||
display dialog "Key numbers must be 8 or 15 or 16 characters long (no spaces) and the key name must not be absent." buttons {"OK"} default button 1 with title "DeDRM" with icon caution
|
||
end if
|
||
end if
|
||
else if button returned of dialogresult is "Delete All" then
|
||
if Keystring is not "" then
|
||
try
|
||
set dialogresult to (display dialog "Are you sure you want to delete all stored Name:Number key pairs?" buttons {"Cancel", "Delete"} default button 1 with title "DeDRM")
|
||
end try
|
||
if button returned of dialogresult is "Delete" then
|
||
DeleteeReaderKeys()
|
||
GetNookKey()
|
||
end if
|
||
end if
|
||
set keyText to ""
|
||
else
|
||
set keyText to text returned of dialogresult
|
||
if keyText is not "" then
|
||
try
|
||
set dialogresult to (display dialog "You entered some text, but didn't click Add. Are you sure you want to more on to the next dialog?" buttons {"Whoops", "Yes, Move on"} default button 1 with title "DeDRM")
|
||
end try
|
||
if button returned of dialogresult is "Yes, Move on" then
|
||
exit repeat
|
||
end if
|
||
else
|
||
exit repeat
|
||
end if
|
||
end if
|
||
end repeat
|
||
end GeteReaderKeys
|
||
|
||
on GetBNKeys(DialogTitle)
|
||
set bnKeyText to ""
|
||
repeat
|
||
set BNKeystring to GetBNKeystring()
|
||
if BNKeystring is "" then
|
||
set DialogPrompt to "Please enter any "
|
||
set FinishedButton to "Close"
|
||
else
|
||
set DialogPrompt to "Current B&N/Nook keys:
|
||
" & BNKeystring & "
|
||
|
||
|
||
Please enter any additional "
|
||
set FinishedButton to "Close"
|
||
end if
|
||
set DialogPrompt to DialogPrompt & "Barnes & Noble/Nook account email addresses and passwords one at a time. Please separate the address and password with a colon (:)and click \"Add\". Note that your account password will only be used to retrieve the key and will not be stored.
|
||
|
||
*** Retrieving the account key may take a couple of minutes, please be patient. ***
|
||
|
||
Or to add a an already generated .b64 file, just click \"Add\" with nothing in the text field."
|
||
set dialogresult to (display dialog DialogPrompt default answer bnKeyText with title DialogTitle buttons {"Forget All", "Add", FinishedButton} default button 2)
|
||
if button returned of dialogresult is "Add" then
|
||
set bnKeyText to text returned of dialogresult
|
||
if bnKeyText is "" then
|
||
try
|
||
set newFile to (choose file with prompt "Please select a Barnes & Noble (.b64) key file") as text
|
||
-- copy to prefs
|
||
AddbnKey(newFile)
|
||
on error message
|
||
if message does not contain "cancel" then
|
||
display dialog message
|
||
end if
|
||
end try
|
||
else if not (bnKeyText contains ":") then
|
||
display dialog "Email address and password must be separated by a colon (:)." buttons {"OK"} default button 1 with title "DeDRM" with icon caution
|
||
else
|
||
set oldTIDs to AppleScript's text item delimiters
|
||
set AppleScript's text item delimiters to ":"
|
||
set keyEmail to the first text item of bnKeyText
|
||
set keyPassword to (text items 2 through -1 of bnKeyText) as string
|
||
set AppleScript's text item delimiters to oldTIDs
|
||
|
||
if (keyEmail contains "@") and (length of keyPassword) > 0 then
|
||
-- get the B&N key from this pair
|
||
set shellresult to ""
|
||
set scriptError to ""
|
||
set success to true
|
||
set userPrefsPath to path to preferences from user domain as string
|
||
set preferencesFolderPath to userPrefsPath & prefsFolderName & ":"
|
||
if not folderexists(preferencesFolderPath) then
|
||
tell application "Finder"
|
||
set preferencesFolder to make new folder at userPrefsPath with properties {name:prefsFolderName}
|
||
end tell
|
||
end if
|
||
set keyfileName to GetUniqueName(preferencesFolderPath, keyEmail & ".b64")
|
||
set keyfilepath to POSIX path of (preferencesFolderPath & keyfileName)
|
||
set shellcommand to python & (quoted form of BNKeyFetchTool) & " " & (quoted form of keyEmail) & " " & (quoted form of keyPassword) & " " & quoted form of keyfilepath
|
||
set shellcommand to shellcommand & " > " & quotedtemppath()
|
||
|
||
writetolog("shellcommand: " & shellcommand)
|
||
cleartemp()
|
||
try
|
||
do shell script shellcommand
|
||
on error scriptError
|
||
set success to false
|
||
end try
|
||
set shellresult to readtemp()
|
||
writetolog("shellresult: " & scriptError & " " & shellresult)
|
||
--display dialog shellresult
|
||
if success then
|
||
set bnKeys to bnKeys & {{keyEmail, "", keyfilepath}}
|
||
set bnKeyText to ""
|
||
else
|
||
display dialog "Error generating key from this info, error message was: " & scriptError buttons {"OK"} default button 1 with title "DeDRM" with icon caution
|
||
end if
|
||
else
|
||
display dialog "Key numbers must be 8 or 15 or 16 characters long (no spaces) and the key name must not be absent." buttons {"OK"} default button 1 with title "DeDRM" with icon caution
|
||
end if
|
||
end if
|
||
else if button returned of dialogresult is "Forget All" then
|
||
if BNKeystring is not "" then
|
||
try
|
||
set dialogresult to (display dialog "Are you sure you want to forget all stored Barnes & Noble/Nook keys?" buttons {"Cancel", "Forget"} default button 1 with title "DeDRM")
|
||
end try
|
||
if button returned of dialogresult is "Forget" then
|
||
DeleteBNKeys()
|
||
end if
|
||
end if
|
||
set bnKeyText to ""
|
||
else
|
||
set bnKeyText to text returned of dialogresult
|
||
if bnKeyText is not "" then
|
||
try
|
||
set dialogresult to (display dialog "You entered some text, but didn't click Add. Are you sure you want to more on to the next dialog?" buttons {"Whoops", "Yes, Move on"} default button 1 with title "DeDRM")
|
||
end try
|
||
if button returned of dialogresult is "Yes, Move on" then
|
||
exit repeat
|
||
end if
|
||
else
|
||
exit repeat
|
||
end if
|
||
end if
|
||
end repeat
|
||
end GetBNKeys
|
||
|
||
on GetAdeptKeyFiles(DialogTitle)
|
||
repeat
|
||
set Adeptstring to GetAdeptstring()
|
||
if Adeptstring is "" then
|
||
set DialogPrompt to "To add Adobe Digital Editions (Adept) key files, click the Add… button. "
|
||
set dialogresult to (display dialog DialogPrompt buttons {"Add…", "Close"} with title DialogTitle default button 1)
|
||
else
|
||
set DialogPrompt to "Current Adobe Digital Editions (Adept) key files:
|
||
" & Adeptstring & "
|
||
|
||
To add extra key files (.der), click the Add… button."
|
||
set dialogresult to (display dialog DialogPrompt buttons {"Forget All", "Add…", "Close"} with title DialogTitle default button 2)
|
||
end if
|
||
if button returned of dialogresult is "Add…" then
|
||
try
|
||
set newFile to (choose file with prompt "Please select an Adobe Digital Editions (.der) key file") as text
|
||
-- copy to prefs
|
||
AddAdeptKey(newFile)
|
||
on error message
|
||
if message does not contain "cancel" then
|
||
display dialog message
|
||
end if
|
||
end try
|
||
|
||
else if button returned of dialogresult is "Forget All" then
|
||
try
|
||
set dialogresult to (display dialog "Are you sure you want to forget all extra Adobe Digital Editions Adept key files?" buttons {"Cancel", "Forget"} default button 1 with title "DeDRM")
|
||
end try
|
||
if button returned of dialogresult is "Forget" then
|
||
set AdeptKeyList to {}
|
||
end if
|
||
else
|
||
exit repeat
|
||
end if
|
||
end repeat
|
||
end GetAdeptKeyFiles
|
||
|
||
on GetKindleKeyFiles(DialogTitle)
|
||
repeat
|
||
set Kindlestring to GetKindlestring()
|
||
if Kindlestring is "" then
|
||
set DialogPrompt to "To add Kindle for Mac key files (.k4i), click the Add… button. "
|
||
set FinishedButton to "Close"
|
||
else
|
||
set DialogPrompt to "Current Kindle for Mac key files:
|
||
" & Kindlestring & "
|
||
|
||
To add extra key files (.k4i), click the Add… button."
|
||
set FinishedButton to "Close"
|
||
end if
|
||
set dialogresult to (display dialog DialogPrompt buttons {"Forget All", "Add…", FinishedButton} with title DialogTitle default button 2)
|
||
if button returned of dialogresult is "Add…" then
|
||
try
|
||
set newFile to (choose file with prompt "Please select a Kindle for Mac/PC (.k4i) key file") as text
|
||
-- copy to prefs
|
||
AddKindleKey(newFile)
|
||
on error message
|
||
if message does not contain "cancel" then
|
||
display dialog message
|
||
end if
|
||
end try
|
||
|
||
else if button returned of dialogresult is "Forget All" then
|
||
if Kindlestring is not "" then
|
||
try
|
||
set dialogresult to (display dialog "Are you sure you want to forget all extra Kindle for Mac key files?" buttons {"Cancel", "Forget"} default button 1 with title "DeDRM")
|
||
end try
|
||
if button returned of dialogresult is "Forget" then
|
||
set KindleKeyList to {}
|
||
end if
|
||
end if
|
||
else
|
||
exit repeat
|
||
end if
|
||
end repeat
|
||
end GetKindleKeyFiles
|
||
|
||
on GetAndroidKeyFiles(DialogTitle)
|
||
repeat
|
||
set Androidstring to GetAndroidstring()
|
||
if Androidstring is "" then
|
||
set DialogPrompt to "To add Kindle for Android backup files (.ab), click the Add… button. "
|
||
set FinishedButton to "Close"
|
||
else
|
||
set DialogPrompt to "Current Kindle for Android backup files:
|
||
" & Androidstring & "
|
||
|
||
To add extra backup files (.ab), click the Add… button."
|
||
set FinishedButton to "Close"
|
||
end if
|
||
set dialogresult to (display dialog DialogPrompt buttons {"Forget All", "Add…", FinishedButton} with title DialogTitle default button 2)
|
||
if button returned of dialogresult is "Add…" then
|
||
try
|
||
set newFile to (choose file with prompt "Please select a Kindle for Android backup (.ab) file") as text
|
||
-- copy to prefs
|
||
AddAndroidKey(newFile)
|
||
on error message
|
||
if message does not contain "cancel" then
|
||
display dialog message
|
||
end if
|
||
end try
|
||
|
||
else if button returned of dialogresult is "Forget All" then
|
||
if Androidstring is not "" then
|
||
try
|
||
set dialogresult to (display dialog "Are you sure you want to forget all Kindle for Android backup files?" buttons {"Cancel", "Forget"} default button 1 with title "DeDRM")
|
||
end try
|
||
if button returned of dialogresult is "Forget" then
|
||
set AndroidKeyList to {}
|
||
end if
|
||
end if
|
||
else
|
||
exit repeat
|
||
end if
|
||
end repeat
|
||
end GetAndroidKeyFiles
|
||
|
||
|
||
on GetAdeptKeys()
|
||
set newKeyList to {}
|
||
set userPrefsPath to path to preferences from user domain as string
|
||
set preferencesFolderPath to userPrefsPath & prefsFolderName & ":"
|
||
if not folderexists(preferencesFolderPath) then
|
||
tell application "Finder"
|
||
set preferencesFolder to make new folder at userPrefsPath with properties {name:prefsFolderName}
|
||
end tell
|
||
end if
|
||
set newKeysFolderPath to preferencesFolderPath & newKeysFolderName & ":"
|
||
if not folderexists(newKeysFolderPath) then
|
||
tell application "Finder"
|
||
set newKeysFolder to make new folder at preferencesFolderPath with properties {name:newKeysFolderName}
|
||
end tell
|
||
end if
|
||
set scriptError to ""
|
||
set shellresult to ""
|
||
set success to true
|
||
set shellcommand to python & (quoted form of AdobeKeyGenTool) & " " & quoted form of (POSIX path of (newKeysFolderPath))
|
||
set shellcommand to shellcommand & " > " & quotedtemppath()
|
||
writetolog("shellcommand: " & shellcommand)
|
||
cleartemp()
|
||
try
|
||
do shell script shellcommand
|
||
on error scriptError
|
||
set success to false
|
||
end try
|
||
set shellresult to readtemp()
|
||
writetolog("shellresult: " & shellresult & " " & scriptError)
|
||
--display dialog shellresult
|
||
if success then
|
||
--get all the files from newKeysFolder and add those that aren't duplicates
|
||
tell application "Finder" to set fileList to (every file in folder newKeysFolderPath)
|
||
repeat with this_item in fileList
|
||
set userAdeptKeyPath to this_item as text
|
||
set dupfile to false
|
||
repeat with AdeptKey in AdeptKeyList
|
||
set shellcommand to "cmp -s " & (quoted form of AdeptKey) & " " & quoted form of (POSIX path of (userAdeptKeyPath))
|
||
try
|
||
--writetolog("shellcommand: " & shellcommand)
|
||
do shell script shellcommand
|
||
-- shellcommand will error on the files being different
|
||
--writetolog("result: duplicate")
|
||
|
||
set dupfile to true
|
||
exit repeat
|
||
on error scriptError
|
||
--writetolog("result: different")
|
||
-- do nothing
|
||
end try
|
||
end repeat
|
||
if not dupfile then
|
||
repeat with AdeptKey in newKeyList
|
||
set shellcommand to "cmp -s " & (quoted form of AdeptKey) & " " & quoted form of (POSIX path of (userAdeptKeyPath))
|
||
try
|
||
--writetolog("shellcommand: " & shellcommand)
|
||
do shell script shellcommand
|
||
-- shellcommand will error on the files being different
|
||
--writetolog("result: duplicate")
|
||
|
||
set dupfile to true
|
||
exit repeat
|
||
on error scriptError
|
||
--writetolog("result: different")
|
||
-- do nothing
|
||
end try
|
||
end repeat
|
||
end if
|
||
if not dupfile then
|
||
-- move to the preferences folder, making sure the name's unique
|
||
set newFilename to GetUniqueName(preferencesFolderPath, "AdobeKey.der")
|
||
tell application "Finder"
|
||
set name of file userAdeptKeyPath to newFilename
|
||
set userAdeptKeyPath to newKeysFolderPath & newFilename
|
||
move file userAdeptKeyPath to preferencesFolderPath with replacing
|
||
end tell
|
||
set newKeyList to newKeyList & (POSIX path of (preferencesFolderPath & newFilename))
|
||
end if
|
||
end repeat
|
||
end if
|
||
-- delete new keys folder
|
||
tell application "Finder" to move newKeysFolderPath to trash
|
||
--display dialog newKeyList as text
|
||
return newKeyList
|
||
end GetAdeptKeys
|
||
|
||
on GetKindleKeys()
|
||
set newKeyList to {}
|
||
set userPrefsPath to path to preferences from user domain as string
|
||
set preferencesFolderPath to userPrefsPath & prefsFolderName & ":"
|
||
if not folderexists(preferencesFolderPath) then
|
||
tell application "Finder"
|
||
set preferencesFolder to make new folder at userPrefsPath with properties {name:prefsFolderName}
|
||
end tell
|
||
end if
|
||
set newKeysFolderPath to preferencesFolderPath & newKeysFolderName & ":"
|
||
if not folderexists(newKeysFolderPath) then
|
||
tell application "Finder"
|
||
set newKeysFolder to make new folder at preferencesFolderPath with properties {name:newKeysFolderName}
|
||
end tell
|
||
end if
|
||
set scriptError to ""
|
||
set shellresult to ""
|
||
set success to true
|
||
set shellcommand to python & (quoted form of KindleKeyTool) & " " & quoted form of (POSIX path of (newKeysFolderPath))
|
||
set shellcommand to shellcommand & " > " & quotedtemppath()
|
||
writetolog("shellcommand: " & shellcommand)
|
||
cleartemp()
|
||
try
|
||
do shell script shellcommand
|
||
on error scriptError
|
||
set success to false
|
||
end try
|
||
set shellresult to readtemp()
|
||
writetolog("shellresult: " & shellresult & " " & scriptError)
|
||
--display dialog shellresult
|
||
if success then
|
||
--get all the files from newKeysFolder and add those that aren't duplicates
|
||
tell application "Finder" to set fileList to (every file in folder newKeysFolderPath)
|
||
repeat with this_item in fileList
|
||
set userKeyPath to this_item as text
|
||
set dupfile to false
|
||
repeat with key in KindleKeyList
|
||
set shellcommand to "cmp -s " & (quoted form of key) & " " & quoted form of (POSIX path of (userKeyPath))
|
||
try
|
||
--writetolog("shellcommand: " & shellcommand)
|
||
do shell script shellcommand
|
||
-- shellcommand will error on the files being different
|
||
--writetolog("result: duplicate")
|
||
|
||
set dupfile to true
|
||
exit repeat
|
||
on error scriptError
|
||
--writetolog("result: different")
|
||
-- do nothing
|
||
end try
|
||
end repeat
|
||
if not dupfile then
|
||
repeat with key in newKeyList
|
||
set shellcommand to "cmp -s " & (quoted form of key) & " " & quoted form of (POSIX path of (userKeyPath))
|
||
try
|
||
--writetolog("shellcommand: " & shellcommand)
|
||
do shell script shellcommand
|
||
-- shellcommand will error on the files being different
|
||
--writetolog("result: duplicate")
|
||
|
||
set dupfile to true
|
||
exit repeat
|
||
on error scriptError
|
||
--writetolog("result: different")
|
||
-- do nothing
|
||
end try
|
||
end repeat
|
||
end if
|
||
if not dupfile then
|
||
-- move to the preferences folder, making sure the name's unique
|
||
set newFilename to GetUniqueName(preferencesFolderPath, "KindleKey.der")
|
||
tell application "Finder"
|
||
set name of file userKeyPath to newFilename
|
||
set userKeyPath to newKeysFolderPath & newFilename
|
||
move file userKeyPath to preferencesFolderPath with replacing
|
||
end tell
|
||
set newKeyList to newKeyList & (POSIX path of (preferencesFolderPath & newFilename))
|
||
end if
|
||
end repeat
|
||
end if
|
||
-- delete new keys folder
|
||
tell application "Finder" to move newKeysFolderPath to trash
|
||
return newKeyList
|
||
end GetKindleKeys
|
||
|
||
on GetNookKeys()
|
||
set newKeyList to {}
|
||
set userPrefsPath to path to preferences from user domain as string
|
||
set preferencesFolderPath to userPrefsPath & prefsFolderName & ":"
|
||
if not folderexists(preferencesFolderPath) then
|
||
tell application "Finder"
|
||
set preferencesFolder to make new folder at userPrefsPath with properties {name:prefsFolderName}
|
||
end tell
|
||
end if
|
||
set newKeysFolderPath to preferencesFolderPath & newKeysFolderName & ":"
|
||
if not folderexists(newKeysFolderPath) then
|
||
tell application "Finder"
|
||
set newKeysFolder to make new folder at preferencesFolderPath with properties {name:newKeysFolderName}
|
||
end tell
|
||
end if
|
||
set scriptError to ""
|
||
set shellresult to ""
|
||
set success to true
|
||
set shellcommand to python & (quoted form of NookKeyTool) & " " & quoted form of (POSIX path of (newKeysFolderPath))
|
||
set shellcommand to shellcommand & " > " & quotedtemppath()
|
||
writetolog("shellcommand: " & shellcommand)
|
||
cleartemp()
|
||
try
|
||
do shell script shellcommand
|
||
on error scriptError
|
||
set success to false
|
||
end try
|
||
set shellresult to readtemp()
|
||
writetolog("shellresult: " & shellresult & " " & scriptError)
|
||
--display dialog shellresult
|
||
if success then
|
||
--get all the files from newKeysFolder and add those that aren't duplicates
|
||
tell application "Finder" to set fileList to (every file in folder newKeysFolderPath)
|
||
--display dialog (count of fileList)
|
||
repeat with this_item in fileList
|
||
set userKeyPath to this_item as text
|
||
set dupfile to false
|
||
repeat with key in bnKeys
|
||
set keyfilepath to third item of key
|
||
if length of keyfilepath > 0 then
|
||
set shellcommand to "cmp -s " & (quoted form of keyfilepath) & " " & quoted form of (POSIX path of (userKeyPath))
|
||
try
|
||
--writetolog("shellcommand: " & shellcommand)
|
||
do shell script shellcommand
|
||
-- shellcommand will error on the files being different
|
||
--writetolog("result: duplicate")
|
||
--display dialog "Deuplicate: " & userKeyPath & "//" & keyfilepath
|
||
set dupfile to true
|
||
exit repeat
|
||
on error scriptError
|
||
--writetolog("result: different")
|
||
-- do nothing
|
||
end try
|
||
end if
|
||
end repeat
|
||
if not dupfile then
|
||
repeat with key in newKeyList
|
||
set keyfilepath to third item of key
|
||
if length of keyfilepath > 0 then
|
||
set shellcommand to "cmp -s " & (quoted form of keyfilepath) & " " & quoted form of (POSIX path of (userKeyPath))
|
||
try
|
||
--writetolog("shellcommand: " & shellcommand)
|
||
do shell script shellcommand
|
||
-- shellcommand will error on the files being different
|
||
--writetolog("result: duplicate")
|
||
--display dialog "Deuplicate: " & userKeyPath & "//" & keyfilepath
|
||
set dupfile to true
|
||
exit repeat
|
||
on error scriptError
|
||
--writetolog("result: different")
|
||
-- do nothing
|
||
end try
|
||
end if
|
||
end repeat
|
||
end if
|
||
if not dupfile then
|
||
-- move to the preferences folder, making sure the name's unique
|
||
set newFilename to GetUniqueName(preferencesFolderPath, "Nook Study Key.b64")
|
||
tell application "Finder"
|
||
set name of file userKeyPath to newFilename
|
||
set userKeyPath to newKeysFolderPath & newFilename
|
||
move file userKeyPath to preferencesFolderPath with replacing
|
||
end tell
|
||
set newKeyList to newKeyList & {{newFilename, "", (POSIX path of (preferencesFolderPath & newFilename))}}
|
||
end if
|
||
end repeat
|
||
end if
|
||
-- delete new keys folder
|
||
tell application "Finder" to move newKeysFolderPath to trash
|
||
return newKeyList
|
||
end GetNookKeys
|
||
|
||
on encodeAsBase64(theFilePath)
|
||
set posixfilepath to POSIX path of file theFilePath
|
||
set base64path to POSIX path of file ((path to me as text) & "Contents:Resources:encodebase64.py")
|
||
return do shell script python & quoted form of base64path & " " & quoted form of posixfilepath
|
||
end encodeAsBase64
|
||
|
||
on AddAdeptKey(keyfile)
|
||
set fileExtension to GetFileExtension(keyfile)
|
||
if fileExtension is "der" then
|
||
set newPrefsFile to CopyToPrefs(keyfile)
|
||
set AdeptKeyList to AdeptKeyList & POSIX path of newPrefsFile
|
||
else
|
||
display dialog "Adobe Adept key files generated by adeptkey.py must have a .der extension." buttons {"OK"} default button 1 with title "DeDRM" with icon caution
|
||
end if
|
||
end AddAdeptKey
|
||
|
||
on AddKindleKey(keyfile)
|
||
set fileExtension to GetFileExtension(keyfile)
|
||
if fileExtension is "k4i" then
|
||
set newPrefsFile to CopyToPrefs(keyfile)
|
||
set KindleKeyList to KindleKeyList & POSIX path of newPrefsFile
|
||
else
|
||
display dialog "Kindle key files generated by kindlekey.py must have a .k4i extension." buttons {"OK"} default button 1 with title "DeDRM" with icon caution
|
||
end if
|
||
end AddKindleKey
|
||
|
||
on AddAndroidKey(keyfile)
|
||
set fileExtension to GetFileExtension(keyfile)
|
||
if fileExtension is "ab" or fileExtension is "db" or fileExtension is "xml" then
|
||
set newPrefsFile to CopyToPrefs(keyfile)
|
||
set AndroidKeyList to AndroidKeyList & POSIX path of newPrefsFile
|
||
else
|
||
display dialog "Android back files generated by use of \"adb backup com.amazon.kindle\" must have a .ab extension." buttons {"OK"} default button 1 with title "DeDRM" with icon caution
|
||
end if
|
||
end AddAndroidKey
|
||
|
||
on AddbnKey(keyfile)
|
||
set fileExtension to GetFileExtension(keyfile)
|
||
if fileExtension is "b64" then
|
||
set newPrefsFile to CopyToPrefs(keyfile)
|
||
tell application "Finder"
|
||
set keyfileName to (name of file newPrefsFile) as text
|
||
end tell
|
||
set fileName to GetFileNameOnly(keyfileName)
|
||
set bnKeys to bnKeys & {{fileName, "", POSIX path of newPrefsFile}}
|
||
else
|
||
display dialog "Barnes & Noble key files must have a .b64 extension." buttons {"OK"} default button 1 with title "DeDRM" with icon caution
|
||
end if
|
||
end AddbnKey
|
||
|
||
on GetUniqueName(folderPath, fileName)
|
||
set newFilename to fileName
|
||
if fileexists(folderPath & fileName) then
|
||
-- first find new name that's unique to folder
|
||
set namecount to 2
|
||
set fileExtension to GetFileExtension(fileName)
|
||
set fileNameOnly to GetFileNameOnly(fileName)
|
||
repeat
|
||
set newFilename to fileNameOnly & " " & (namecount as text) & "." & fileExtension
|
||
if not fileexists(folderPath & newFilename) then
|
||
exit repeat
|
||
end if
|
||
set namecount to namecount + 1
|
||
end repeat
|
||
end if
|
||
return newFilename
|
||
end GetUniqueName
|
||
|
||
on CopyToPrefs(keyfilepath)
|
||
tell application "Finder"
|
||
set keyfileName to (name of file keyfilepath) as text
|
||
end tell
|
||
set keyfileApplepath to POSIX file (POSIX path of keyfilepath)
|
||
set userPrefsPath to path to preferences from user domain as string
|
||
set userTempPath to path to temporary items from user domain as string
|
||
set preferencesFolderPath to userPrefsPath & prefsFolderName & ":"
|
||
if not folderexists(preferencesFolderPath) then
|
||
tell application "Finder"
|
||
set preferencesFolder to make new folder at userPrefsPath with properties {name:prefsFolderName}
|
||
end tell
|
||
end if
|
||
if fileexists(preferencesFolderPath & keyfileName) then
|
||
-- copy to temporary items folder, rename, and then we can copy from there to the preferences folder
|
||
-- first find new name
|
||
set namecount to 2
|
||
set fileExtension to GetFileExtension(keyfileName)
|
||
set keyfileNameOnly to GetFileNameOnly(keyfileName)
|
||
repeat
|
||
set newkeyfileName to keyfileNameOnly & " " & (namecount as text) & "." & fileExtension
|
||
if not fileexists(preferencesFolderPath & newkeyfileName) and not fileexists(userTempPath & newkeyfileName) then
|
||
exit repeat
|
||
end if
|
||
set namecount to namecount + 1
|
||
end repeat
|
||
-- rename to new name
|
||
set newkeyfilepath to userTempPath & newkeyfileName
|
||
tell application "Finder"
|
||
set tempfilepath to duplicate file keyfileApplepath to folder userTempPath with replacing
|
||
set name of tempfilepath to newkeyfileName
|
||
move file newkeyfilepath to preferencesFolderPath
|
||
end tell
|
||
set newFile to preferencesFolderPath & newkeyfileName
|
||
else
|
||
tell application "Finder"
|
||
set newFile to duplicate file keyfileApplepath to folder preferencesFolderPath with replacing
|
||
end tell
|
||
end if
|
||
|
||
return newFile as text
|
||
end CopyToPrefs
|
||
|
||
on ReadPrefs()
|
||
-- read any existing keys from the preferences
|
||
set PIDs to {}
|
||
set UDIDs to {}
|
||
set bnKeys to {}
|
||
set KindleKeyList to {}
|
||
set AndroidKeyList to {}
|
||
set KindleSerialList to {}
|
||
set AdeptKeyList to {}
|
||
set outputFolder to (path to desktop as string)
|
||
set logFilePath to (path to desktop as string) & "DeDRM.log"
|
||
set userPrefsPath to path to preferences from user domain as string
|
||
set preferencesFolderPath to userPrefsPath & prefsFolderName & ":"
|
||
if not folderexists(preferencesFolderPath) then
|
||
tell application "Finder"
|
||
set preferencesFolder to make new folder at userPrefsPath with properties {name:prefsFolderName}
|
||
end tell
|
||
end if
|
||
set preferencesFilePath to userPrefsPath & prefsFileName
|
||
set tempfilepath to preferencesFolderPath & tempFileName
|
||
|
||
if fileexists(POSIX path of file preferencesFilePath) then
|
||
tell application "System Events"
|
||
try
|
||
set PIDs to value of property list item "PIDs" of property list file preferencesFilePath
|
||
end try
|
||
try
|
||
set UDIDs to value of property list item "UDIDs" of property list file preferencesFilePath
|
||
end try
|
||
try
|
||
set KindleSerialList to value of property list item "KindleSerials" of property list file preferencesFilePath
|
||
end try
|
||
try
|
||
set bnKeys to value of property list item "bnKeys" of property list file preferencesFilePath
|
||
end try
|
||
try
|
||
set AdeptKeyList to value of property list item "AdeptKeys" of property list file preferencesFilePath
|
||
end try
|
||
try
|
||
set AndroidKeyList to value of property list item "AndroidKeys" of property list file preferencesFilePath
|
||
end try
|
||
try
|
||
set KindleKeyList to value of property list item "KindleKeys" of property list file preferencesFilePath
|
||
end try
|
||
try
|
||
set outputFolder to value of property list item "OutputFolder" of property list file preferencesFilePath
|
||
end try
|
||
end tell
|
||
end if
|
||
|
||
|
||
set newList to {}
|
||
repeat with i from 1 to count AndroidKeyList
|
||
if fileexists(AndroidKeyList's item i) then set newList's end to AndroidKeyList's item i
|
||
end repeat
|
||
set AndroidKeyList to newList
|
||
|
||
set newList to {}
|
||
repeat with i from 1 to count AdeptKeyList
|
||
if fileexists(AdeptKeyList's item i) then set newList's end to AdeptKeyList's item i
|
||
end repeat
|
||
set AdeptKeyList to newList
|
||
|
||
set newList to {}
|
||
repeat with i from 1 to count KindleKeyList
|
||
if fileexists(KindleKeyList's item i) then set newList's end to KindleKeyList's item i
|
||
end repeat
|
||
set KindleKeyList to newList
|
||
|
||
set newList to {}
|
||
repeat with i from 1 to count bnKeys
|
||
if (item 3 of bnKeys's item i) is "" or fileexists(item 3 of bnKeys's item i) then set newList's end to bnKeys's item i
|
||
end repeat
|
||
set bnKeys to newList
|
||
|
||
end ReadPrefs
|
||
|
||
on CreatePlist(filePath)
|
||
set theEmptyPListData to "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
|
||
<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
|
||
<plist version=\"1.0\">
|
||
<dict/>
|
||
</plist>"
|
||
|
||
set thePListFile to open for access filePath with write permission
|
||
set eof of thePListFile to 0
|
||
write theEmptyPListData to thePListFile starting at eof
|
||
close access thePListFile
|
||
|
||
end CreatePlist
|
||
|
||
on WritePrefsOld()
|
||
-- write keys to the preferences from older AppleScript
|
||
set preferencesFilePath to (path to preferences from user domain as string) & prefsFileName
|
||
CreatePlist(preferencesFilePath)
|
||
tell application "System Events"
|
||
tell contents of property list file preferencesFilePath
|
||
set value to ({|PIDs|:PIDs} & {|UDIDs|:UDIDs} & {|AndroidKeys|:AndroidKeyList} & {|KindleSerials|:KindleSerialList} & {|KindleKeys|:KindleKeyList} & {|bnKeys|:bnKeys} & {|AdeptKeys|:AdeptKeyList} & {|OutputFolder|:outputFolder})
|
||
|
||
end tell
|
||
end tell
|
||
end WritePrefsOld
|
||
|
||
on WritePrefs()
|
||
if oldAppleScript then
|
||
WritePrefsOld()
|
||
else
|
||
-- write keys to the preferences for AppleScript 2.0 and later
|
||
set preferencesFilePath to (path to preferences from user domain as string) & prefsFileName
|
||
-- we still need to create an empty file in Yosemite, apparently
|
||
CreatePlist(preferencesFilePath)
|
||
tell application "System Events"
|
||
set the base_dict to make new property list item with properties {kind:record}
|
||
set myPrefs to make new property list file with properties {contents:base_dict, name:preferencesFilePath}
|
||
make new property list item at end of property list items of contents of myPrefs with properties {kind:list, name:"PIDs", value:PIDs}
|
||
make new property list item at end of property list items of contents of myPrefs with properties {kind:list, name:"UDIDs", value:UDIDs}
|
||
make new property list item at end of property list items of contents of myPrefs with properties {kind:list, name:"AndroidKeys", value:AndroidKeyList}
|
||
make new property list item at end of property list items of contents of myPrefs with properties {kind:list, name:"KindleSerials", value:KindleSerialList}
|
||
make new property list item at end of property list items of contents of myPrefs with properties {kind:list, name:"KindleKeys", value:KindleKeyList}
|
||
make new property list item at end of property list items of contents of myPrefs with properties {kind:list, name:"bnKeys", value:bnKeys}
|
||
make new property list item at end of property list items of contents of myPrefs with properties {kind:list, name:"AdeptKeys", value:AdeptKeyList}
|
||
make new property list item at end of property list items of contents of myPrefs with properties {kind:string, name:"OutputFolder", value:outputFolder}
|
||
end tell
|
||
end if
|
||
end WritePrefs
|
||
|
||
|
||
on InitProgress(maxcount)
|
||
try
|
||
if totalebooks > 1 then
|
||
launch application ((path to resource "DeDRM Progress.app") as string)
|
||
tell application ((path to resource "DeDRM Progress.app") as string)
|
||
activate
|
||
set contents of «class texF» "maintext" of window "main" to "Decrypting " & maxcount & " ebooks."
|
||
set contents of «class texF» "subtext" of window "main" to "Decrypting book 0: "
|
||
set «class maxV» of «class proI» "bar" of window "main" to maxcount
|
||
set «class conT» of «class proI» "bar" of window "main" to 0
|
||
end tell
|
||
end if
|
||
end try
|
||
|
||
end InitProgress
|
||
|
||
on ProcessItems(some_items)
|
||
try
|
||
set ErrorList to ""
|
||
set WarningList to ""
|
||
set CompletedList to ""
|
||
set ErrorCount to 0
|
||
set WarningCount to 0
|
||
set CompletedCount to 0
|
||
set totalebooks to 0
|
||
set completedebooks to 0
|
||
repeat with this_item in some_items
|
||
if (folder of (info for this_item) is true) then
|
||
tell application "Finder" to set totalebooks to totalebooks + (count of (every file in entire contents of folder this_item whose name extension is in handledExtensions))
|
||
else
|
||
countfile(this_item as text)
|
||
end if
|
||
end repeat
|
||
if totalebooks is 1 then
|
||
set TotalText to "There is 1 ebook to be decrypted."
|
||
else
|
||
set TotalText to "There are " & totalebooks & " ebooks to be decrypted."
|
||
end if
|
||
writetolog(TotalText)
|
||
InitProgress(totalebooks)
|
||
repeat with this_item in some_items
|
||
if totalebooks > 1 and not ProgressActive() then
|
||
exit repeat
|
||
end if
|
||
if (folder of (info for this_item) is true) then
|
||
handlefolder(this_item as text)
|
||
else
|
||
handlefile(this_item as text)
|
||
end if
|
||
end repeat
|
||
endProgress()
|
||
on error errmsg number errnum
|
||
set errorReport to "An unexpected error occurred. Please report on Apprentice Alf's blog.
|
||
|
||
Error Message: " & errmsg & "
|
||
Error Number: " & errnum
|
||
writetolog(errorReport)
|
||
display notification errorReport with title "DeDRM" subtitle "Unexpected Error"
|
||
--display dialog errorReport with title "DeDRM" buttons {"Bother"} default button 1 with icon stop
|
||
end try
|
||
if WarningList is not "" then
|
||
set WarningText to ""
|
||
if WarningCount is 1 then
|
||
set WarningText to "There was a warning with 1 ebook:"
|
||
else
|
||
set WarningText to "There were warnings with " & WarningCount & " ebooks:"
|
||
end if
|
||
writetolog(WarningText)
|
||
writetolog(WarningList)
|
||
--set dialogresult to display dialog WarningText & "
|
||
|
||
--" & WarningList buttons {"OK"} with title "DeDRM" default button 1
|
||
display notification WarningList with title "DeDRM" subtitle WarningText
|
||
end if
|
||
if ErrorList is not "" then
|
||
set ErrorText to ""
|
||
if ErrorCount is 1 then
|
||
set ErrorText to "There was an error with 1 ebook:"
|
||
else
|
||
set ErrorText to "There were errors with " & ErrorCount & " ebooks:"
|
||
end if
|
||
writetolog(ErrorText)
|
||
writetolog(ErrorList)
|
||
--set dialogresult to display dialog ErrorText & "
|
||
|
||
--" & ErrorList buttons {"Bother"} with title "DeDRM" default button 1
|
||
display notification ErrorList with title "DeDRM" subtitle ErrorText
|
||
end if
|
||
if CompletedCount > 0 then
|
||
set CompletedText to ""
|
||
if CompletedCount is 1 then
|
||
set CompletedText to "Successfully de-drmed 1 ebook:"
|
||
else
|
||
set CompletedText to "Successfully de-drmed " & CompletedCount & " ebooks:"
|
||
end if
|
||
writetolog(CompletedText)
|
||
writetolog(CompletedList)
|
||
--set dialogresult to display dialog CompletedText & "
|
||
|
||
--" & CompletedList buttons {"Thanks"} with title "DeDRM" default button 1
|
||
display notification CompletedList with title "DeDRM" subtitle CompletedText
|
||
end if
|
||
return CompletedCount + WarningCount + ErrorCount
|
||
end ProcessItems
|
||
|
||
on ProgressActive()
|
||
tell application "System Events" to set progactive to count (every process whose name is "DeDRM Progress")
|
||
if progactive > 0 then return true
|
||
return false
|
||
end ProgressActive
|
||
|
||
on IncProgress(booktitle, doingcount)
|
||
try
|
||
if ProgressActive() then
|
||
tell application ((path to resource "DeDRM Progress.app") as string)
|
||
set contents of «class texF» "subtext" of window "main" to "Decrypting book " & doingcount & ": " & booktitle
|
||
set «class conT» of «class proI» "bar" of window "main" to doingcount
|
||
end tell
|
||
end if
|
||
end try
|
||
end IncProgress
|
||
|
||
on endProgress()
|
||
try
|
||
if ProgressActive() then tell application ((path to resource "DeDRM Progress.app") as string) to quit
|
||
end try
|
||
end endProgress
|
||
|
||
|
||
on run
|
||
if GetTools() then
|
||
ReadPrefs()
|
||
clearlog()
|
||
repeat
|
||
set dialogresult to display dialog "To remove DRM from an ebook, click ‘Select Ebook…’
|
||
To configure this software, click ‘Configure…’
|
||
|
||
When the DeDRM application is not running, you can also remove DRM from ebooks by dropping them onto the DeDRM application icon in the Finder.
|
||
|
||
For details of the ebook formats which this application can handle, see the ReadMe file or visit http://apprenticealf.wordpress.com/
|
||
Please only use this application on your own books. Authors, publishers and ebook stores need to make money to produce more ebooks.
|
||
Don't cheat them.
|
||
|
||
This application is by Apprentice Alf and Apprentice Harper based on an AppleScript script by Paul Durrant and uses python scripts produced by Apprentice Alf, CMBDTC, The Dark Reverser, DiapDealer, i♥cabbages, some_updates, Apprentice Harper and others.
|
||
The AppleScript part of this application is free software released into the public domain, see http://unlicense.org/
|
||
The application icon is adapted from the Authors Against DRM logo at
|
||
http://readersbillofrights.info/AAD and is under the Creative Commons Attribution-ShareAlike licence.
|
||
|
||
The included Python scripts are all free to use, but have a variety of licences. See the individual files for details.
|
||
" with title "DeDRM by Apprentice Alf" buttons {"Quit", "Select Ebook… ", "Configure… "} default button 1 with icon note
|
||
if button returned of dialogresult is "Quit" then exit repeat
|
||
if button returned of dialogresult is "Select Ebook… " then
|
||
set DRMebook to ""
|
||
try
|
||
set DRMebook to {choose file with prompt "Please select a DRMed ebook"}
|
||
end try
|
||
if DRMebook is not "" then
|
||
if ProcessItems(DRMebook) is 0 then
|
||
display dialog "That was a file that this script cannot process." with title "DeDRM" buttons {"OK"} default button 1 with icon note
|
||
end if
|
||
WritePrefs()
|
||
end if
|
||
else
|
||
set choice to true
|
||
repeat while choice is not false
|
||
set choice to choose from list {"eInk Kindle eBooks", "Barnes and Noble (nook) ebooks", "Mobipocket eBooks", "eReader ebooks", "Adobe Digital Editions ebooks", "Kindle for Mac ebooks", "Output Folder"} with prompt "Choose a Configuration Option:" with title "DeDRM Configuration" OK button name "Configure..." cancel button name "Finished"
|
||
if choice contains "Barnes and Noble (nook) ebooks" then
|
||
GetBNKeys("DeDRM Configure for Barnes and Noble (nook)")
|
||
else if choice contains "eInk Kindle eBooks" then
|
||
GetSerials("DeDRM Configure for eInk Kindle")
|
||
else if choice contains "Mobipocket eBooks" then
|
||
GetPIDs("DeDRM Configure for Mobipocket")
|
||
else if choice contains "eReader ebooks" then
|
||
GeteReaderKeys("DeDRM Configure for eReader")
|
||
else if choice contains "Kindle for Mac ebooks" then
|
||
GetKindleKeyFiles("DeDRM Configure Kindle for Mac")
|
||
else if choice contains "Kindle for Android ebooks" then
|
||
GetAndroidKeyFiles("DeDRM Configure Kindle for Android")
|
||
else if choice contains "Adobe Digital Editions ebooks" then
|
||
GetAdeptKeyFiles("DeDRM Configure Adobe Digital Editions")
|
||
else if choice contains "Output Folder" then
|
||
GetOutputFolder("DeDRM Configure Output Folder")
|
||
end if
|
||
end repeat
|
||
WritePrefs()
|
||
end if
|
||
end repeat
|
||
end if
|
||
end run
|
||
|
||
on open some_items
|
||
--display dialog (some_items as text)
|
||
if GetTools() then
|
||
ReadPrefs()
|
||
clearlog()
|
||
|
||
if ProcessItems(some_items) is 0 then
|
||
display notification "No ebooks found in the dropped items. DeDRM can handle Mobipocket, Kindle, eReader, Adobe ePub, Barnes & Noble ePub and Adobe PDF. Please try again." with title "DeDRM"
|
||
end if
|
||
WritePrefs()
|
||
delay 1 --> allow time for any notifications to trigger
|
||
end if
|
||
end open
|
||
|