2012
05.30
05.30
Ever wondered what’s the deal with *.xsiaddon files? What are they?
Well, they’re good ol’ XML with a bit of metadata and the files embedded in them are compressed with the zlib library and base64 encoded for safe plaintext storage.
How would we parse such a file? Check this out:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
import os import zlib import base64 import xml.etree.ElementTree as ET from pprint import pprint as pp tmpDir = os.environ['TMP'] xsiaddonPath = r'C:\path\to\something.xsiaddon' tree = ET.parse(xsiaddonPath) # Load file # Get the root element ('xsi_file') root = tree.getroot() addonInfo = { 'version': root.find('AddonVersion').text, 'title': root.find('Title').text, 'author': root.find('AuthorName').text, 'email': root.find('AuthorEMail').text, 'url': root.find('URL').text, 'desc': root.find('Description').text, 'usage': root.find('Usage').text, 'installDirName': root.find('InstallDir').text, 'madeInVersion': root.attrib['xsi_version'] } pp(addonInfo) # pretty print :) # Now let's loop through all the files embedded in it: addonFiles = root.findall('AddonItem') for item in addonFiles: fileName = item.attrib['filename'] relativeExtractionPath = item.attrib.setdefault('destination','\\') fileCategory = item.attrib['type'] # SPDLs, Others, etc. # XSIADDON ATTACHMENTS ARE BASE64-ENCODED STRINGS # OF ZLIB-COMPRESSED DATA, but ONLY AFTER THE 12TH BYTE. # # In Halfdan's own words: # "They're compressed using zlib but they don't have the # gzip headers. The compression starts at the 12th byte. # The first 12 bytes contain a textural representation # of the size (+pad)." # decoded = base64.b64decode(item.text) data = zlib.decompress( decoded[12:] ) fileInfo = { 'filename': fileName, 'filesize': len(data), 'extractTo': relativeExtractionPath, 'category': fileCategory, } pp(fileInfo) # For demonstration sake, invent a temporary filepath: filePath = os.path.normpath(tmpDir+'\\'+fileName) # Write our file to disk: f = open(filePath, 'wb') f.write(data) f.close() print "Extracted %s to: %s" % (fileName, filePath) print ( "Gee wiz, %s! That xsiaddon had %s file(s). --> %s" % (os.environ['USERNAME'], len(addonFiles), xsiaddonPath) ) # Mission accomplished. |
Easy as that! š
Cool script! The only problem with this technique is that it loses the directory structure in the process.