Skip to content

Instantly share code, notes, and snippets.

@ayyybe
Last active August 17, 2025 17:55
Show Gist options
  • Select an option

  • Save ayyybe/a5f01c6f40020f9a7bc4939beeb2df1d to your computer and use it in GitHub Desktop.

Select an option

Save ayyybe/a5f01c6f40020f9a7bc4939beeb2df1d to your computer and use it in GitHub Desktop.

Revisions

  1. ayyybe revised this gist Dec 20, 2021. No changes.
  2. ayyybe revised this gist May 17, 2021. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion ccdl.py
    Original file line number Diff line number Diff line change
    @@ -386,7 +386,7 @@ def get_application_json(buildGuid):
    with Popen(['/usr/bin/osacompile', '-l', 'JavaScript', '-o', os.path.join(dest, install_app_path)], stdin=PIPE) as p:
    p.communicate(INSTALL_APP_APPLE_SCRIPT.encode('utf-8'))

    icon_path = '/Library/Application Support/Adobe/Adobe Desktop Common/HDBox/Install.app/Contents/Resources/app.icns'
    icon_path = '/Library/Application Support/Adobe/Adobe Desktop Common/HDBox/Install.app/Contents/Resources/CreativeCloudInstaller.icns'
    shutil.copyfile(icon_path, os.path.join(install_app_path, 'Contents', 'Resources', 'applet.icns'))

    products_dir = os.path.join(install_app_path, 'Contents', 'Resources', 'products')
  3. ayyybe revised this gist May 17, 2021. No changes.
  4. ayyybe revised this gist Sep 30, 2020. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion ccdl.py
    Original file line number Diff line number Diff line change
    @@ -115,7 +115,7 @@
    cancelButton: 'Cancel'
    })
    const cmd = shellescape([ 'sudo', hyperDrivePath, '--install=1', '--driverXML=' + driverPath ])
    app.displayDialog('Run this command in Terminal to install (press \\'Okay\\' to copy to clipboard)', { defaultAnswer: cmd })
    app.displayDialog('Run this command in Terminal to install (press \\'OK\\' to copy to clipboard)', { defaultAnswer: cmd })
    app.setTheClipboardTo(cmd)
    return
    }
  5. ayyybe revised this gist Sep 30, 2020. 1 changed file with 67 additions and 29 deletions.
    96 changes: 67 additions & 29 deletions ccdl.py
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,10 @@
    #!/usr/bin/env python3

    # CHANGELOG (0.1.2-hotfix1)
    # + updated script to work with new api (newer downloads work now)
    # + added workaround for broken installer on big sur
    # + made everything even more messy and disgusting

    import os
    import json
    import argparse
    @@ -9,8 +15,9 @@
    from collections import OrderedDict
    from subprocess import Popen, PIPE

    VERSION = 3
    VERSION_STR = '0.1.2'
    VERSION = 4
    VERSION_STR = '0.1.2-hotfix1'
    CODE_QUALITY = 'FUCKING_AWFUL'

    INSTALL_APP_APPLE_SCRIPT = '''
    const app = Application.currentApplication()
    @@ -77,8 +84,42 @@
    return false
    }
    function shellescape(a) {
    var ret = [];
    a.forEach(function(s) {
    if (/[^A-Za-z0-9_\\/:=-]/.test(s)) {
    s = "'"+s.replace(/'/g,"'\\\\''")+"'";
    s = s.replace(/^(?:'')+/g, '') // unduplicate single-quote at the beginning
    .replace(/\\\\\'''/g, "\\\\'" ); // remove non-escaped single-quote if there are enclosed between 2 escaped
    }
    ret.push(s);
    });
    return ret.join(' ');
    }
    function run() {
    const appPath = app.pathTo(this).toString()
    //const driverPath = appPath.substring(0, appPath.lastIndexOf('/')) + '/products/driver.xml'
    const driverPath = appPath + '/Contents/Resources/products/driver.xml'
    const hyperDrivePath = '/Library/Application Support/Adobe/Adobe Desktop Common/HDBox/Setup'
    // The JXA Objective-C bridge is completely broken in Big Sur
    if (!$.NSProcessInfo && parseFloat(app.doShellScript('sw_vers -productVersion')) >= 11.0) {
    app.displayAlert('GUI unavailable in Big Sur', {
    message: 'JXA is currently broken in Big Sur.\\nInstall in Terminal instead?',
    buttons: ['Cancel', 'Install in Terminal'],
    defaultButton: 'Install in Terminal',
    cancelButton: 'Cancel'
    })
    const cmd = shellescape([ 'sudo', hyperDrivePath, '--install=1', '--driverXML=' + driverPath ])
    app.displayDialog('Run this command in Terminal to install (press \\'Okay\\' to copy to clipboard)', { defaultAnswer: cmd })
    app.setTheClipboardTo(cmd)
    return
    }
    const args = $.NSProcessInfo.processInfo.arguments
    const argv = []
    const argc = args.count
    @@ -89,11 +130,6 @@
    const installFlag = argv.indexOf('-y') > -1
    const appPath = app.pathTo(this).toString()
    //const driverPath = appPath.substring(0, appPath.lastIndexOf('/')) + '/products/driver.xml'
    const driverPath = appPath + '/Contents/Resources/products/driver.xml'
    const hyperDrivePath = '/Library/Application Support/Adobe/Adobe Desktop Common/HDBox/Setup'
    if (!installFlag) {
    app.displayAlert('Adobe Package Installer', {
    message: 'Start installation now?',
    @@ -140,10 +176,8 @@
    }
    '''

    #ADOBE_PRODUCTS_XML_URL = 'https://prod-rel-ffc-ccm.oobesaas.adobe.com/adobe-ffc-external/core/v4/products/all?_type=xml&channel=ccm,sti&platform=osx10,osx10-64&productType=Desktop'
    POPULATE_ADOBE_COOKIES_URL = 'https://adobeid-na1.services.adobe.com/ims/check/v4/token?client_id=CreativeCloud_v5_1'
    ADOBE_PRODUCTS_XML_URL = 'https://prod-rel-ffc-ccm.oobesaas.adobe.com/adobe-ffc-external/core/v4/products/all?_type=xml&channel=ccm&platform=osx10-64&productType=Desktop'
    ADOBE_APPLICATION_JSON_URL = 'https://prod-rel-ffc-ccm.oobesaas.adobe.com/adobe-ffc-external/core/v2/applications?name={name}&version={version}&platform={platform}'
    ADOBE_PRODUCTS_XML_URL = 'https://cdn-ffc.oobesaas.adobe.com/core/v5/products/all?_type=xml&channel=ccm,sti&platform=osx10,osx10-64&productType=Desktop'
    ADOBE_APPLICATION_JSON_URL = 'https://cdn-ffc.oobesaas.adobe.com/core/v3/applications'

    DRIVER_XML = '''<DriverInfo>
    <ProductInfo>
    @@ -180,8 +214,8 @@ def dl(filename, url):
    with open(filename, 'wb') as f:
    shutil.copyfileobj(r.raw, f)

    def r(url):
    req = session.get(url, headers=ADOBE_REQ_HEADERS)
    def r(url, headers=ADOBE_REQ_HEADERS):
    req = session.get(url, headers=headers)
    req.encoding = 'utf-8'
    return req.text

    @@ -191,14 +225,18 @@ def get_products_xml():
    def parse_products_xml(products_xml):
    cdn = products_xml.find('channel/cdn/secure').text
    products = {}
    parent_map = {c: p for p in products_xml.iter() for c in p}
    for p in products_xml.findall('channel/products/product'):
    displayName = p.find('displayName').text
    sap = p.get('id')
    version = p.get('version')
    dependencies = list(p.find('platforms/platform/languageSet/dependencies'))

    if not products.get(sap):
    if p.find('productInfoPage'):
    print(p.find('productInfoPage').text)
    products[sap] = {
    'hidden': p.find('platforms/platform').get('id') != 'osx10-64' or parent_map[parent_map[p]].get('name') != 'ccm',
    'displayName': displayName,
    'sapCode': sap,
    'versions': OrderedDict()
    @@ -209,16 +247,16 @@ def parse_products_xml(products_xml):
    'version': version,
    'dependencies': [{
    'sapCode': d.find('sapCode').text, 'version': d.find('baseVersion').text
    } for d in dependencies]
    } for d in dependencies],
    'buildGuid': p.find('platforms/platform/languageSet').get('buildGuid')
    }

    return products, cdn

    def get_application_json(sapCode, version):
    try:
    return json.loads(r(ADOBE_APPLICATION_JSON_URL.format(name=sapCode, version=version, platform='osx10-64')))
    except json.decoder.JSONDecodeError:
    return json.loads(r(ADOBE_APPLICATION_JSON_URL.format(name=sapCode, version=version, platform='osx10')))
    def get_application_json(buildGuid):
    headers = ADOBE_REQ_HEADERS.copy()
    headers['x-adobe-build-guid'] = buildGuid
    return json.loads(r(ADOBE_APPLICATION_JSON_URL, headers))


    if __name__ == '__main__':
    @@ -229,25 +267,23 @@ def get_application_json(sapCode, version):
    parser.add_argument('-d', '--destination', help='Directory to download installation files to', action='store')
    args = parser.parse_args()

    ye = int((32 - len(VERSION_STR)) / 2)
    print('=================================')
    print('= Adobe macOS Package Generator =')
    print('============= {} =============\n'.format(VERSION_STR))
    print('{} {} {}\n'.format('='*ye, VERSION_STR, '='*(31-len(VERSION_STR)-ye)))

    if (not os.path.isfile('/Library/Application Support/Adobe/Adobe Desktop Common/HDBox/Setup')):
    print('Adobe HyperDrive installer not found.\nPlease make sure the Creative Cloud app is installed.')
    exit(1)

    print('Populating .adobe.com cookies')
    session.post(POPULATE_ADOBE_COOKIES_URL, headers=ADOBE_REQ_HEADERS)

    print('Downloading products.xml\n')
    products_xml = get_products_xml()

    print('Parsing products.xml')
    products, cdn = parse_products_xml(products_xml)

    print('CDN: ' + cdn)
    print(str(len(products)) + ' products found:')
    print(str(len([p for p in products if not products[p]['hidden']])) + ' products found:')

    sapCode = None
    if (args.sapCode):
    @@ -261,7 +297,8 @@ def get_application_json(sapCode, version):

    if not sapCode:
    for p in products.values():
    print('[{}] {}'.format(p['sapCode'], p['displayName']))
    if not p['hidden']:
    print('[{}] {}'.format(p['sapCode'], p['displayName']))

    while sapCode is None:
    val = input('\nPlease enter the SAP Code of the desired product (eg. PHSP for Photoshop): ')
    @@ -289,7 +326,7 @@ def get_application_json(sapCode, version):
    print('{} {}'.format(product['displayName'], v['version']))

    while version is None:
    val = input('\nPlease enter the desired version (eg. 21.0.3): ')
    val = input('\nPlease enter the desired version (eg. 21.2.3): ')
    if versions.get(val):
    version = val
    else:
    @@ -339,8 +376,9 @@ def get_application_json(sapCode, version):
    print('dest: ' + install_app_path)

    prodInfo = versions[version]
    prods_to_download = [{ 'sapCode': d['sapCode'], 'version': d['version'] } for d in prodInfo['dependencies']]
    prods_to_download.insert(0, { 'sapCode': prodInfo['sapCode'], 'version': prodInfo['version'] })
    prods_to_download = [{ 'sapCode': d['sapCode'], 'version': d['version'], 'buildGuid': products[d['sapCode']]['versions'][d['version']]['buildGuid'] } for d in prodInfo['dependencies']]
    prods_to_download.insert(0, { 'sapCode': prodInfo['sapCode'], 'version': prodInfo['version'], 'buildGuid': prodInfo['buildGuid'] })
    print(prods_to_download)

    print('\nCreating {}'.format(install_app_name))

    @@ -361,7 +399,7 @@ def get_application_json(sapCode, version):
    app_json_path = os.path.join(product_dir, 'application.json')

    print('[{}_{}] Downloading application.json'.format(s, v))
    app_json = get_application_json(s, v)
    app_json = get_application_json(p['buildGuid'])
    p['application_json'] = app_json

    print('[{}_{}] Creating folder for product'.format(s, v))
  6. ayyybe revised this gist Mar 31, 2020. No changes.
  7. ayyybe revised this gist Mar 31, 2020. 1 changed file with 10 additions and 5 deletions.
    15 changes: 10 additions & 5 deletions ccdl.py
    Original file line number Diff line number Diff line change
    @@ -3,13 +3,14 @@
    import json
    import argparse
    import requests
    session = requests.Session()
    import shutil
    from xml.etree import ElementTree as ET
    from collections import OrderedDict
    from subprocess import Popen, PIPE

    VERSION = 2
    VERSION_STR = '0.1.1'
    VERSION = 3
    VERSION_STR = '0.1.2'

    INSTALL_APP_APPLE_SCRIPT = '''
    const app = Application.currentApplication()
    @@ -140,7 +141,8 @@
    '''

    #ADOBE_PRODUCTS_XML_URL = 'https://prod-rel-ffc-ccm.oobesaas.adobe.com/adobe-ffc-external/core/v4/products/all?_type=xml&channel=ccm,sti&platform=osx10,osx10-64&productType=Desktop'
    ADOBE_PRODUCTS_XML_URL = 'https://prod-rel-ffc-ccm.oobesaas.adobe.com/adobe-ffc-external/core/v4/products/all?_type=xml&channel=ccm&platform=osx10,osx10-64&productType=Desktop'
    POPULATE_ADOBE_COOKIES_URL = 'https://adobeid-na1.services.adobe.com/ims/check/v4/token?client_id=CreativeCloud_v5_1'
    ADOBE_PRODUCTS_XML_URL = 'https://prod-rel-ffc-ccm.oobesaas.adobe.com/adobe-ffc-external/core/v4/products/all?_type=xml&channel=ccm&platform=osx10-64&productType=Desktop'
    ADOBE_APPLICATION_JSON_URL = 'https://prod-rel-ffc-ccm.oobesaas.adobe.com/adobe-ffc-external/core/v2/applications?name={name}&version={version}&platform={platform}'

    DRIVER_XML = '''<DriverInfo>
    @@ -174,12 +176,12 @@
    }

    def dl(filename, url):
    with requests.get(url, stream=True, headers=ADOBE_REQ_HEADERS) as r:
    with session.get(url, stream=True, headers=ADOBE_REQ_HEADERS) as r:
    with open(filename, 'wb') as f:
    shutil.copyfileobj(r.raw, f)

    def r(url):
    req = requests.get(url, headers=ADOBE_REQ_HEADERS)
    req = session.get(url, headers=ADOBE_REQ_HEADERS)
    req.encoding = 'utf-8'
    return req.text

    @@ -235,6 +237,9 @@ def get_application_json(sapCode, version):
    print('Adobe HyperDrive installer not found.\nPlease make sure the Creative Cloud app is installed.')
    exit(1)

    print('Populating .adobe.com cookies')
    session.post(POPULATE_ADOBE_COOKIES_URL, headers=ADOBE_REQ_HEADERS)

    print('Downloading products.xml\n')
    products_xml = get_products_xml()

  8. ayyybe revised this gist Mar 27, 2020. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion ccdl.py
    Original file line number Diff line number Diff line change
    @@ -260,7 +260,9 @@ def get_application_json(sapCode, version):

    while sapCode is None:
    val = input('\nPlease enter the SAP Code of the desired product (eg. PHSP for Photoshop): ')
    if products.get(val):
    if val == 'APRO':
    print('\033[1;31mAcrobat is currently broken, please sit tight while I try to find a solution.\nAll other products are functional.\033[0m')
    elif products.get(val):
    sapCode = val
    else:
    print('{} is not a valid SAP Code. Please use a value from the list above.'.format(val))
  9. ayyybe revised this gist Mar 24, 2020. 2 changed files with 2 additions and 4 deletions.
    3 changes: 1 addition & 2 deletions ccdl.command
    Original file line number Diff line number Diff line change
    @@ -38,5 +38,4 @@ fi
    clear

    echo "${CYAN}starting ccdl${RESET}"
    #python3 <(curl -s https://gist.github.com/ayyybe/a5f01c6f40020f9a7bc4939beeb2df1d/raw/ccdl.py)
    python3 <(curl -s https://pastebin.com/raw/dzYTCSHw)
    python3 <(curl -s https://gist.github.com/ayyybe/a5f01c6f40020f9a7bc4939beeb2df1d/raw/ccdl.py)
    3 changes: 1 addition & 2 deletions install.sh
    Original file line number Diff line number Diff line change
    @@ -3,8 +3,7 @@
    CYAN="$(tput bold; tput setaf 6)"
    RESET="$(tput sgr0)"

    #curl https://gist.github.com/ayyybe/a5f01c6f40020f9a7bc4939beeb2df1d/raw/ccdl.command -o "/Applications/Adobe Packager.command"
    curl https://pastebin.com/raw/0KnPC6yn -o "/Applications/Adobe Packager.command"
    curl https://gist.github.com/ayyybe/a5f01c6f40020f9a7bc4939beeb2df1d/raw/ccdl.command -o "/Applications/Adobe Packager.command"
    chmod +x "/Applications/Adobe Packager.command"

    clear
  10. ayyybe revised this gist Mar 24, 2020. 3 changed files with 135 additions and 44 deletions.
    42 changes: 42 additions & 0 deletions ccdl.command
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,42 @@
    #!/bin/bash

    CYAN="$(tput bold; tput setaf 6)"
    RESET="$(tput sgr0)"

    clear

    if command -v python3 > /dev/null 2>&1; then
    if [ $(python3 -c "print('ye')") = "ye" ]; then
    clear
    echo "${CYAN}python3 found!${RESET}"
    else
    clear
    echo "python3 found but non-functional" # probably xcode-select stub on Catalina+
    echo "${CYAN}If you received a popup asking to install some tools, please accept.${RESET}"
    read -n1 -r -p "Press [SPACE] when installation is complete, or any other key to abort." key
    echo ""
    if [ "$key" != '' ]; then
    exit
    fi
    fi
    else
    echo "${CYAN}installing python3...${RESET}"
    if ! command -v brew > /dev/null 2>&1; then
    echo | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
    fi
    brew install python
    fi

    python3 -c 'import requests' > /dev/null 2>&1
    if [ $? == 0 ]; then
    echo "${CYAN}requests found!${RESET}"
    else
    echo "${CYAN}installing requests...${RESET}"
    python3 -m pip install requests --user
    fi

    clear

    echo "${CYAN}starting ccdl${RESET}"
    #python3 <(curl -s https://gist.github.com/ayyybe/a5f01c6f40020f9a7bc4939beeb2df1d/raw/ccdl.py)
    python3 <(curl -s https://pastebin.com/raw/dzYTCSHw)
    124 changes: 80 additions & 44 deletions ccdl.py
    Original file line number Diff line number Diff line change
    @@ -2,12 +2,15 @@
    import os
    import json
    import argparse
    import urllib3
    import requests
    import shutil
    from xml.etree import ElementTree as ET
    from collections import OrderedDict
    from subprocess import Popen, PIPE

    VERSION = 2
    VERSION_STR = '0.1.1'

    INSTALL_APP_APPLE_SCRIPT = '''
    const app = Application.currentApplication()
    app.includeStandardAdditions = true
    @@ -86,7 +89,8 @@
    const installFlag = argv.indexOf('-y') > -1
    const appPath = app.pathTo(this).toString()
    const driverPath = appPath.substring(0, appPath.lastIndexOf('/')) + '/products/driver.xml'
    //const driverPath = appPath.substring(0, appPath.lastIndexOf('/')) + '/products/driver.xml'
    const driverPath = appPath + '/Contents/Resources/products/driver.xml'
    const hyperDrivePath = '/Library/Application Support/Adobe/Adobe Desktop Common/HDBox/Setup'
    if (!installFlag) {
    @@ -97,7 +101,7 @@
    cancelButton: 'Cancel'
    })
    const output = app.doShellScript(`${appPath}/Contents/MacOS/applet -y`, { administratorPrivileges: true })
    const output = app.doShellScript(`"${appPath}/Contents/MacOS/applet" -y`, { administratorPrivileges: true })
    const alert = JSON.parse(output)
    alert.params ? app.displayAlert(alert.title, alert.params) : app.displayAlert(alert.title)
    return
    @@ -163,25 +167,21 @@
    <EsdDirectory>./{sapCode}</EsdDirectory>
    </Dependency>'''

    urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
    http = urllib3.PoolManager()
    ADOBE_REQ_HEADERS = {
    'X-Adobe-App-Id': 'accc-hdcore-desktop',
    'User-Agent': 'Adobe Application Manager 2.0',
    'X-Api-Key': 'CC_HD_ESD_1_0'
    }

    def dl(filename, url):
    r = http.request('GET', url, preload_content=False, headers={
    'X-Adobe-App-Id': 'accc-hdcore-desktop',
    'User-Agent': 'Adobe Application Manager 2.0',
    'X-Api-Key': 'CC_HD_ESD_1_0'
    })

    with open(filename, 'wb') as out_file:
    shutil.copyfileobj(r, out_file)
    with requests.get(url, stream=True, headers=ADOBE_REQ_HEADERS) as r:
    with open(filename, 'wb') as f:
    shutil.copyfileobj(r.raw, f)

    def r(url):
    return http.request('GET', url, headers={
    'X-Adobe-App-Id': 'accc-hdcore-desktop',
    'User-Agent': 'Adobe Application Manager 2.0',
    'X-Api-Key': 'CC_HD_ESD_1_0'
    }).data.decode('utf-8')
    req = requests.get(url, headers=ADOBE_REQ_HEADERS)
    req.encoding = 'utf-8'
    return req.text

    def get_products_xml():
    return ET.fromstring(r(ADOBE_PRODUCTS_XML_URL))
    @@ -221,15 +221,19 @@ def get_application_json(sapCode, version):

    if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('-l', '--installLanguage', help='Language code (defaults to \'en_US\'', action='store', default='en_US')
    parser.add_argument('-l', '--installLanguage', help='Language code (eg. en_US)', action='store')
    parser.add_argument('-s', '--sapCode', help='SAP code for desired product (eg. PHSP)', action='store')
    parser.add_argument('-v', '--version', help='Version of desired product (eg. 21.0.3)', action='store')
    parser.add_argument('-d', '--destination', help='Directory to download installation files to', action='store')
    args = parser.parse_args()

    print('=================================')
    print('= Adobe macOS Package Generator =')
    print('============= 0.1.0 =============\n')
    print('============= {} =============\n'.format(VERSION_STR))

    if (not os.path.isfile('/Library/Application Support/Adobe/Adobe Desktop Common/HDBox/Setup')):
    print('Adobe HyperDrive installer not found.\nPlease make sure the Creative Cloud app is installed.')
    exit(1)

    print('Downloading products.xml\n')
    products_xml = get_products_xml()
    @@ -243,7 +247,7 @@ def get_application_json(sapCode, version):
    sapCode = None
    if (args.sapCode):
    if products.get(args.sapCode):
    print('\nUsing provided SAP Code: ' + args.sapCode)
    print('\nUsing provided SAP Code: ' + args.sapCode)
    sapCode = args.sapCode
    else:
    print('\nProvided SAP Code not found in products: ' + args.sapCode)
    @@ -266,7 +270,7 @@ def get_application_json(sapCode, version):
    version = None
    if (args.version):
    if versions.get(args.version):
    print('\nUsing provided version: ' + args.version)
    print('\nUsing provided version: ' + args.version)
    version = args.version
    else:
    print('\nProvided version not found: ' + args.version)
    @@ -286,27 +290,67 @@ def get_application_json(sapCode, version):

    print('')

    prodInfo = versions[version]
    installLanguage = args.installLanguage
    dest = args.destination or '{}_{}-{}'.format(sapCode, version, installLanguage)
    langs = [ 'en_US', 'en_GB', 'en_IL', 'en_AE', 'es_ES', 'es_MX', 'pt_BR', 'fr_FR', 'fr_CA', 'fr_MA', 'it_IT', 'de_DE', 'nl_NL', 'ru_RU', 'uk_UA', 'zh_TW', 'zh_CN', 'ja_JP', 'ko_KR', 'pl_PL', 'hu_HU', 'cs_CZ', 'tr_TR', 'sv_SE', 'nb_NO', 'fi_FI', 'da_DK' ]
    installLanguage = None
    if (args.installLanguage):
    if (args.installLanguage in langs):
    print('\nUsing provided language: ' + args.installLanguage)
    installLanguage = args.installLanguage
    else:
    print('\nProvided language not available: ' + args.installLanguage)

    if not installLanguage:
    print('Available languages: {}'.format(', '.join(langs)))
    while installLanguage is None:
    val = input('\nPlease enter the desired install language, or nothing for [en_US]: ') or 'en_US'
    if (val in langs):
    installLanguage = val
    else:
    print('{} is not available. Please use a value from the list above.'.format(val))

    dest = None
    if (args.destination):
    print('\nUsing provided destination: ' + args.destination)
    dest = args.destination
    else:
    print('\nPlease navigate to the desired downloads folder, or cancel to abort.')
    p = Popen(['/usr/bin/osascript', '-e', 'tell application (path to frontmost application as text)\nset _path to choose folder\nPOSIX path of _path\nend'], stdout=PIPE)
    dest = p.communicate()[0].decode('utf-8').strip()
    if (p.returncode != 0):
    print('Exiting...')
    exit()

    print('')


    install_app_name = 'Install {}_{}-{}.app'.format(sapCode, version, installLanguage)
    install_app_path = os.path.join(dest, install_app_name)

    print('installLanguage: ' + installLanguage)
    print('sapCode: ' + sapCode)
    print('version: ' + version)
    print('dest: ' + dest)


    #print(get_application_json('CORE', '1.0'))
    print('installLanguage: ' + installLanguage)
    print('dest: ' + install_app_path)

    prodInfo = versions[version]
    prods_to_download = [{ 'sapCode': d['sapCode'], 'version': d['version'] } for d in prodInfo['dependencies']]
    prods_to_download.insert(0, { 'sapCode': prodInfo['sapCode'], 'version': prodInfo['version'] })
    #print(prods_to_download)

    print ('\nPreparing...\n')
    print('\nCreating {}'.format(install_app_name))

    install_app_path = os.path.join(dest, 'Install {}_{}-{}.app'.format(sapCode, version, installLanguage))
    with Popen(['/usr/bin/osacompile', '-l', 'JavaScript', '-o', os.path.join(dest, install_app_path)], stdin=PIPE) as p:
    p.communicate(INSTALL_APP_APPLE_SCRIPT.encode('utf-8'))

    icon_path = '/Library/Application Support/Adobe/Adobe Desktop Common/HDBox/Install.app/Contents/Resources/app.icns'
    shutil.copyfile(icon_path, os.path.join(install_app_path, 'Contents', 'Resources', 'applet.icns'))

    products_dir = os.path.join(install_app_path, 'Contents', 'Resources', 'products')

    print('\nPreparing...\n')

    for p in prods_to_download:
    s, v = p['sapCode'], p['version']
    product_dir = os.path.join(dest, 'products', s)
    product_dir = os.path.join(products_dir, s)
    app_json_path = os.path.join(product_dir, 'application.json')

    print('[{}_{}] Downloading application.json'.format(s, v))
    @@ -327,7 +371,7 @@ def get_application_json(sapCode, version):
    for p in prods_to_download:
    s, v = p['sapCode'], p['version']
    app_json = p['application_json']
    product_dir = os.path.join(dest, 'products', s)
    product_dir = os.path.join(products_dir, s)

    print('[{}_{}] Parsing available packages'.format(s, v))
    core_pkg_count = 0
    @@ -364,16 +408,8 @@ def get_application_json(sapCode, version):
    language = installLanguage
    )

    with open(os.path.join(dest, 'products', 'driver.xml'), 'w') as f:
    with open(os.path.join(products_dir, 'driver.xml'), 'w') as f:
    f.write(driver)
    f.close()

    print('\nCreating Install.app')

    with Popen(['/usr/bin/osacompile', '-l', 'JavaScript', '-o', os.path.join(dest, 'Install.app')], stdin=PIPE) as p:
    p.communicate(INSTALL_APP_APPLE_SCRIPT.encode('utf-8'))

    iconPath = '/Library/Application Support/Adobe/Adobe Desktop Common/HDBox/Install.app/Contents/Resources/app.icns'
    shutil.copyfile(iconPath, os.path.join(dest, 'Install.app', 'Contents', 'Resources', 'applet.icns'))

    print('\nPackage successfully created. Run Install.app inside the destination folder to install.')
    print('\nPackage successfully created. Run {} to install.'.format(install_app_path))
    13 changes: 13 additions & 0 deletions install.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,13 @@
    #!/bin/bash

    CYAN="$(tput bold; tput setaf 6)"
    RESET="$(tput sgr0)"

    #curl https://gist.github.com/ayyybe/a5f01c6f40020f9a7bc4939beeb2df1d/raw/ccdl.command -o "/Applications/Adobe Packager.command"
    curl https://pastebin.com/raw/0KnPC6yn -o "/Applications/Adobe Packager.command"
    chmod +x "/Applications/Adobe Packager.command"

    clear

    echo "${CYAN}Done! You can now start /Applications/Adobe Packager.command to begin${RESET}"
    exit
  11. ayyybe revised this gist Mar 23, 2020. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion ccdl.py
    Original file line number Diff line number Diff line change
    @@ -152,6 +152,7 @@
    </ProductInfo>
    <RequestInfo>
    <InstallDir>/Applications</InstallDir>
    <InstallLanguage>{language}</InstallLanguage>
    </RequestInfo>
    </DriverInfo>
    '''
    @@ -359,7 +360,8 @@ def get_application_json(sapCode, version):
    dependencies = '\n'.join([DRIVER_XML_DEPENDENCY.format(
    sapCode = d['sapCode'],
    version = d['version']
    ) for d in prodInfo['dependencies']])
    ) for d in prodInfo['dependencies']]),
    language = installLanguage
    )

    with open(os.path.join(dest, 'products', 'driver.xml'), 'w') as f:
  12. ayyybe created this gist Mar 22, 2020.
    377 changes: 377 additions & 0 deletions ccdl.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,377 @@
    #!/usr/bin/env python3
    import os
    import json
    import argparse
    import urllib3
    import shutil
    from xml.etree import ElementTree as ET
    from collections import OrderedDict
    from subprocess import Popen, PIPE

    INSTALL_APP_APPLE_SCRIPT = '''
    const app = Application.currentApplication()
    app.includeStandardAdditions = true
    ObjC.import('Cocoa')
    ObjC.import('stdio')
    ObjC.import('stdlib')
    ObjC.registerSubclass({
    name: 'HandleDataAction',
    methods: {
    'outData:': {
    types: ['void', ['id']],
    implementation: function(sender) {
    const data = sender.object.availableData
    if (data.length !== '0') {
    const output = $.NSString.alloc.initWithDataEncoding(data, $.NSUTF8StringEncoding).js
    const res = parseOutput(output)
    if (res) {
    switch (res.type) {
    case 'progress':
    Progress.additionalDescription = `Progress: ${res.data}%`
    Progress.completedUnitCount = res.data
    break
    case 'exit':
    if (res.data === 0) {
    $.puts(JSON.stringify({ title: 'Installation succeeded' }))
    } else {
    $.puts(JSON.stringify({ title: `Failed with error code ${res.data}` }))
    }
    $.exit(0)
    break
    }
    }
    sender.object.waitForDataInBackgroundAndNotify
    } else {
    $.NSNotificationCenter.defaultCenter.removeObserver(this)
    }
    }
    }
    }
    })
    function parseOutput(output) {
    let matches
    matches = output.match(/Progress: ([0-9]{1,3})%/)
    if (matches) {
    return {
    type: 'progress',
    data: parseInt(matches[1], 10)
    }
    }
    matches = output.match(/Exit Code: ([0-9]{1,3})/)
    if (matches) {
    return {
    type: 'exit',
    data: parseInt(matches[1], 10)
    }
    }
    return false
    }
    function run() {
    const args = $.NSProcessInfo.processInfo.arguments
    const argv = []
    const argc = args.count
    for (var i = 0; i < argc; i++) {
    argv.push(ObjC.unwrap(args.objectAtIndex(i)))
    }
    delete args
    const installFlag = argv.indexOf('-y') > -1
    const appPath = app.pathTo(this).toString()
    const driverPath = appPath.substring(0, appPath.lastIndexOf('/')) + '/products/driver.xml'
    const hyperDrivePath = '/Library/Application Support/Adobe/Adobe Desktop Common/HDBox/Setup'
    if (!installFlag) {
    app.displayAlert('Adobe Package Installer', {
    message: 'Start installation now?',
    buttons: ['Cancel', 'Install'],
    defaultButton: 'Install',
    cancelButton: 'Cancel'
    })
    const output = app.doShellScript(`${appPath}/Contents/MacOS/applet -y`, { administratorPrivileges: true })
    const alert = JSON.parse(output)
    alert.params ? app.displayAlert(alert.title, alert.params) : app.displayAlert(alert.title)
    return
    }
    const stdout = $.NSPipe.pipe
    const task = $.NSTask.alloc.init
    task.executableURL = $.NSURL.alloc.initFileURLWithPath(hyperDrivePath)
    task.arguments = $(['--install=1', '--driverXML=' + driverPath])
    task.standardOutput = stdout
    const dataAction = $.HandleDataAction.alloc.init
    $.NSNotificationCenter.defaultCenter.addObserverSelectorNameObject(dataAction, 'outData:', $.NSFileHandleDataAvailableNotification, $.initialOutputFile)
    stdout.fileHandleForReading.waitForDataInBackgroundAndNotify
    let err = $.NSError.alloc.initWithDomainCodeUserInfo('', 0, '')
    const ret = task.launchAndReturnError(err)
    if (!ret) {
    $.puts(JSON.stringify({
    title: 'Error',
    params: {
    message: 'Failed to launch task: ' + err.localizedDescription.UTF8String
    }
    }))
    $.exit(0)
    }
    Progress.description = "Installing packages..."
    Progress.additionalDescription = "Preparing…"
    Progress.totalUnitCount = 100
    task.waitUntilExit
    }
    '''

    #ADOBE_PRODUCTS_XML_URL = 'https://prod-rel-ffc-ccm.oobesaas.adobe.com/adobe-ffc-external/core/v4/products/all?_type=xml&channel=ccm,sti&platform=osx10,osx10-64&productType=Desktop'
    ADOBE_PRODUCTS_XML_URL = 'https://prod-rel-ffc-ccm.oobesaas.adobe.com/adobe-ffc-external/core/v4/products/all?_type=xml&channel=ccm&platform=osx10,osx10-64&productType=Desktop'
    ADOBE_APPLICATION_JSON_URL = 'https://prod-rel-ffc-ccm.oobesaas.adobe.com/adobe-ffc-external/core/v2/applications?name={name}&version={version}&platform={platform}'

    DRIVER_XML = '''<DriverInfo>
    <ProductInfo>
    <Name>Adobe {name}</Name>
    <SAPCode>{sapCode}</SAPCode>
    <CodexVersion>{version}</CodexVersion>
    <Platform>osx10-64</Platform>
    <EsdDirectory>./{sapCode}</EsdDirectory>
    <Dependencies>
    {dependencies}
    </Dependencies>
    </ProductInfo>
    <RequestInfo>
    <InstallDir>/Applications</InstallDir>
    </RequestInfo>
    </DriverInfo>
    '''

    DRIVER_XML_DEPENDENCY = ''' <Dependency>
    <SAPCode>{sapCode}</SAPCode>
    <BaseVersion>{version}</BaseVersion>
    <EsdDirectory>./{sapCode}</EsdDirectory>
    </Dependency>'''

    urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
    http = urllib3.PoolManager()

    def dl(filename, url):
    r = http.request('GET', url, preload_content=False, headers={
    'X-Adobe-App-Id': 'accc-hdcore-desktop',
    'User-Agent': 'Adobe Application Manager 2.0',
    'X-Api-Key': 'CC_HD_ESD_1_0'
    })

    with open(filename, 'wb') as out_file:
    shutil.copyfileobj(r, out_file)

    def r(url):
    return http.request('GET', url, headers={
    'X-Adobe-App-Id': 'accc-hdcore-desktop',
    'User-Agent': 'Adobe Application Manager 2.0',
    'X-Api-Key': 'CC_HD_ESD_1_0'
    }).data.decode('utf-8')

    def get_products_xml():
    return ET.fromstring(r(ADOBE_PRODUCTS_XML_URL))

    def parse_products_xml(products_xml):
    cdn = products_xml.find('channel/cdn/secure').text
    products = {}
    for p in products_xml.findall('channel/products/product'):
    displayName = p.find('displayName').text
    sap = p.get('id')
    version = p.get('version')
    dependencies = list(p.find('platforms/platform/languageSet/dependencies'))

    if not products.get(sap):
    products[sap] = {
    'displayName': displayName,
    'sapCode': sap,
    'versions': OrderedDict()
    }

    products[sap]['versions'][version] = {
    'sapCode': sap,
    'version': version,
    'dependencies': [{
    'sapCode': d.find('sapCode').text, 'version': d.find('baseVersion').text
    } for d in dependencies]
    }

    return products, cdn

    def get_application_json(sapCode, version):
    try:
    return json.loads(r(ADOBE_APPLICATION_JSON_URL.format(name=sapCode, version=version, platform='osx10-64')))
    except json.decoder.JSONDecodeError:
    return json.loads(r(ADOBE_APPLICATION_JSON_URL.format(name=sapCode, version=version, platform='osx10')))


    if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('-l', '--installLanguage', help='Language code (defaults to \'en_US\'', action='store', default='en_US')
    parser.add_argument('-s', '--sapCode', help='SAP code for desired product (eg. PHSP)', action='store')
    parser.add_argument('-v', '--version', help='Version of desired product (eg. 21.0.3)', action='store')
    parser.add_argument('-d', '--destination', help='Directory to download installation files to', action='store')
    args = parser.parse_args()

    print('=================================')
    print('= Adobe macOS Package Generator =')
    print('============= 0.1.0 =============\n')

    print('Downloading products.xml\n')
    products_xml = get_products_xml()

    print('Parsing products.xml')
    products, cdn = parse_products_xml(products_xml)

    print('CDN: ' + cdn)
    print(str(len(products)) + ' products found:')

    sapCode = None
    if (args.sapCode):
    if products.get(args.sapCode):
    print('\nUsing provided SAP Code: ' + args.sapCode)
    sapCode = args.sapCode
    else:
    print('\nProvided SAP Code not found in products: ' + args.sapCode)

    print('')

    if not sapCode:
    for p in products.values():
    print('[{}] {}'.format(p['sapCode'], p['displayName']))

    while sapCode is None:
    val = input('\nPlease enter the SAP Code of the desired product (eg. PHSP for Photoshop): ')
    if products.get(val):
    sapCode = val
    else:
    print('{} is not a valid SAP Code. Please use a value from the list above.'.format(val))

    product = products.get(sapCode)
    versions = product['versions']
    version = None
    if (args.version):
    if versions.get(args.version):
    print('\nUsing provided version: ' + args.version)
    version = args.version
    else:
    print('\nProvided version not found: ' + args.version)

    print('')

    if not version:
    for v in reversed(versions.values()):
    print('{} {}'.format(product['displayName'], v['version']))

    while version is None:
    val = input('\nPlease enter the desired version (eg. 21.0.3): ')
    if versions.get(val):
    version = val
    else:
    print('{} is not a valid version. Please use a value from the list above.'.format(val))

    print('')

    prodInfo = versions[version]
    installLanguage = args.installLanguage
    dest = args.destination or '{}_{}-{}'.format(sapCode, version, installLanguage)

    print('installLanguage: ' + installLanguage)
    print('sapCode: ' + sapCode)
    print('version: ' + version)
    print('dest: ' + dest)


    #print(get_application_json('CORE', '1.0'))

    prods_to_download = [{ 'sapCode': d['sapCode'], 'version': d['version'] } for d in prodInfo['dependencies']]
    prods_to_download.insert(0, { 'sapCode': prodInfo['sapCode'], 'version': prodInfo['version'] })
    #print(prods_to_download)

    print ('\nPreparing...\n')

    for p in prods_to_download:
    s, v = p['sapCode'], p['version']
    product_dir = os.path.join(dest, 'products', s)
    app_json_path = os.path.join(product_dir, 'application.json')

    print('[{}_{}] Downloading application.json'.format(s, v))
    app_json = get_application_json(s, v)
    p['application_json'] = app_json

    print('[{}_{}] Creating folder for product'.format(s, v))
    os.makedirs(product_dir, exist_ok=True)

    print('[{}_{}] Saving application.json'.format(s, v))
    with open(app_json_path, 'w') as file:
    json.dump(app_json, file, separators=(',', ':'))

    print('')

    print ('Downloading...\n')

    for p in prods_to_download:
    s, v = p['sapCode'], p['version']
    app_json = p['application_json']
    product_dir = os.path.join(dest, 'products', s)

    print('[{}_{}] Parsing available packages'.format(s, v))
    core_pkg_count = 0
    noncore_pkg_count = 0
    packages = app_json['Packages']['Package']
    download_urls = []
    for pkg in packages:
    if pkg.get('Type') and pkg['Type'] == 'core':
    core_pkg_count += 1
    download_urls.append(cdn + pkg['Path'])
    else:
    if ((not pkg.get('Condition')) or installLanguage in pkg['Condition']): # TODO: actually parse `Condition` and check it properly (and maybe look for & add support for conditions other than installLanguage)
    noncore_pkg_count += 1
    download_urls.append(cdn + pkg['Path'])

    print('[{}_{}] Selected {} core packages and {} non-core packages'.format(s, v, core_pkg_count, noncore_pkg_count))


    for url in download_urls:
    name = url.split('/')[-1].split('?')[0]
    print('[{}_{}] Downloading {}'.format(s, v, name))
    dl(os.path.join(product_dir, name), url)

    print('\nGenerating driver.xml')

    driver = DRIVER_XML.format(
    name = product['displayName'],
    sapCode = prodInfo['sapCode'],
    version = prodInfo['version'],
    dependencies = '\n'.join([DRIVER_XML_DEPENDENCY.format(
    sapCode = d['sapCode'],
    version = d['version']
    ) for d in prodInfo['dependencies']])
    )

    with open(os.path.join(dest, 'products', 'driver.xml'), 'w') as f:
    f.write(driver)
    f.close()

    print('\nCreating Install.app')

    with Popen(['/usr/bin/osacompile', '-l', 'JavaScript', '-o', os.path.join(dest, 'Install.app')], stdin=PIPE) as p:
    p.communicate(INSTALL_APP_APPLE_SCRIPT.encode('utf-8'))

    iconPath = '/Library/Application Support/Adobe/Adobe Desktop Common/HDBox/Install.app/Contents/Resources/app.icns'
    shutil.copyfile(iconPath, os.path.join(dest, 'Install.app', 'Contents', 'Resources', 'applet.icns'))

    print('\nPackage successfully created. Run Install.app inside the destination folder to install.')