I had a few folks mentioned in an OS X AppleScript thread that they wanted to see the code from a project I finished a few months back in case it would help other folks. So I’m re-posting here with the code.
QUESTION:
The original query I was responding to was someone asking how to put the File Type and File Creator back onto Mac files that have lost them to mangling by the Windows world.
MY RESPONSE:
The trick is YOU need to know the File Type and File Creator in order to make the fixes. Mac OS X is kinda dumb on this front, I found much to my dismay.
We had a bunch of Mac files in a Digital Asset Manager (DAM) that handled Mac files fine. We had to migrate to a new system, and all seemed well until we realized far too late that all File Type and File Creator information got stripped. Lost the resource fork, essentially.
Since we couldn’t fix the hundreds of thousands of assets (nearly 1.2 TB) server-side, we opted for a “fixit” routine I wrote for Mac folks when they download the files. After the download they drag-n-drop the files onto my droplet and it fixes over 95% of issues, including restoring previews in image files. It also makes minor changes, like applying extensions to files that didn’t have them, or fixes extensions that the asset manager “gives” them because they had none (the DAM guesses wrong alot).
I did all this “magic” by scouring our Macs for every common file type the DAM contained, even scouring old archives, and then creating a chart of Type and Creator. This involved a script that would write to a text file the file name, Creator, and Type. Then I had to see how much of the Type/Creator info was unique to certain extensions (this gives the File Type part of the equation). I also had to use hexdumps to view file contents looking for unique strings (the Creator Type detective work). Then I had to reference that against things I could figure out from a file that didn’t have this information, which meant reading headers, knowing something about our internal file naming standards, etc.
In the end, I had 40 cases I had to do lookups against. I narrowed the list down to a tree of conditions. Sometimes a single condition defined a Creator/Type pair; sometimes it spawned a sub-tree of conditionals to check; sometimes a “this condition AND that condition” had to be met, which could then spawn more sub-conditions. In other words, nowhere near straightfoward.
In fact, last week we found a certain file with a certain “guess” induced by the DAM caused some files not to be “fixed” by my script. I narrowed down what the problem was (a set of circumstances I didn’t predict), and I will have to re-assess all my nested conditionals and rebuild one of the branches for PDF-vs-Illustrator detection.
One thing I learned, you can’t reply on the Mac OS itself. It is “guessing” based on the existing file extension. If none exists, it’s a horrible guesser. For example, Adobe Illustrator CS files look like PDFs, so the Mac OS can’t tell the difference between a “real” PDF and an Illustrator file without an extension. The only real way to tell is to GREP the contents of the file seeking specific text strings embedded therein. This is further complicated by “encrypted” files formats used by some companies (cough Quark XPress cough) that have no English-readable strings for GREP to find. Those were fun…NOT.
If anyone is interested, I can post the code I came-up with, but it’s pretty long. It’s not as elegant as it could be, and is very biased towards graphics files (I work in the Creative Services department). I’ve also since learned better ways to do things like file extension detection, I just don’t have the time to go back and re-write the appropriate handlers.
DISCLAIMERS:
1…This routine is VERY specific to my workplace. We have certain file naming standards I took advantage of to shortcut some of the work, and hopefully I commented those enough for anyone wanting to re-use the code.
2…I’m kinda short on time, so the code below is directly from a FaceSpan application. So you may see constructs that are not normal ApplScript but things FaceSpan needs, especially for things like progress bars. But there is a current question about this need in the forums, so I’m providing it in haste. Apologies in advance, I’ll subscribe to this thread to answer questions as I can.
3…I’m no expert. This is the most complex AppleScript I’ve designed to date, and my first big foray into FaceSpan. Please be gentle.
4…On part that really needs work is the “extension detection” handlers. I only recently realize the easier way to handle discovery of an existing file extension is to “reverse” the file name so you can use “first x characters” or “look for first period” instead of the kludy was I had to do it working from the back. Live and learn…that’ll be in Version 2.
5…We have one bug in the application here in the shop. If an Adobe Illustrator CS file is mislabelled with a “.pdf” extension instead of a proper “.ai” extension, this droplet will not fix it. The script was designed to even fix mistakes like that, but I didn’t forsee this specific instance. I’ve traced the problem, but no time to re-arrange and rewrite the appropriate decision trees.
6…The is the Project Script from a FaceSpan-built applet. It likely won’t work “as is” unless you plop it into FaceSpan and compile.
7…It has issues detecting various flavors of Quark files (can’t disern Quark 4 and Quark 7 files as I recall). Quark is a 5-letter word here so it wasn’t an issue I pursued much. We’re an Adobe shop.
INSTRUCTIONS:
If you can adapt it to a simple drag-n-drop Applet, it will accept any combinations of files, folders, or subfolders dragged into it. It will set the Finder label color to red for all files, then proceed to check and fix every single one in turn. If it can fix it, it will return the Finder label to none, and leave a comment in the Get Info box. If it cannot figure out what to do with it, the Finder label will stay red.
It fixes File Type and Creator Type if it can, sometimes it will only fix one or the other. It will add extensions to files missing them (Illustrator or InDesign). It will open and re-save all Photoshop files so their screen previews will work properly when linked to Illustrator (except for GIFs), which also returns their thumbnail previews.
It will fix older files like Illustrator 8, but due to the way Adobe handles the File/Creator types for all version of Illustrator, all Illustrator files will take-on the icon of the newest version of Illustrator on your machine. Same goes for InDesign. FreeHand files, however, will get their proper icons based on version.
ENJOY!
I’ll subscribe to this thread and try to answer questions as I can.
APPLESCRIPT CODE:
(*
-- --------------------------------------------------------------------
-- FACESPAN DEFAULTS for drag-n-drop template
-- --------------------------------------------------------------------
property windowOpen : false
on launched theObject
set windowOpen to true
open window "main"
end launched
if windowOpen is false then
open window "main"
end if
-- --------------------------------------------------------------------
*)
--
-- DECLARE GLOBAL VARIABLES
--
global g_debug
global g_extensions_native_illustrator
global g_headers_native_illustrator
global g_extensions_other_illustrator
global g_headers_other_illustrator
global g_extensions_quark
global g_headers_quark
global g_extensions_indesign
global g_headers_indesign
global g_extensions_photoshop_eps
global g_headers_photoshop_eps
global g_extensions_photoshop_psd
global g_headers_photoshop_psd
global g_extensions_photoshop_tif
global g_headers_photoshop_tif
global g_extensions_photoshop_jpg
global g_headers_photoshop_jpg
global g_extensions_photoshop_gif
global g_extensions_photoshop_png
global g_extensions_acrobat
global g_headers_acrobat
global g_extensions_pagemaker
global g_extensions_freehand_eps
global g_headers_freehand_eps
global g_extensions_freehand
global g_headers_freehand
--
-- UTILITY HANDLERS
--
--
--Load Global Lists
--
on loadLists()
set g_extensions_native_illustrator to {"none", ".ai", ".eps"} --DAM System adds ".eps" when it doesn't see an extension...doh!
set g_headers_native_illustrator to {"Creator:Adobe Illustrator(TM) 3.2", "Creator: Adobe Illustrator(R) 8", "Creator: Adobe Illustrator(R) 9", "Creator: Adobe Illustrator(R) 10", "Creator: Adobe Illustrator(R) 11", "Creator: Adobe Illustrator(R) 12"}
set g_extensions_other_illustrator to {".eps", ".epsf"}
set g_headers_other_illustrator to {"PS-Adobe-2.0 EPSF-", "PS-Adobe-3.0 EPSF-", "PS-Adobe-3.1 EPSF-"} --valid Illustrator EPS files have this additional header info
set g_extensions_quark to {"none", ".qxd", ".qxp"}
set g_headers_quark to {"QXP__5", "QXPPP6"}
set g_extensions_indesign to {"none", ".indd"}
set g_headers_indesign to {"CreatorTool>Adobe InDesign 3", "CreatorTool>Adobe InDesign 4", "Adobe InDesign"}
set g_extensions_photoshop_psd to {".psd", ".psd_lr", ".psd_hr"}
set g_headers_photoshop_psd to {"8BIM", "Adobe Photoshop 7", "Adobe Photoshop CS Macintosh", "Adobe Photoshop CS2 Macintosh"}
-- "8BIM" in header list is from Adobe Photoshop 6
set g_extensions_photoshop_eps to {".eps", ".epsf", ".dcs", ".eps_lr", ".eps_hr", ".dcs_lr", ".dcs_hr"}
set g_headers_photoshop_eps to {"Creator: Adobe Photoshop Version 6", "Creator: Adobe Photoshop Version 7", "Creator: Adobe Photoshop Version 8", "Creator: Adobe Photoshop Version 9", "Creator: MediaBin"}
set g_extensions_photoshop_tif to {".tif", ".tiff", ".tif_lr", ".tif_hr"}
set g_headers_photoshop_tif to {"Adobe Photoshop 7", "Adobe Photoshop CS Macintosh", "Adobe Photoshop CS2 Macintosh"}
set g_extensions_photoshop_jpg to {".jpg", ".jpeg"}
set g_headers_photoshop_jpg to {"Adobe Photoshop 7", "Adobe Photoshop CS Macintosh", "Adobe Photoshop CS2 Macintosh"}
set g_extensions_photoshop_gif to {".gif"}
set g_extensions_photoshop_png to {".png"}
set g_extensions_acrobat to {".pdf"}
set g_headers_acrobat to {"PDF-1.3", "PDF-1.4", "PDF-1.5", "PDF-1.6"}
set g_extensions_pagemaker to {".pm5", ".pm6", ".p65"}
set g_extensions_freehand_eps to {".eps"}
set g_headers_freehand_eps to {"Creator: FreeHand 8", "Creator: FreeHand 7", "Creator: FreeHand MX 11"}
set g_extensions_freehand to {"none", ".fh3", ".fh4", ".fh5", ".fh7", ".fh8", ".fh9", ".fh10", ".fh11"}
set g_headers_freehand to {"AGD1", "AGD2", "AGD3", "FreeHand10", "FreeHand11"}
end loadLists
--
--Log Entry Generation
--
on logMe(log_string, indent_level)
if g_debug is "true" then --allows turning the debugger on and off so logMe's can be left in final version
set log_file_name to "CompanyName File Repair Log.txt"
set home_folder_path to path to home folder
set log_file_path to (home_folder_path & "Library:Logs:" & log_file_name) as text
try
writeEntry(log_string, indent_level, log_file_path)
on error
tell application "Finder"
make new file at log_file_path with properties {name:log_file_name}
close access (log_file_path as alias)
end tell
writeEntry(log_string, indent_level, log_file_path)
end try
end if
end logMe
on writeEntry(log_string, indent_level, log_file_path)
tell application "Finder"
open for access file log_file_path with write permission
repeat indent_level times
write tab to (log_file_path as alias) starting at eof
end repeat
write (log_string & return) to (log_file_path as alias) starting at eof
close access (log_file_path as alias)
end tell
end writeEntry
--
-- Is it a folder?
--
on folderFinder(alias_to_check)
if (alias_to_check as string) ends with ":" then
return "yes"
else
return "no"
end if
end folderFinder
--
-- Finder comment editor
--
on finderCommenter(path_to_file, add_this_text)
tell application "Finder"
set existing_comments to (comment of path_to_file)
set new_comments to existing_comments & return & add_this_text
set comment of path_to_file to new_comments
end tell
end finderCommenter
--
-- Date stamp generator
--
on dateStamp()
-- Load date components from system
set day_stamp to day of (current date) as integer
set month_stamp to month of (current date) as text
set year_stamp to year of (current date) as text
--Coerce day component to two-digit form
if day_stamp < 10 then set day_stamp to "0" & day_stamp
--Coerce month component to two-digit form
if month_stamp is "January" then set month_stamp to "01"
if month_stamp is "February" then set month_stamp to "02"
if month_stamp is "March" then set month_stamp to "03"
if month_stamp is "April" then set month_stamp to "04"
if month_stamp is "May" then set month_stamp to "05"
if month_stamp is "June" then set month_stamp to "06"
if month_stamp is "July" then set month_stamp to "07"
if month_stamp is "August" then set month_stamp to "08"
if month_stamp is "September" then set month_stamp to "09"
if month_stamp is "October" then set month_stamp to "10"
if month_stamp is "November" then set month_stamp to "11"
if month_stamp is "December" then set month_stamp to "12"
-- Coerce year into two-digit form
set year_stamp to characters 3 thru 4 of year_stamp as text
--Assemble datestamp
return year_stamp & month_stamp & day_stamp as text
end dateStamp
--
-- File progress updater
--
on fileProgressUpdate(path_name, status_string, progress_increment)
tell application "Finder"
set file_name to name of path_name as string
end tell
set string value of text field "textFilenameOperation" of window "main" to ("File: " & file_name & " ¢ " & "Status: " & status_string & "...")
set current_progress to (contents of progress indicator "progressFile" of window "main")
set contents of progress indicator "progressFile" of window "main" to (current_progress + progress_increment)
end fileProgressUpdate
--
-- INFORMATION GATHERING HANDLERS
--
--
-- lr/hr file extension parser
--
on lrhrParse(name_type, path_to_fix)
tell application "Finder"
set file_to_fix to name of path_to_fix as string
set name_length to length of file_to_fix as number
end tell
if name_type is "long" then
set extension_length to 10
else
set extension_length to 6
end if
if name_length is greater than extension_length then
set this_extension to (text items (name_length - extension_length) thru name_length of file_to_fix) as string
--check validity of extension (trap for false "." characters)
set extension_validate to (text items 5 thru 7 of this_extension) as string
if extension_validate is not in {"_lr", "_hr"} then
return "<invalid>"
else
return this_extension
end if
else
return "too short"
end if
end lrhrParse
--
-- Determines "real" extension
--
on extensionFinder(path_to_fix)
logMe("extensionFinder Handler Called", 3)
--get some basic Finder information
tell application "Finder"
set file_to_fix to name of path_to_fix as string
set name_length to length of file_to_fix as number
end tell
logMe("name length = " & name_length, 4)
--parse end of file name for possible extension types
--
--define possible "_lr/_hr + DAM System" extension, watch for files names too short for this check
set lrhr_long_extension to lrhrParse("long", path_to_fix)
logMe("lrhr_long_extension = " & lrhr_long_extension, 4)
--define possible _lr/_hr extension, watch for files names too short for this check
set lrhr_short_extension to lrhrParse("short", path_to_fix)
logMe("lrhr_short_extension = " & lrhr_short_extension, 4)
--define any Finder-recognized extension
set standard_2_extension to (text items (name_length - 2) thru name_length of file_to_fix) as string --like Illustrator's .ai
logMe("standard_2_extension = " & standard_2_extension, 4)
set standard_3_extension to (text items (name_length - 3) thru name_length of file_to_fix) as string --standard 3-letter extensions
logMe("standard_3_extension = " & standard_3_extension, 4)
set standard_4_extension to (text items (name_length - 4) thru name_length of file_to_fix) as string --like InDesign's .indd
logMe("standard_4_extension = " & standard_4_extension, 4)
--figure out which extension type captured above is the "real" one
--
--is it "_lr/_hr + DAM System"?
if text item 1 of lrhr_long_extension is "." then
logMe("EXTENSION TYPE: CADS-style Long (CADS-style + DAM System)", 4)
--remove the extra DAM System extension
set fixed_long_extension to (text items 1 thru ((length of lrhr_long_extension) - 4) of lrhr_long_extension as string)
set my_extension to fixed_long_extension
logMe("¢ CONVERT TO CADS-style SHORT: " & fixed_long_extension, 4)
else
-- is it simply _lr/_hr?
if text item 1 of lrhr_short_extension is "." then
logMe("EXTENSION TYPE: CADS-style Short", 4)
set my_extension to lrhr_short_extension
else
--is it something like InDesign (.indd)
if text item 1 of standard_4_extension is "." then
logMe("EXTENSION TYPE: Finder Long", 4)
set my_extension to standard_4_extension
else
--is it a typical 3-digit Finder?
if text item 1 of standard_3_extension is "." then
logMe("EXTENSION TYPE: Finder Typical", 4)
set my_extension to standard_3_extension
else
--is it something like Illustrator (.ai)
if text item 1 of standard_2_extension is "." then
logMe("EXTENSION TYPE: Finder Short", 4)
set my_extension to standard_2_extension
else
--no extension
logMe("EXTENSION TYPE: none", 4)
set my_extension to "none"
end if
end if
end if
end if
end if
logMe("extensionFinder Handler Finished", 3)
return my_extension as string
end extensionFinder
--
-- Uses GREP to look into file looking for header string to identify file
--
on grepForString(path_to_fix, search_list)
logMe("grepForString Handler Called", 3)
repeat with i from 1 to count of items of search_list
set current_item to item i of search_list
logMe("current_item: " & current_item, 4)
try
set grep_result to grepMe(path_to_fix, current_item)
logMe("¢ Matches found = " & grep_result, 4)
exit repeat
on error
set grep_result to 0
logMe("¢ Matches found = " & grep_result, 4)
end try
end repeat
logMe("grepForString Handler Finished", 3)
return {grep_result, current_item}
end grepForString
--
-- Uses GREP to parse a single instance for grepForString
--
-- Sub-handling this gets around AppleScript problem when GREP returns zero
--
on grepMe(path_to_fix, search_item)
set path_to_fix_POSIX to POSIX path of path_to_fix
set shell_string to ("grep -ch \"" & search_item & "\" " & quoted form of path_to_fix_POSIX)
return (do shell script shell_string)
end grepMe
--
-- what kind of file is it?
--
on fileDetective(path_to_fix)
logMe("---", 1)
logMe("fileDetective Handler Called", 1)
set file_type to "" as text
set file_creator to "" as text
set need_preivew to "" as text
set my_extension to extensionFinder(path_to_fix)
--
--START DETECTIVE WORK
--
--is it a native Illustrator file? (including DAM System-added ".eps" extensions)
fileProgressUpdate(path_to_fix, "File type & creator check: Native Illustrator", 0.0)
if (file_type is "") and (file_creator is "") then
logMe("Native Illustrator check invoked", 2)
set valid_extensions to g_extensions_native_illustrator
if (my_extension is in valid_extensions) then
--Illustrator EPS files have additional header info that should NOT be in native files
set invalid_headers to g_headers_other_illustrator
set header_scan_invalid to grepForString(path_to_fix, invalid_headers)
set header_grep_count to item 1 of header_scan_invalid
set header_grep_string to item 2 of header_scan_invalid
if header_grep_count is 0 then
--EPSF header information not found, might be native Illustrator
set valid_headers to g_headers_native_illustrator
set header_scan to grepForString(path_to_fix, valid_headers)
set header_grep_count to item 1 of header_scan
set header_grep_string to item 2 of header_scan
if header_grep_count is not 0 then
if header_grep_string = "Creator: Adobe Illustrator(R) 8" then
logMe("¢ Illustrator 8 file detected", 2)
set file_type to "TEXT"
else
logMe("¢ Illustrator 9+ (9, 10, CS1/10, CS2/11) file detected", 2)
set file_type to "PDF "
end if
set file_creator to "ART5"
set need_preview to "no"
else
logMe("¢ Native Illustrator check invalid (string not found)", 2)
end if
else
logMe("¢ Native Illustrator check invalid (EPS header info found)", 2)
end if
else
logMe("¢ Native Illustrator check invalid (extension failed)", 2)
end if
end if
--is it an Illustrator EPS file?
fileProgressUpdate(path_to_fix, "File type & creator check: Illustrator EPS", 0.0)
if (file_type is "") and (file_creator is "") then
logMe("Illustrator EPS check invoked", 2)
set valid_extensions to g_extensions_other_illustrator
if (my_extension is in valid_extensions) then
set valid_headers to g_headers_other_illustrator
set header_scan to grepForString(path_to_fix, valid_headers)
set header_grep_count to item 1 of header_scan
set header_grep_string to item 2 of header_scan
if header_grep_count is not 0 then
logMe("¢ Might be Illustrator EPS file...checking headers again", 2)
set valid_headers to g_headers_native_illustrator
set header_scan to grepForString(path_to_fix, valid_headers)
set header_grep_count to item 1 of header_scan
set header_grep_string to item 2 of header_scan
if header_grep_count is not 0 then
logMe("¢ Illustrator EPS file detected (3.2, 8, 9, 10, CS1/10, CS2/11)", 2)
set file_type to "EPSF"
set file_creator to "ART5"
set need_preview to "no"
else
logMe("¢ Illustrator EPS check invalid (Illustrator string not found)", 2)
end if
else
logMe("¢ Illustrator EPS check invalid (EPS string not found)", 2)
end if
else
logMe("¢ Illustrator EPS check invalid (extension failed)", 2)
end if
end if
--is it a FreeHand EPS document?
fileProgressUpdate(path_to_fix, "File type & creator check: FreeHand EPS", 0.0)
if (file_type is "") and (file_creator is "") then
logMe("FreeHand EPS check invoked", 2)
set valid_extensions to g_extensions_freehand_eps
if (my_extension is in valid_extensions) then
set valid_headers to g_headers_freehand_eps
set header_scan to grepForString(path_to_fix, valid_headers)
set header_grep_count to item 1 of header_scan
set header_grep_string to item 2 of header_scan
if header_grep_count is not 0 then
if header_grep_string is "Creator: FreeHand 8" then
logMe("¢ FreeHand 8 EPS file detected", 2)
set file_type to "EPSF"
set file_creator to "FH80"
set need_preview to "no"
else
if header_grep_string is "Creator: FreeHand 7" then
logMe("¢ FreeHand 7 EPS file detected", 2)
set file_type to "EPSF"
set file_creator to "FH70"
set need_preview to "no"
else
if header_grep_string is "Creator: FreeHand MX 11" then
logMe("¢ FreeHand MX/11 EPS file detected", 2)
set file_type to "EPSF"
set file_creator to "FH11"
set need_preview to "no"
end if
end if
end if
else
logMe("¢ FreeHand EPS check invalid (string not found)", 2)
end if
else
logMe("¢ FreeHand EPS check invalid (extension failed)", 2)
end if
end if
--is it a bitmapped EPS (or DCS) document (default to Photoshop)?
fileProgressUpdate(path_to_fix, "File type & creator check: Photoshop EPS/DCS", 0.0)
if (file_type is "") and (file_creator is "") then
logMe("Photoshop EPS/DCS check invoked", 2)
set valid_extensions to g_extensions_photoshop_eps
if (my_extension is in valid_extensions) then
set valid_headers to g_headers_photoshop_eps
set header_scan to grepForString(path_to_fix, valid_headers)
set header_grep_count to item 1 of header_scan
set header_grep_string to item 2 of header_scan
if header_grep_count is not 0 then
logMe("¢ Photoshop EPS file detected", 2)
set file_type to "EPSF"
set file_creator to "8BIM"
set need_preview to "yes"
else
logMe("¢ Photoshop EPS/DCS check invalid (string not found)", 2)
end if
else
logMe("¢ Photoshop EPS/DCS check invalid (extension failed)", 2)
end if
end if
--is it a Photoshop PSD document?
fileProgressUpdate(path_to_fix, "File type & creator check: Photoshop PSD", 0.0)
if (file_type is "") and (file_creator is "") then
logMe("Photoshop PSD check invoked", 2)
set valid_extensions to g_extensions_photoshop_psd
if (my_extension is in valid_extensions) then
set valid_headers to g_headers_photoshop_psd
set header_scan to grepForString(path_to_fix, valid_headers)
set header_grep_count to item 1 of header_scan
set header_grep_string to item 2 of header_scan
if header_grep_count is not 0 then
logMe("¢ Photoshop PSD file detected", 2)
set file_type to "8BPS"
set file_creator to "8BIM"
set need_preview to "yes"
else
logMe("¢ Photoshop PSD check invalid (string not found)", 2)
end if
else
logMe("¢ Photoshop PSD check invalid (extension failed)", 2)
end if
end if
--is it a Photoshop TIF document?
fileProgressUpdate(path_to_fix, "File type & creator check: Photoshop TIFF", 0.0)
if (file_type is "") and (file_creator is "") then
logMe("Photoshop TIF check invoked", 2)
set valid_extensions to g_extensions_photoshop_tif
if (my_extension is in valid_extensions) then
set valid_headers to g_headers_photoshop_tif
set header_scan to grepForString(path_to_fix, valid_headers)
set header_grep_count to item 1 of header_scan
set header_grep_string to item 2 of header_scan
if header_grep_count is not 0 then
logMe("¢ Photoshop TIF file detected", 2)
set file_type to "TIFF"
set file_creator to "8BIM"
set need_preview to "yes"
else
logMe("¢ Photoshop TIF check invalid (string not found)", 2)
end if
else
logMe("¢ Photoshop TIF check invalid (extension failed)", 2)
end if
end if
--is it a JPEG document (default to Photoshop)?
fileProgressUpdate(path_to_fix, "File type & creator check: Photoshop JPEG", 0.0)
if (file_type is "") and (file_creator is "") then
logMe("Photoshop JPG check invoked", 2)
set valid_extensions to g_extensions_photoshop_jpg
if (my_extension is in valid_extensions) then
set valid_headers to g_headers_photoshop_jpg
set header_scan to grepForString(path_to_fix, valid_headers)
set header_grep_count to item 1 of header_scan
set header_grep_string to item 2 of header_scan
if header_grep_count is not 0 then
logMe("¢ Photoshop JPG file detected", 2)
set file_type to "JPEG"
set file_creator to "8BIM"
set need_preview to "yes"
else
logMe("¢ Photoshop JPG check invalid (string not found)", 2)
end if
else
logMe("¢ Photoshop JPG check invalid (extension failed)", 2)
end if
end if
--is it a PNG document (default to Photoshop)?
fileProgressUpdate(path_to_fix, "File type & creator check: Photoshop PNG", 0.0)
if (file_type is "") and (file_creator is "") then
logMe("Photoshop PNG check invoked", 2)
set valid_extensions to g_extensions_photoshop_png
if my_extension is in valid_extensions then
logMe("¢ Photoshop PNG file detected", 2)
set file_type to "PNGf"
set file_creator to "8BIM"
set need_preview to "yes"
else
logMe("¢ Photoshop PNG check invalid (extension failed)", 2)
end if
end if
--Is it a GIF document (default to Photoshop)?
fileProgressUpdate(path_to_fix, "File type & creator check: Photoshop GIF", 0.0)
if (file_type is "") and (file_creator is "") then
logMe("Photoshop GIF check invoked", 2)
set valid_extensions to g_extensions_photoshop_gif
if my_extension is in valid_extensions then
logMe("¢ Photoshop GIF file detected", 2)
set file_type to "GIFf"
set file_creator to "8BIM"
set need_preview to "yes"
else
logMe("¢ Photoshop GIF check invalid (extension failed)", 2)
end if
end if
--is it a QuarkXpress document?
fileProgressUpdate(path_to_fix, "File type & creator check: QuarkXpress", 0.0)
if (file_type is "") and (file_creator is "") then
logMe("QuarkXPress check invoked", 2)
set valid_extensions to g_extensions_quark
if my_extension is in valid_extensions then
set valid_headers to g_headers_quark
set header_scan to grepForString(path_to_fix, valid_headers)
set header_grep_count to item 1 of header_scan
set header_grep_string to item 2 of header_scan
if (header_grep_count is 0) and (my_extension is in {".qxd", ".qxp"}) then
logMe("¢ Quark file detected (4.11 or 7?)", 2)
set file_type to ""
set file_creator to "XPR3"
set need_preview to "no"
else
if header_grep_count > "0" then
if header_grep_string is "QXP__5" then
logMe("¢ Quark 5 file detected", 2)
set file_type to "XDOC"
set file_creator to "XPR3"
set need_preview to "no"
else
if header_grep_string is "QXPPP6" then
logMe("¢ Quark 6.5 file detected", 2)
set file_type to "XPRJ"
set file_creator to "XPR3"
set need_preview to "no"
end if
end if
else
logMe("¢ QuarkXPress check invalid (string not found)", 2)
end if
end if
else
logMe("¢ QuarkXPress check invalid (extension failed)", 2)
end if
end if
--is it an InDesign document?
fileProgressUpdate(path_to_fix, "File type & creator check: InDesign", 0.0)
if (file_type is "") and (file_creator is "") then
logMe("InDesign check invoked", 2)
set valid_extensions to g_extensions_indesign
if my_extension is in valid_extensions then
set valid_headers to g_headers_indesign
set header_scan to grepForString(path_to_fix, valid_headers)
set header_grep_count to item 1 of header_scan
set header_grep_string to item 2 of header_scan
if (header_grep_count > 0) then
if header_grep_string = "CreatorTool>Adobe InDesign 3" then
logMe("¢ InDesign CS1 (3) file detected", 2)
set file_type to "IDd3"
set file_creator to "InDn"
set need_preview to "no"
else
if header_grep_string = "CreatorTool>Adobe InDesign 4" then
logMe("¢ InDesign CS2 (4) file detected", 2)
set file_type to "IDd4"
set file_creator to "InDn"
set need_preview to "no"
else
if (header_grep_string = "Adobe InDesign") then
logMe("¢ InDesign 2 file detected", 2)
set file_type to "InDd"
set file_creator to "InDn"
set need_preview to "no"
end if
end if
end if
else
logMe("¢ InDesign check invalid (string not found)", 2)
end if
else
logMe("¢ InDesign check invalid (extension failed)", 2)
end if
end if
--is it a PDF document?
fileProgressUpdate(path_to_fix, "File type & creator check: PDF", 0.0)
if (file_type is "") and (file_creator is "") then
logMe("PDF check invoked", 2)
set valid_extensions to g_extensions_acrobat
if my_extension is in valid_extensions then
set valid_headers to g_headers_acrobat
set header_scan to grepForString(path_to_fix, valid_headers)
set header_grep_count to item 1 of header_scan
set header_grep_string to item 2 of header_scan
if (header_grep_count > 0) then
logMe("¢ Acrobat/PDF file detected (1.3-1.6)", 2)
set file_type to "PDF " -- don't forget the trailing space, file types MUST be 4 characters
set file_creator to "CARO"
set need_preview to "no"
else
logMe("¢ PDF check invalid (string not found)", 2)
end if
else
logMe("¢ PDF check invalid (extension failed)", 2)
end if
end if
--is it a FreeHand document?
fileProgressUpdate(path_to_fix, "File type & creator check: Native FreeHand", 0.0)
if (file_type is "") and (file_creator is "") then
logMe("Native FreeHand check invoked", 2)
set valid_extensions to g_extensions_freehand
if my_extension is in valid_extensions then
set valid_headers to g_headers_freehand
set header_scan to grepForString(path_to_fix, valid_headers)
set header_grep_count to item 1 of header_scan
set header_grep_string to item 2 of header_scan
if (header_grep_count > 0) then
--some FreeHand files can only be detected via extension
if my_extension is in {".fh3", ".fh4", ".fh9"} then
if my_extension is ".fh3" then
logMe("¢ Native FreeHand 3 file detected)", 2)
set file_type to "FHD3"
set file_creator to "FHA3"
set need_preview to "no"
else
if my_extension is ".fh4" then
logMe("¢ Native FreeHand 4 file detected)", 2)
set file_type to "AGD1"
set file_creator to "FH40"
set need_preview to "no"
else
if my_extension is ".fh9" then
logMe("¢ Native FreeHand 9 file detected)", 2)
set file_type to "AGD4"
set file_creator to "FH90"
set need_preview to "no"
end if
end if
end if
else
--some FreeHand files can be detected by extension or string match
if (my_extension is ".fh5") or (header_grep_string is "AGD1") then
logMe("¢ Native FreeHand 5 file detected)", 2)
set file_type to "AGD1"
set file_creator to "FH50"
set need_preview to "no"
else
--FreeHand 8 routine must come before FreeHand 7 to avoid some false positives
if (my_extension is ".fh8") or (header_grep_string is "AGD3") then
logMe("¢ Native FreeHand 8 file detected)", 2)
set file_type to "AGD3"
set file_creator to "FH80"
set need_preview to "no"
else
if (my_extension is ".fh7") or (header_grep_string is "AGD2") then
logMe("¢ Native FreeHand 7 file detected)", 2)
set file_type to "AGD2"
set file_creator to "FH70"
set need_preview to "no"
else
if (my_extension is ".fh10") or (header_grep_string is "FreeHand10") then
logMe("¢ Native FreeHand 10 file detected)", 2)
set file_type to "AGD5"
set file_creator to "FH X"
set need_preview to "no"
else
if (my_extension is ".fh11") or (header_grep_string is "FreeHand11") then
logMe("¢ Native FreeHand 11 file detected)", 2)
set file_type to "AGD6"
set file_creator to "FH11"
set need_preview to "no"
end if
end if
end if
end if
end if
end if
else
logMe("¢ Native FreeHand check invalid (string not found)", 2)
end if
else
logMe("¢ Native FreeHand check invalid (extension failed)", 2)
end if
set valid_extensions to g_extensions_freehand
end if
--is it a PageMaker document?
fileProgressUpdate(path_to_fix, "File type & creator check: PageMaker", 0.0)
if (file_type is "") and (file_creator is "") then
logMe("PageMaker check invoked", 2)
set valid_extensions to g_extensions_pagemaker
if my_extension is in valid_extensions then
if my_extension is ".pm5" then
logMe("¢ PageMaker 5 file detected", 2)
set file_type to "ALB5"
set file_creator to "ALD5"
set need_preview to "no"
else
if my_extension is ".pm6" then
logMe("¢ PageMaker 6.0 file detected", 2)
set file_type to "ALB6"
set file_creator to "ALD6"
set need_preview to "no"
else
if my_extension is ".p65" then
logMe("¢ PageMaker 6.5 file detected", 2)
set file_type to "AB65"
set file_creator to "AD65"
set need_preview to "no"
end if
end if
end if
else
logMe("¢ PageMaker check invalid (extension failed)", 2)
end if
end if
--have all checks failed?
if (file_type is "") and (file_creator is "") then
logMe("ERROR", 2)
logMe("¢ File type and creator not recognized", 2)
set file_type to "error"
set file_creator to "error"
set need_preview to "no"
end if
--
--END DETECTIVE WORK
--
logMe("---", 2)
logMe("FILE TYPE: " & file_type & " ¢ FILE CREATOR: " & file_creator & " ¢ NEED PREVIEW?: " & need_preview, 2)
logMe("fileDetective Handler Finished", 1)
logMe("---", 1)
return {file_type, file_creator, need_preview}
end fileDetective
--
-- FILE REPAIR HANDLERS
--
--
-- Fixes file type and creator
--
on tcRepair(path_to_fix, file_info)
logMe("---", 1)
logMe("tcRepair Handler Called", 1)
set file_type to item 1 of file_info
set file_creator to item 2 of file_info
if (file_type is not "error") or (file_creator is not "error") then
tell application "Finder"
set file type of path_to_fix to file_type as text
set creator type of path_to_fix to file_creator as text
--remove red file label to show something was done
set label index of path_to_fix to "0" as text
end tell
finderCommenter(path_to_fix, "¢ File Type and Creator Type repaired.")
else
logMe("---", 2)
logMe("File Type or File Creator was not available", 2)
logMe("¢ No changes were made", 2)
end if
logMe("tcRepair Handler Finished", 1)
logMe("---", 1)
end tcRepair
--
-- Fixes file names, specifically
--
--
on nameRepair(path_to_fix)
logMe("---", 1)
logMe("nameRepair Handler Called", 1)
--initialize check variables
set my_extension to extensionFinder(path_to_fix)
logMe("my_extension = " & my_extension, 2)
set extension_length to count of text items of my_extension
logMe("extension_length = " & extension_length, 2)
tell application "Finder"
set current_name to name of path_to_fix
set name_length to length of current_name as number
end tell
set rename_me to "no"
--
--START CHECKS
--
--is it an _lr/_hr extension from the old naming stanards
--with an "extra" extension added by DAM System?
if rename_me = "no" then
logMe("Checking for _lr/_hr + DAM System style extension", 2)
if (extension_length = 7) or (extension_length = 11) then
set need_fixing to lrhrParse("long", path_to_fix)
if need_fixing is not in {"too short", "<invalid>"} then
logMe("DAM System added an extension to this _lr/_hr file", 2)
set new_name to (text items 1 thru (name_length - 4)) of current_name as string
set rename_me to "yes"
else
logMe("Checking for _lr/_hr + DAM System style extension: invalid long extension", 2)
end if
else
logMe("Checking for _lr/_hr + DAM System style extension: wrong length", 2)
end if
end if
--is it EPS extension that should be AI?
if rename_me = "no" then
logMe("Checking for EPS extension that should be AI", 2)
if my_extension is ".eps" then
logMe("EPS file found", 2)
set invalid_headers to g_headers_other_illustrator
set header_scan_invalid to grepForString(path_to_fix, invalid_headers)
set header_grep_count to item 1 of header_scan_invalid
if header_grep_count is 0 then
logMe("EPS file is really an AI file", 2)
set base_name to (text items 1 thru (name_length - 4)) of current_name as string --remove "eps"
set new_name to base_name & ".ai" --use standard ".ai" extension
set rename_me to "yes"
else
logMe("This is a valid EPS file", 2)
end if
else
logMe("This is not a mislabeled EPS file", 2)
end if
end if
--is it no extension, maybe Illustrator?
if rename_me = "no" then
logMe("Checking for no extension that could be AI", 2)
if my_extension is "none" then
logMe("¢ File has no extension", 2)
set invalid_headers to g_headers_other_illustrator
set header_scan_invalid to grepForString(path_to_fix, invalid_headers)
set header_grep_count to item 1 of header_scan_invalid
if header_grep_count is 0 then
set valid_headers to g_headers_native_illustrator
set header_scan_valid to grepForString(path_to_fix, valid_headers)
set header_grep_count to item 1 of header_scan_valid
if header_grep_count > 0 then
logMe("File is a native Illustrator file", 2)
set new_name to current_name & ".ai" --use standard ".ai" extension
set rename_me to "yes"
else
logMe("I'm not an Illustrator file", 2)
end if
else
logMe("I'm not sure, but I may be an EPS file", 2)
end if
else
logMe("I've got a valid extension already", 2)
end if
end if
--is it no extension, maybe InDesign?
if rename_me = "no" then
logMe("Checking for no extension that could be INDD", 2)
if my_extension is "none" then
logMe("¢ File has no extension", 2)
set valid_headers to g_headers_indesign
set header_scan_valid to grepForString(path_to_fix, valid_headers)
set header_grep_count to item 1 of header_scan_valid
if header_grep_count > 0 then
logMe("¢ File is an InDesign file", 2)
set new_name to current_name & ".indd" --use standard ".indd" extension
set rename_me to "yes"
else
logMe("I'm not an InDesign file", 2)
end if
else
logMe("I've got a valid extension already", 2)
end if
end if
--
--END CHECKS
--
--were any changes made?
if rename_me = "yes" then
logMe("---", 2)
logMe("Old file name = " & current_name, 2)
finderCommenter(path_to_fix, "¢ File name repaired.")
tell application "Finder"
--rename file
set name of path_to_fix to new_name as text
--remove red file label to show something was done
set label index of path_to_fix to "0" as text
end tell
logMe("NEW file name = " & new_name, 2)
else
logMe("---", 2)
logMe("No file name changes were made.", 2)
end if
logMe("nameRepair Handler Finished", 1)
logMe("---", 1)
return path_to_fix
end nameRepair
--
-- PHOTOSHOP AUTOMATION
--
on restorePreview(path_to_fix, file_info)
logMe("---", 1)
logMe("restorePreview Handler Called", 1)
--does file need repair?
set need_preview to item 3 of file_info
set file_type to item 1 of file_info
set unable_to_preview to {"GIFf"}
--define location of external JavaScript
set path_to_desktop to (path to desktop) as text
set path_to_javascript to (path_to_desktop & "Create_Preview.js")
if (need_preview = "yes") and (file_type is not in unable_to_preview) then
logMe("¢ File needs Photoshop to restore it's preview image", 1)
finderCommenter(path_to_fix, "¢ Photoshop preview restored.")
--remove red file label to show something was done
tell application "Finder"
set label index of path_to_fix to "0" as text
end tell
--locate JavaScript for Photoshop (FaceSpan, Mac OS X 10.3 or earlier)
set where_is_this_app to path to me
set package_contents to "Contents:Resources:Create_Preview.js"
set script_location to (where_is_this_app & package_contents) as string
tell application "Adobe Photoshop CS2"
open (path_to_fix as alias)
--execute JavaScript control of Photoshop
--acquired with ScriptingListener plugin per Adobe guidelines
do javascript (script_location as alias)
end tell
else
--This seems like an odd place to trap for this, but some files
--are Photoshop, but mislabeled (such as PSDs with EPS extensions).
--In such cases, we need to re-label the file red to indicate an issue,
--despite the file being renamed. Since this routine runs last, easiest
--to catch it here
if (item 1 of file_info = "error") or (item 2 of file_info = "error") then
tell application "Finder"
set label index of path_to_fix to "2" as text
end tell
end if
logMe("¢ File does not need a restored preview image", 1)
end if
logMe("restorePreview Handler Finished", 1)
logMe("---", 1)
end restorePreview
on open actionItems
--initilaize debugging?
set g_debug to "false"
--initialize other variables
tell current application
set cfr_version to version
end tell
loadLists()
--initialize progress window
set string value of text field "textProcessingTotal" of window "main" to "Examining & preparing files..."
set string value of text field "textFilenameOperation" of window "main" to ""
set contents of progress indicator "progressTotal" of window "main" to 0
set contents of progress indicator "progressFile" of window "main" to 0
open window "main"
--start main script
logMe("--------------------------------------------------", 0)
logMe("CompanyName File Repair Started", 0)
logMe("Debugging Mode = " & g_debug, 0)
logMe("--------------------------------------------------", 0)
--convert UNIX paths "in place" to alias for FaceSpan
repeat with an_item in actionItems
set contents of an_item to alias (POSIX file an_item)
end repeat
--if there are subfolders, add their aliases to actionItems
logMe("Discerning files and subfolders...", 0)
repeat with i from 1 to count of items of actionItems
set current_path to item i of actionItems
if folderFinder(current_path) is "yes" then
logMe("¢ Pulling subfolder information...", 0)
tell application "Finder"
try
set subfolder_list to files of current_path's entire contents as alias list
on error
set subfolder_list to {first file of current_path's entire contents as alias}
end try
end tell
set actionItems to actionItems & subfolder_list
end if
end repeat
--mark all files red first, so it's visually obvious what files got touched during the script
repeat with i from 1 to count of items of actionItems
if folderFinder(item i of actionItems) is "no" then
set current_path to item i of actionItems
tell application "Finder"
set label index of current_path to "2"
end tell
finderCommenter(current_path, "Scanned by CompanyName File Fixer v" & cfr_version & " on " & dateStamp())
end if
end repeat
logMe("---", 0)
logMe("Begining main repeat loop...", 0)
logMe("---", 0)
set actionItem_count to count of items of actionItems
-- setup main loop progress indicator
tell window "main"
tell progress indicator "progressTotal"
set minimum value to 0
set maximum value to actionItem_count + 1
set contents to 0.1
set indeterminate to false
end tell
end tell
repeat with i from 1 to actionItem_count
set current_actionItem to item i of actionItems
--update progress indicator
set string value of text field "textProcessingTotal" of window "main" to ("Processing files: " & i & " of " & actionItem_count)
set contents of progress indicator "progressTotal" of window "main" to i
delay 1.0
-- initialize file progress indicator
tell window "main"
tell progress indicator "progressFile"
set minimum value to 0
set maximum value to 5.1
set contents to 0.1
set indeterminate to false
end tell
delay 1.0
end tell
if folderFinder(current_actionItem) is "no" then
--which file am I repairing?
set path_to_fix to item i of actionItems
tell application "Finder"
set name_to_fix to name of path_to_fix as string
end tell
logMe("Current File Being Fixed, name_to_fix = ", 0)
logMe(name_to_fix, 0)
--what kind of file is it?
fileProgressUpdate(path_to_fix, "Determining file type & creator", 1)
set file_info to fileDetective(path_to_fix)
--repair file type and creator
fileProgressUpdate(path_to_fix, "Repairing file type & creator", 1)
tcRepair(path_to_fix, file_info)
--repair file name, update reference
fileProgressUpdate(path_to_fix, "Repairing file name", 1)
set path_to_fix to nameRepair(path_to_fix)
--restore preview image if needed
fileProgressUpdate(path_to_fix, "Fix Photoshop preview if needed", 1)
restorePreview(path_to_fix, file_info)
--finish progress bar
set contents of progress indicator "progressFile" of window "main" to 5.1
logMe("--------------------------------------------------", 0)
else
set string value of text field "textFilenameOperation" of window "main" to ("(this is a folder path ¢ skipped)")
set contents of progress indicator "progressFile" of window "main" to 5.1
end if
end repeat
--update progress indicators
set string value of text field "textProcessingTotal" of window "main" to ("Processing files: COMPLETE")
set contents of progress indicator "progressTotal" of window "main" to actionItem_count + 1
set string value of text field "textFilenameOperation" of window "main" to ("File: COMPLETE ¢ Status: COMPLETE")
set contents of progress indicator "progressFile" of window "main" to 5.1
delay 2.5
tell window "main"
stop progress indicator "progressTotal"
stop progress indicator "progressFile"
--work around a bug where progress indicators don't always redraw
set visible of progress indicator "progressTotal" to true
set visible of progress indicator "progressFile" to true
end tell
logMe("CompanyName File Repair Finished", 0)
logMe("--------------------------------------------------", 0)
quit
end open
-- --------------------------------------------------------------------
-- FACESPAN DEFAULT for drag-n-drop template
-- --------------------------------------------------------------------
(*
on will close theObject
set windowOpen to false
end will close
*)
-- --------------------------------------------------------------------
JAVASCRIPT CODE:
Needed for the Adobe Photoshop preview-restoring handler.
// =======================================================
var id20 = charIDToTypeID( "Mk " );
var desc3 = new ActionDescriptor();
var id21 = charIDToTypeID( “null” );
var ref1 = new ActionReference();
var id22 = charIDToTypeID( "Lyr " );
ref1.putClass( id22 );
desc3.putReference( id21, ref1 );
var id23 = charIDToTypeID( “Usng” );
var desc4 = new ActionDescriptor();
var id24 = charIDToTypeID( "Nm " );
desc4.putString( id24, “SCRIPT_TEMP” );
var id25 = charIDToTypeID( "Lyr " );
desc3.putObject( id23, id25, desc4 );
executeAction( id20, desc3, DialogModes.NO );
// =======================================================
var id26 = charIDToTypeID( "Dlt " );
var desc5 = new ActionDescriptor();
var id27 = charIDToTypeID( “null” );
var ref2 = new ActionReference();
var id28 = charIDToTypeID( "Lyr " );
var id29 = charIDToTypeID( “Ordn” );
var id30 = charIDToTypeID( “Trgt” );
ref2.putEnumerated( id28, id29, id30 );
desc5.putReference( id27, ref2 );
executeAction( id26, desc5, DialogModes.NO );
// =======================================================
var id31 = charIDToTypeID( “save” );
executeAction( id31, undefined, DialogModes.NO );
// =======================================================
var id32 = charIDToTypeID( "Cls " );
executeAction( id32, undefined, DialogModes.NO );