I have a python 2.7.10 script that takes a user's input and inserts it into the name
and body
parameter of the make new note
AppleScript.
The problem is that any escape or special characters get interpreted by AppleScript. I want all strings to be treated as raw and to ignore all escape characters and things like :\//tft//
or c:\test\test.txt
without giving me a Expected “"” but found unknown token.
error or ignoring the t
character after the \
The line of python looks like this:
cmd = "osascript -e 'tell application \"Notes\" \n tell account \"iCloud\" \n make new note at folder \"Notes\" with properties {name:\"%s\", body:\"%s\"} \n end tell \n end tell'" % (header, body)
... where header
and body
are the user supplied strings.
But for manual testing I use the Script Editor to quickly reproduce the error.
tell application "Notes"
tell account "iCloud"
make new note at folder "Notes" with properties {name:"myname", body:"c:\test\test.txt"}
end tell
end tell
This particular note ends up looking like this:
I know that I can use \\
instead of \
but I don't want users to have to sanitize all their input as they could be copy pasting from a large body of text. Think of a log file or paste-bin style body of text.
Is there a way to programmatically sanitize the user's input?
NOTE:
This is NOT a duplicate of this question because I've tried replacing the string variable header
and body
with eval(header)
and eval(body)
but that didn't work. I also tried .decode('string_escape')
to no avail. Finally, I tried this with no luck either:
d = header.escape('\w[0-9]')
header = d.decode('string_escape')
I think this has to do with AppleScript's ability to accept this string and not just Python's ability to sanitize it using the above functions.
UPDATE
I am capturing user input using a dialog box with code like this:
cmd = "osascript -e \'set theString to text returned of (display dialog \"Please Enter The Note To Add To Your iCloud Notes \" with icon file \"%s\" default answer \"\n\n\n\" buttons {\"OK\",\"Cancel\"} default button 1) \'" % (appicon_abs_path_apple)
note = run_script(cmd)
In the demo.py
gist below there is a custom sanitize
function which is utilized to escape any backslash (\
) or double quote ("
) character(s) that the user may enter into the dialog box. It's necessary to escape these characters this way in your .py
file prior to subsequently passing them to osascript
.
demo.py
#!/usr/bin/env python
from subprocess import Popen, PIPE
def sanitize(str):
return str.replace("\\", "\\\\") \
.replace("\"", "\\\"")
def run_script(script):
p = Popen(['osascript', '-'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
stdout, stderr = p.communicate(script)
return stdout
appicon_abs_path_apple = "Applications:Stickies.app:Contents:Resources:Stickies.icns"
input_dialog = """
tell application "Finder"
activate
set mssg to "Please Enter The Note To Add To Your iCloud Notes"
set theString to text returned of (display dialog mssg with icon file "%s" \
default answer "\n\n\n" buttons {"OK", "Cancel"} default button 1)
end tell
""" % (appicon_abs_path_apple)
# Notice in the following line we `sanitize` the text characters returned
# from the input dialog before assigning it to the `note` variable.
note = sanitize(run_script(input_dialog))
# -------------------------------
# Let's test that any special characters have been preserved
show_input = """
tell application "Finder"
activate
display dialog "%s"
end tell
""" % (note)
run_script(show_input)
Notes:
The show_input
and run_script(show_input)
parts at the end of demo.py
are for test purposes only. This should be replaced with the AppleScript code necessary to make a new note. For instance:
# ...
# ...
note = sanitize(run_script(input_dialog))
# header = sanitize(header)
make_note = """
tell application "Notes"
tell account "iCloud"
make new note at folder "Notes" with properties {name:"%s", body:"%s"}
end tell
end tell
""" % (header, note)
run_script(make_note)
You'll probably also want to consider passing the text string assigned to the header
variable through the sanitize
function (as per the line currently commented out in snippet above), however I'm unsure from your question where that data comes from. If it's user generated then definitely sanitize
it.
Also note how in the aforementioned gist we wrap the Applescript code in triple double quotes ("""
) - this helps to make the code more readable and avoids the need for additional escaping and \n
character(s), unlike the following:
make_note = "osascript -e 'tell application \"Notes\" \n tell account \"iCloud\" \n make new note at folder \"Notes\" with properties {name:\"%s\", body:\"%s\"} \n end tell \n end tell'" % (header, body)
To test the demo.py
gist above you'll need to:
chmod
command and changing the file path as necessary.chmod +x /some/path/to/demo.py
appicon_abs_path_apple
variable - currently it utilizes the icon for the Stickies application.Input:
The following arbitrary text string containing special characters was entered into the dialog:
:\//tft//
c:\test\test.txt
c:\\quux\\foo.md
'¡"€#¢∞§¶•ª⁄™‹›fifl‡°·
Screenshot (above) showing the input text includes many special characters.
Output:
Screenshot (above) showing that the special characters in the input text have been preserved in the subsequent dialog.