# 按照 BundleID 查找匹配的描述文件 search_mobileprovision() { # 如果指定了描述文件目录 if [[ -d"${MOBILEPROVISION_PATH}" ]]; then # echo MOBILEPROVISION_PATH "${MOBILEPROVISION_PATH}" | subl # 遍历指定目录下所有描述文件 local mobileprovision_files mobileprovision_files=$(find "${MOBILEPROVISION_PATH}"-type f -name'*.mobileprovision') local old_ifs=${IFS} IFS=$'\n' local mobileprovision_files_array mobileprovision_files_array=(${mobileprovision_files}) IFS=${old_ifs} # 判断是否找到了内容 if [[ "0" -lt"${#mobileprovision_files_array[@]}" ]]; then # 遍历处理 for provision_file in"${mobileprovision_files_array[@]}"; do # 获取描述文件的 BundleID local bundle_id bundle_id=$(extract_bundle_id "${provision_file}") local is_inhouse_profile is_inhouse_profile=$(extract_is_inhouse_profile "${provision_file}") # 判断是否是 In-House 发布证书 if [[ "${is_inhouse_profile}" != "1" ]]; then continue fi # 判断是否与传入的 BundleID 匹配 if [[ "${bundle_id}" == "$1" ]]; then echo"${provision_file}" break fi done fi
# 删除签名 remove_code_signature() { local code_signature_path="$1/_CodeSignature" if [[ -d"${code_signature_path}" ]]; then rm-rf"${code_signature_path}" fi }
# 代码签名 sign_code() { local sign_path="$1" # 删除原签名 remove_code_signature "${sign_path}" # 获取旧的描述文件 local old_profile="${sign_path}/embedded.mobileprovision" # 获取原来的 BundleID local bundle_id bundle_id=$(extract_bundle_id "${old_profile}") # 根据 BundleID 在指定目录中查找新的描述文件 local new_profile # 如果命令行中明确指定了描述文件 if [[ -n"${MOBILEPROVISION_FILE}" ]]; then new_profile="${MOBILEPROVISION_FILE}" # 如果指定的描述文件不存在 if [[ ! -f"${new_profile}" ]]; then echo Provision profile "${new_profile}" not exists. exit1 fi elif [[ -n"${MOBILEPROVISION_PATH}" ]]; then # 如果命令行中没有明确指定描述文件,但明确指定了描述文件的搜索位置 # 则在指定路径中搜索 new_profile=$(search_mobileprovision "${bundle_id}") # 判断搜索描述文件的结果 if [[ ! -f"${new_profile}" ]]; then echo Provision profile not found. exit1 fi fi
# 如果找到了新的描述文件则替换旧的 if [[ -n"${new_profile}" ]]; then cp"${new_profile}""${old_profile}" else # 如果没找到新的描述文件则用旧的 new_profile="${old_profile}" fi
# 从 mobileprovision 中提取 指定字段内容 extract_field_content_from_plist_content() { local plist_content="$1" local path="$2" local content content=$(echo"$plist_content" | plutil -extract"${path}" xml1 -o - -- -) if [[ "0" -ne"$?" ]]; then content='""' fi echo"$content" }
# 提取数组字段值,以 JSON 数组形式展示 extract_field_value_array_from_plist_content() { local plist_content="$1" local path="$2" local val val=$(extract_field_content_from_plist_content "${plist_content}""${path}" | plutil -convert json -o - -- -) if [[ "0" -ne"$?" ]]; then val='[]' fi eval "echo \"${val}\"" }
# 从 mobileprovision 中提取 指定字段值 extract_field_value_from_plist_content() { local plist_content="$1" local path="$2" local val val=$(extract_field_content_from_plist_content "${plist_content}""${path}" | plutil -p -- -) eval "echo \"${val}\"" }
# 获取 ipa 信息 ipa_basic_info() {
local ipa_file="$1" local INFO_PLIST INFO_PLIST=$(unzip -p"$ipa_file""Payload/*.app/Info.plist" | plutil -convert xml1 -o - -- -)
# Name local bundle_name bundle_name=$(extract_field_value_from_plist_content "$INFO_PLIST" CFBundleName) local display_name display_name=$(extract_field_value_from_plist_content "$INFO_PLIST" CFBundleDisplayName) echo Name: ^"$bundle_name($display_name)"
# Version local short_ver short_ver=$(extract_field_value_from_plist_content "$INFO_PLIST" CFBundleShortVersionString) local bundle_ver bundle_ver=$(extract_field_value_from_plist_content "$INFO_PLIST" CFBundleVersion) echo Version: ^"$short_ver($bundle_ver)"
# Xcode local xcode_ver xcode_ver=$(extract_field_value_from_plist_content "$INFO_PLIST" DTXcode) local xcode_build xcode_build=$(extract_field_value_from_plist_content "$INFO_PLIST" DTXcodeBuild) echo Xcode: ^"$xcode_ver($xcode_build)"
# Machine local machine_os_build machine_os_build=$(extract_field_value_from_plist_content "$INFO_PLIST" BuildMachineOSBuild) echo Build Machine OS Build: ^$machine_os_build
local back_modes back_modes=$(extract_field_value_array_from_plist_content "$INFO_PLIST" UIBackgroundModes) eval "echo Background Modes: ^\"$back_modes\""
}
# 获取 provision 信息 provision_info() { local ipa_file="$1" local PLIST_IN_MOBILEPROVISION PLIST_IN_MOBILEPROVISION=$(unzip -p"$ipa_file""Payload/*.app/embedded.mobileprovision" | security cms -D)
local provision_app_id_name provision_app_id_name=$(extract_field_value_from_plist_content "$PLIST_IN_MOBILEPROVISION" AppIDName) echo App ID Name: ^$provision_app_id_name
local provision_name provision_name=$(extract_field_value_from_plist_content "$PLIST_IN_MOBILEPROVISION" Name) echo Name: ^$provision_name
local provision_platform provision_platform=$(extract_field_value_array_from_plist_content "$PLIST_IN_MOBILEPROVISION" Platform) echo Platform: ^$provision_platform
local provision_is_xcode_managed provision_is_xcode_managed=$(extract_field_value_from_plist_content "$PLIST_IN_MOBILEPROVISION" IsXcodeManaged) echo Is Xcode Managed: ^$provision_is_xcode_managed
local provision_creation_date provision_creation_date=$(extract_field_value_from_plist_content "$PLIST_IN_MOBILEPROVISION" CreationDate) echo Creation Date: ^$provision_creation_date
local provision_expiration_date provision_expiration_date=$(extract_field_value_from_plist_content "$PLIST_IN_MOBILEPROVISION" ExpirationDate) echo Expiration Date: ^$provision_expiration_date
local provision_team_identifier provision_team_identifier=$(extract_field_value_from_plist_content "$PLIST_IN_MOBILEPROVISION"'Entitlements.com\.apple\.developer\.team-identifier') echo Team Identifier: ^$provision_team_identifier
local provision_team_name provision_team_name=$(extract_field_value_from_plist_content "$PLIST_IN_MOBILEPROVISION" TeamName) echo Team Name: ^$provision_team_name }
# 获取 证书 信息 certificate_info() { local ipa_file="$1" local PLIST_IN_MOBILEPROVISION PLIST_IN_MOBILEPROVISION=$(extract_plist_in_embedded_mobileprovision "$ipa_file")
# 第一个证书的 Base64 编码 local dev_cer0 dev_cer0=$(extract_field_content_from_plist_content "$PLIST_IN_MOBILEPROVISION"'DeveloperCertificates.0' | tr -d'\n' | sed -r's/.*<data>(.*)<\/data>.*/\1/g')
# 起始有效期 local cert_start_date cert_start_date=$(echo$dev_cer0 | base64 --decode | openssl x509 -inform der -noout-startdate | sed -r's/notBefore=(.*)/\1/g') echo Not Before: ^$cert_start_date
# 结束有效期 local cert_end_date cert_end_date=$(echo$dev_cer0 | base64 --decode | openssl x509 -inform der -noout-enddate | sed -r's/notAfter=(.*)/\1/g') echo Not After: ^$cert_end_date
# 主题 local cert_subject cert_subject=$(echo$dev_cer0 | base64 --decode | openssl x509 -inform der -noout-subject)
# 从 主题 中提取 UID local cert_uid cert_uid=$(echo"$cert_subject" | sed -r's/.*UID=(.*)?\/CN=.*/\1/g') echo UID: ^$cert_uid
# 从 主题 中提取 CN local cert_cn cert_cn=$(echo"$cert_subject" | sed -r's/.*CN=(.*)?\/OU=.*/\1/g') echo Common Name: ^$cert_cn }
# 没有指定 ipa 文件 if [[ -z"${IPA_FILE}" ]]; then cat << EOF
Usage: $(basename "$0") [options] <ipa_file>
Options: -i Show ipa information only. -c Choose a certificate for signing. -e Extract 'plist' content from 'embedded.mobileprovision' file. -p <provisioning_profile_file> Choose a provision profile for signing. -s <provisioning_profiles_folder> Specify the directory to search for the mobile provision profile. -v <version> Specify the 'Bundle version string (CFBundleShortVersionString)' of the ipa file. -b <build_version> Specify the 'Bundle version (CFBundleVersion)' of the ipa file.
EOF exit fi
# ipa 文件不存在 if [[ ! -f"${IPA_FILE}" ]]; then echo File not exists. exit1 fi
# 如果存在扩展目录则处理 if [[ -d"${plugins_path}" ]]; then # 列出扩展 plugins=$(find "${plugins_path}"-type d -name'*.appex') old_ifs=${IFS} IFS=$'\n' plugins=(${plugins}) IFS=${old_ifs} # 遍历扩展,为每个扩展签名 for plugin in"${plugins[@]}"; do echo echo"Signing extension \"${plugin}\"..." sign_code "${plugin}" done fi
# 指定主程序版本 echo echo-n'Specify the main app version:'
# 指定 Version if [[ -n"${IPA_SHORT_VERSION}" ]]; then echo echo" Version(CFBundleShortVersionString)=${IPA_SHORT_VERSION}" set_short_version "${app_path}/Info.plist""${IPA_SHORT_VERSION}" else echo' [N/A]' fi
# 指定 Build if [[ -n"${IPA_BUILD_VERSION}" ]]; then echo" Build(CFBundleVersion)=${IPA_BUILD_VERSION}" set_build_version "${app_path}/Info.plist""${IPA_BUILD_VERSION}" fi