Skip to content

Instantly share code, notes, and snippets.

@briped
Last active October 31, 2015 21:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save briped/7744f6071bff8a7ee9cb to your computer and use it in GitHub Desktop.
Save briped/7744f6071bff8a7ee9cb to your computer and use it in GitHub Desktop.
#!/bin/bash
clear
if [ $# -lt 2 ]; then
echo "usage: $0 -i inputIpaFile -p provisioning [-c replacementIconFile] [-n 'name to display'] [-b bundleId] [-o outputIpa]" >&2
exit 1
fi
function abspath() {
python -c "import os; print os.path.abspath(\"$1\")"
}
CWD=$(pwd)
###############################################################################
## Define argument variables ##
###############################################################################
INPUT_IPA=""
PROVISIONING=""
BUNDLE_ID=""
DISPLAY_NAME=""
OUTPUT_IPA=""
NEW_ICON=""
###############################################################################
## Get arguments and set variables ##
###############################################################################
OPTIND=1
while getopts i:p:c:n:b:o: opt; do
case $opt in
i)
if [ ! -f $(abspath "$OPTARG") ]; then
echo "Input file/IPA '$OPTARG' does not exist."
exit 1
elif [ "${OPTARG##*.}" != "ipa" ]; then
echo "Input file '$OPTARG' is not an .ipa-file."
exit 1
else
INPUT_IPA=$(abspath "$OPTARG")
echo "Input IPA file : $INPUT_IPA" >&2
fi
;;
p)
if [ ! -f $(abspath "$OPTARG") ]; then
echo "Provisioning file '$OPTARG' does not exist."
exit 1
elif [ "${OPTARG##*.}" != "mobileprovision" ]; then
echo "Provisioning file '$OPTARG' is not a .mobileprovision-file."
exit 1
else
PROVISIONING=$(abspath "$OPTARG")
echo "Provisioning profile : $PROVISIONING" >&2
fi
;;
c)
if [ ! -f $(abspath "$OPTARG") ]; then
echo "Icon file '$OPTARG' does not exist."
exit 1
elif [ "${OPTARG##*.}" != "png" ]; then
echo "Provisioning file '$OPTARG' is not a .png-file."
exit 1
elif [ $(sips -g pixelWidth ${OPTARG} | tail -n1 | cut -d" " -f4) < 1024 ]; then
echo "Replacement icon should be at least 1024x1024 for resizing."
exit 1
else
NEW_ICON=$(abspath "$OPTARG")
echo "App Icon file : $NEW_ICON" >&2
fi
;;
n)
DISPLAY_NAME="$OPTARG"
echo "Bundle Display Name : $DISPLAY_NAME" >&2
;;
b)
BUNDLE_ID="$OPTARG"
echo "Bundle Identifier : $BUNDLE_ID" >&2
;;
o)
if [ -f $(abspath "$OPTARG") ]; then
echo "Output file/IPA '$OPTARG' already exist."
exit 1
elif [ "${OPTARG##*.}" != "ipa" ]; then
echo "Output file '$OPTARG' is not an .ipa-file."
exit 1
else
OUTPUT_IPA=$(abspath "$OPTARG")
echo "Output IPA file : $OUTPUT_IPA" >&2
fi
;;
\?)
echo "Invalid option : -$OPTARG" >&2
exit 1
;;
:)
echo "Option -$OPTARG requires an argument." >&2
exit 1
;;
esac
done
###############################################################################
## Prepare the work area and extract the IPA file ##
###############################################################################
# Extract name of IPA file and create a temporary WORK folder as well as UNZIPPED folder...
IPA_BNAME=$(basename "$INPUT_IPA" .ipa)
echo "IPA_BNAME : ${IPA_BNAME}"
WORK_DIR=$(abspath "${IPA_BNAME}_WORKTEMP")
echo "WORK_DIR : ${WORK_DIR}"
UNZIPPED_DIR=$(abspath "${WORK_DIR}/_UNZIPPED")
echo "UNZIPPED_DIR : ${UNZIPPED_DIR}"
# Check if the WORK folder already exists, if so remove it to ensure no conflicts, then re-create the WORK folder...
if [ -d ${WORK_DIR} ]; then
echo "Removing old WORK dir: ${WORK_DIR}"
rm -rf ${WORK_DIR}
fi
echo "Creating new WORK dir: ${WORK_DIR}"
mkdir -p "${UNZIPPED_DIR}"
unzip -q ${INPUT_IPA} -d ${UNZIPPED_DIR}
#echo
# Extract the complete path to where the files in the app...
APP_PATH="${UNZIPPED_DIR}/Payload/$(ls ${UNZIPPED_DIR}/Payload/)"
#echo "APP_PATH : $APP_PATH"
#echo
###############################################################################
## If a new icon is specified, then process this into the IPA file ##
###############################################################################
if [ "${NEW_ICON}" != "" ]; then
# Read the icon names from Info.plist into an array...
CFBundleIcons=( $(/usr/libexec/PlistBuddy -c 'Print :CFBundleIcons' "${APP_PATH}/Info.plist" | grep --invert-match '[{}]' | tr -d '[ ]') )
# Read the iPad icon names from Info.plist into an array...
CFBundleIconsIpad=( $(/usr/libexec/PlistBuddy -c 'Print :CFBundleIcons~ipad' "${APP_PATH}/Info.plist" | grep --invert-match '[{}]' | tr -d '[ ]') )
# Merge the two icon arrays into one array...
CFBundleIconsAll=( "${CFBundleIcons[@]}" "${CFBundleIconsIpad[@]}" )
# Remove duplicate icon names from the merged array...
CFBundleIconsUnique=( $(printf '%s\n' "${CFBundleIconsAll[@]}" | sort -u) )
# Loop through the icon names from Info.plist...
for icoName in "${CFBundleIconsUnique[@]}"; do
icoNoExt=${icoName%.*}
for icoFile in "${APP_PATH}/${icoNoExt}"*; do
icoBasename=$(basename "${icoFile}")
icoOrgUncrushed="${WORK_DIR}/orgUncrushed_${icoBasename}"
icoNewResized="${WORK_DIR}/newResized_${icoBasename}"
icoNewCrushed="${WORK_DIR}/newCrushed_${icoBasename}"
# Uncrush original icon-file...
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/pngcrush -revert-iphone-optimizations -q "${icoFile}" "${icoOrgUncrushed}"
# Get dimension of original icon-file...
icoWidth=$(sips -g pixelWidth ${icoOrgUncrushed} | tail -n1 | cut -d" " -f4)
# Resize NEW_ICON to same dimensions as original icon-file...
sips --resampleWidth ${icoWidth} "${NEW_ICON}" --out "${icoNewResized}" &> /dev/null
# Crush the resized icon-file...
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/pngcrush -iphone -q "${icoNewResized}" "${icoNewCrushed}"
# Replace the original icon-file with the resized and crushed NEW_ICON-file...
mv -f "${icoNewCrushed}" "${icoFile}"
# Remove temporary icon-files...
rm -f ${icoOrgUncrushed}
rm -f ${icoNewResized}
done
done
fi
###############################################################################
## If a display name is specified, process this into the IPA file ##
###############################################################################
if [ "${DISPLAY_NAME}" != "" ]; then
#echo "Set CFBundleDisplayName to :"${DISPLAY_NAME}
/usr/libexec/PlistBuddy -c "Set :CFBundleDisplayName $DISPLAY_NAME" "${APP_PATH}/Info.plist"
fi
CFBundleDisplayName=$(/usr/libexec/PlistBuddy -c 'Print :CFBundleDisplayName' "${APP_PATH}/Info.plist")
###############################################################################
## If a the application-identifier in the provisioning file is ##
## different than the IPA, change the CFBundleIdentifier in the IPA ##
###############################################################################
CFBundleIdentifier=$(/usr/libexec/PlistBuddy -c 'Print :CFBundleIdentifier' "${APP_PATH}/Info.plist" | grep --invert-match '[{}]' | tr -d '[ ]')
provBundleIdentifier=$(egrep -a -A 2 application-identifier ${PROVISIONING} | grep string | sed -e 's/<string>//' -e 's/<\/string>//' -e 's/\s+//' | awk '{split($0,a,"."); i = length(a); for(ix=2; ix <= i;ix++){ s=s a[ix]; if(i!=ix){s=s "."};} print s;}')
if [ "${CFBundleIdentifier}" != "${provBundleIdentifier}" ]; then
#echo "Set CFBundleIdentifier to :"${provBundleIdentifier}
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier ${provBundleIdentifier}" "${APP_PATH}/Info.plist"
CFBundleIdentifier="${provBundleIdentifier}"
fi
#NEW_TEAM_ID=$(egrep -a -A 2 TeamIdentifier ${PROVISIONING} | grep string | sed -e 's/<string>//' -e 's/<\/string>//' -e 's/ //')
#echo "NEW_TEAM_ID : "${NEW_TEAM_ID}
#APP_ID=${NEW_TEAM_ID}.${NEW_BUNDLE_ID}
#echo $APP_ID
if [ "${OUTPUT_IPA}" == "" ]; then
CFBundleShortVersionString=$(/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' "${APP_PATH}/Info.plist")
if [ "${NEW_ICON}" != "" ]; then
iconString="_NewIcon"
fi
OUTPUT_IPA="${WORK_DIR}/${CFBundleDisplayName}_${CFBundleShortVersionString}${iconString}.ipa"
echo "OUTPUT_IPA : ${OUTPUT_IPA}"
fi
#Zip folder into IPA file
#echo "Zip app folder and rename to IPA file: "${OUTPUT_IPA}
cd ${UNZIPPED_DIR}
# zipping
zip -qr "${OUTPUT_IPA}" Payload/
cd ${CWD}
#MDX_Toolkits=( $(mdfind "kMDItemKind==Application&&kMDItemDisplayName=='MDX Toolkit'") )
#for Toolkit in "${MDX_Toolkits[@]}"; do
# echo "TOOLKIT: ${Toolkit}"
# mdxV=$(/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' "${Toolkit}/Contents/Info.plist")
# mdxB=$(/usr/libexec/PlistBuddy -c 'Print :CFBundleVersion' "${Toolkit}/Contents/Info.plist")
# mdxVersion="${mdxV}.${mdxB}"
# echo "MDX Version: ${mdxVersion}"
#done
# This should be done better, as there could be multiple codesigning certificates. Best option would be to show a selection screen...
codeSigningIdentity="$(/usr/bin/security find-identity -p codesigning -v | grep "1).*iPhone Distribution: " | cut -d'"' -f2)"
MDX_Toolkit="/Applications/Citrix/MDXToolkit"
MDX_VERSION=$(/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' "${MDX_Toolkit}/MDX Toolkit.app/Contents/Info.plist")
MDX_BUILD=$(/usr/libexec/PlistBuddy -c 'Print :CFBundleVersion' "${MDX_Toolkit}/MDX Toolkit.app/Contents/Info.plist")
MDX_VERSION_LONG="${MDX_VERSION}.${MDX_BUILD}"
OUTPUT_MDX="${OUTPUT_IPA%.*}_iOS_MDXv${MDX_VERSION_LONG}.mdx"
echo "OUTPUT_MDX : ${OUTPUT_MDX}"
/Applications/Citrix/MDXToolkit/CGAppCLPrepTool Wrap \
-in "${INPUT_IPA}" \
-out "${OUTPUT_MDX}" \
-Cert "${codeSigningIdentity}" \
-Profile "${PROVISIONING}" \
-appName "${CFBundleDisplayName}" \
-appDesc "${CFBundleDisplayName} v${CFBundleShortVersionString}. MDX v${MDX_VERSION_LONG}." \
-policyXML "policy_metadata.xml" \
-bundleID "${CFBundleIdentifier}" \
-logWriteLevel 4 &> /dev/null
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment