Skip to content

Instantly share code, notes, and snippets.

@n8henrie
Last active Aug 29, 2015
Embed
What would you like to do?
Quick script to undo all my hard-earned URL quoting in LCP scripts, which have stopped working after LCP 2.3.1
#! /usr/bin/env python3
'''lcp_unquote.py
Takes a Launch Center Pro .lcpbackup file as an argument and
unencodes all the URL encoded stuff, possibly making it more readable,
and much of which is probably unnecessary after LCP 2.3.1.
Details: http://n8h.me/1meUxTi
'''
import re
import urllib.parse
import sys
import subprocess
import os
import shutil
import time
if len(sys.argv) == 1:
print("Don't forget to include the file you're trying to convert....")
sys.exit(0)
infile = sys.argv[1]
outfile = '{}_out.lcpbackup'.format(str(int(time.time())))
unquote_list = [ '{', '}', '[', ']', '%', ':', '/', '?', '=' ]
def ask(writefile):
'''Function to make sure any files that will be created won't be overwriting anything without permission.'''
while True:
answer = input("Looks like {} already exists, possibly leftover form a prior run. Okay to overwrite? Y/N: ".format(writefile))
if answer in ['Y', 'y']:
break
elif answer in ['N', 'n']:
print("Edit lcp_unquote.py if you want to change the default output or tmpfile filename. Exiting.")
sys.exit(0)
else:
print("Bad input. Try again.")
def convert(my_format):
'''Converts outfile between xml and binary formats with plutil.'''
args = ['plutil', '-convert', my_format, outfile]
subprocess.call(args)
def main():
# Include other files in the list below if they will be created and could possibly overwrite something important.
for my_file in [outfile]:
if os.path.isfile(my_file):
ask(my_file)
# Copy the infile to make sure not to modify or change it.
shutil.copy2(infile, outfile)
convert('xml1')
with open(outfile) as r:
lines = r.readlines()
# encoded_regex = re.compile(r'%[A-Z0-9]{2}')
unquote_me = [urllib.parse.quote(each, safe = '') for each in unquote_list]
found = True
while found:
# Only continue the loop if at least one match sets found back to True
found = False
for index, line in enumerate(lines):
# The lines containing the URLs are 2 lines below a predictable pattern,
# and only need editing if they have one of the URL encoded characters we
# have chosen to replace.
if all([
re.search(r'<string>x-coredata://', lines[index - 2]),
re.search(r'/LaunchAction/', lines[index - 2]),
any(x in line for x in unquote_me)
]):
found = True
for each in unquote_me:
lines[index] = re.sub(each, urllib.parse.unquote(each), lines[index])
# `&` breaks the plist format rules, so its URL encoded form needs to be
# substituted with its HTML encoded form instead
lines[index] = re.sub('%26', '&amp;', lines[index])
with open(outfile, 'w') as w:
w.writelines(lines)
convert('binary1')
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment